π File detail
utils/pdfUtils.ts
π§© .tsπ 71 linesπΎ 2,190 bytesπ text
β Back to All Filesπ― Use case
This file lives under βutils/β, which covers cross-cutting helpers (shell, tempfiles, settings, messages, process input, β¦). On the API surface it exposes DOCUMENT_EXTENSIONS, parsePDFPageRange, isPDFSupported, and isPDFExtension β mainly functions, hooks, or classes. It composes internal code from model (relative imports).
Generated from folder role, exports, dependency roots, and inline comments β not hand-reviewed for every path.
π§ Inline summary
import { getMainLoopModel } from './model/model.js' // Document extensions that are handled specially export const DOCUMENT_EXTENSIONS = new Set(['pdf'])
π€ Exports (heuristic)
DOCUMENT_EXTENSIONSparsePDFPageRangeisPDFSupportedisPDFExtension
π₯οΈ Source preview
import { getMainLoopModel } from './model/model.js'
// Document extensions that are handled specially
export const DOCUMENT_EXTENSIONS = new Set(['pdf'])
/**
* Parse a page range string into firstPage/lastPage numbers.
* Supported formats:
* - "5" β { firstPage: 5, lastPage: 5 }
* - "1-10" β { firstPage: 1, lastPage: 10 }
* - "3-" β { firstPage: 3, lastPage: Infinity }
*
* Returns null on invalid input (non-numeric, zero, inverted range).
* Pages are 1-indexed.
*/
export function parsePDFPageRange(
pages: string,
): { firstPage: number; lastPage: number } | null {
const trimmed = pages.trim()
if (!trimmed) {
return null
}
// "N-" open-ended range
if (trimmed.endsWith('-')) {
const first = parseInt(trimmed.slice(0, -1), 10)
if (isNaN(first) || first < 1) {
return null
}
return { firstPage: first, lastPage: Infinity }
}
const dashIndex = trimmed.indexOf('-')
if (dashIndex === -1) {
// Single page: "5"
const page = parseInt(trimmed, 10)
if (isNaN(page) || page < 1) {
return null
}
return { firstPage: page, lastPage: page }
}
// Range: "1-10"
const first = parseInt(trimmed.slice(0, dashIndex), 10)
const last = parseInt(trimmed.slice(dashIndex + 1), 10)
if (isNaN(first) || isNaN(last) || first < 1 || last < 1 || last < first) {
return null
}
return { firstPage: first, lastPage: last }
}
/**
* Check if PDF reading is supported with the current model.
* PDF document blocks work on all providers (1P, Vertex, Bedrock, Foundry).
* Haiku 3 is the only remaining model that predates PDF support; users on
* it fall back to the page-extraction path (poppler-utils). Substring match
* covers all provider ID formats (Bedrock prefixes, Vertex @-dates).
*/
export function isPDFSupported(): boolean {
return !getMainLoopModel().toLowerCase().includes('claude-3-haiku')
}
/**
* Check if a file extension is a PDF document.
* @param ext File extension (with or without leading dot)
*/
export function isPDFExtension(ext: string): boolean {
const normalized = ext.startsWith('.') ? ext.slice(1) : ext
return DOCUMENT_EXTENSIONS.has(normalized.toLowerCase())
}