@sema-agent/core
Version:
Stateless, task-oriented AI agent core
48 lines (47 loc) • 3.77 kB
TypeScript
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>;