@sema-agent/core
Version:
Stateless, task-oriented AI agent core
53 lines (52 loc) • 3.06 kB
TypeScript
/**
* Media degradation shared by the two message assemblers (anthropic.ts / openai.ts).
*
* Both lanes answer the same two questions on every request — "may this model see images?" and
* "what do I say when a media block cannot ride along?" — from ONE construction point: a capability
* rule that drifts between lanes is a silent per-provider behavior difference, and a placeholder
* sentence that drifts is a string consumers grep for.
*/
import type { Model } from "../internal/llm.js";
/**
* Whether the SERVING model accepts image input (`Model.input` contains "image").
*
* An ABSENT `input` is deliberately permissive (vision on): the field is caller-supplied metadata,
* and treating "not declared" as "not capable" would silently downgrade every caller who never
* filled it in. A caller that genuinely serves a text-only endpoint declares `input: ["text"]` and
* gets the placeholder path — the case a text-only API rejects with a hard 400 on an image part.
*/
export declare function modelSupportsVision(model?: Model): boolean;
/** Placeholder for an image block dropped because the serving model declares no image input. */
export declare const IMAGE_OMITTED_NO_VISION = "[image omitted: the serving model does not support image input]";
/** {@link IMAGE_OMITTED_NO_VISION}, counted — a batch of dropped images states how many were lost. */
export declare function imagesOmittedNoVisionNote(count: number): string;
/** An image content block carrying both wire fields — the only shape any lane can actually send. */
export interface SendableImage {
type: "image";
data: string;
mimeType: string;
}
/**
* The blocks that would ride as REAL image media: `type:"image"` with both wire fields present.
*
* One predicate for both lanes and for both of its uses — deciding what to SEND and counting what was
* DROPPED. A block missing `data`/`mimeType` is discarded by every assembler on every path, error or
* not, so an omission note that counted it would blame the error for a loss it did not cause.
*/
export declare function sendableImages(blocks: readonly unknown[]): SendableImage[];
/**
* Disclosure for media blocks stripped out of an ERROR tool result.
*
* The stripping itself is mandatory on both lanes and is NOT a choice this note softens: the
* Anthropic API rejects an image inside an `is_error` tool_result outright (CC messages.ts, image-in-error rejection —
* a passthrough attempt 400s the request forever, not once), and the OpenAI-compatible `tool` role
* carries text only, with the synthetic image-carrier user message deliberately not built for error
* results. What the note fixes is the SILENCE: an error whose attached evidence simply vanished
* reads to the model as an error that never had any, so it cannot ask for the evidence another way.
*
* @returns the note, or `undefined` when there is nothing to disclose (no media was dropped).
*/
export declare function errorResultMediaNote(counts: {
images: number;
documents: number;
}): string | undefined;