UNPKG

@sema-agent/core

Version:

Stateless, task-oriented AI agent core

48 lines (47 loc) • 3.77 kB
import type { DocumentContent, ImageContent, TextContent } from "../../internal/llm.js"; import type { ExecutionEnv } from "../../internal/harness-types.js"; import { type PdfModelCapabilities } from "./pdf.js"; import { type ReadImageDownsamplerOption } from "./fs-shared.js"; import { type ReminderDisclosureEffects } from "../../core/reminder-disclosure.js"; /** The reader's disclosure state, threaded into the PDF TEXT legs (the two `pdftotext` extraction arms — * the only PDF returns with a model-facing text projection of the document; the native document block and * rendered page images have no text to scan). Shares the reader's throttle windows so a PDF and its text * read dedup on the same file key. The windows are READ here and never advanced: each planned * disclosure's effects are pushed onto `effects`, and the reader commits them with the delivery. */ export interface PdfReminderDisclosure { mark: string | undefined; windows: Map<string, number>; key: string; effects: ReminderDisclosureEffects[]; } export { pdfModelCapabilitiesOf, type PdfModelCapabilities } from "./pdf.js"; /** What the Read tool's PDF pipeline returns (document block, or rendered page images, or an error string). */ type ReadPdfReturn = string | { content: Array<TextContent | ImageContent | DocumentContent>; details: unknown; }; /** * PDF read pipeline (CC FileReadTool parity — mechanism + limits in fs/pdf.ts): * - no `pages` → whole file as a native `document` block, gated at ≤{@link PDF_TARGET_RAW_SIZE} raw and * ≤{@link PDF_INLINE_PAGE_THRESHOLD} pages (page count via `pdfinfo`, byte-scan fallback; unknown = fail-open, * CC-identical — the size gate still bounds the request); * - `pages` "F-L" → poppler `pdftoppm` renders the range as JPEG page images (CC-identical mechanism; the * downsampler seam then applies the same pipeline as the Read image branch). poppler absent → HONEST * degradation with the working alternative, never a fake success. * Wire discipline: the base64 payload rides `details.file` only while ≤48K chars (same OMIT rule as the * image variant — a bigger card would be dropped whole by the card projector's 4×cap and blind the shell). * The budget rule only means anything while `"document"` is registered on `CC_DETAIL_TYPES`: without * that word every `document` card, sized or not, is dropped at the gate, which makes the 48K rule dead * code and the pages/fallback-level disclosure invisible to a host. * * Degradation chain (the brain-level placeholder is NOT the end state): when the SERVING model * cannot take a native document block (`caps.document === false` — e.g. any openai-compatible API), the * whole-PDF path degrades IN THE TOOL (the only layer holding env.exec), best first: * 1. `pdftotext -layout` text extraction → the content arrives as TEXT (Read byte-cap discipline applies); * 2. pdftotext absent/failed + the model has vision → render the first {@link PDF_FALLBACK_RENDER_PAGES} * pages via the existing `pdftoppm` pipeline (note directs `pages` for more); * 3. honest placeholder explaining WHY levels 1–2 did not run + the Bash self-help. * Every degraded return carries `details.fallback = { level, reason }` (telemetry on the structured frame). * `caps` absent ⇒ fully capable (native document block; the brain placeholder still guards). */ export declare function readPdfFile(env: ExecutionEnv, path: string, key: string, pages: string | undefined, signal: AbortSignal | undefined, downsamplerOpt: ReadImageDownsamplerOption, cwd: string, preRead?: Uint8Array, caps?: PdfModelCapabilities, readDeny?: import("./read-deny.js").ReadDenyMatcher, disclosure?: PdfReminderDisclosure): Promise<ReadPdfReturn>;