feat(fs): add a minimal read_image tool over the attachment and fs seams
The model reads a PNG/JPEG/WebP/GIF file, the bytes commit through the durable attachment lifecycle, and the tool result carries the real ImageBlock so the image enters context from the next request onward. FileSystem gains a bounded readBytes primitive (local + E2B providers); registration is conditional on the attachment store, and a strict execution gate refuses routes that do not declare image input, so a text route's durable history stays free of image blocks. llm-replay models may declare inputModalities, letting keyless ACP snapshots pin both the sha256-referenced success and the verbatim refusal. Supersedes the withdrawn route-scoped design of PR #598; the decision record is .agents/notes/implemented/feature/2026-08-10-minimal-read-image-tool.md.
This commit is contained in:
@@ -38,6 +38,8 @@ const WORKSPACE_CONTEXT_CONFIG = fileURLToPath(new URL('../workspace-context.cor
|
||||
const ADVANCED_CONFIG = fileURLToPath(new URL('../advanced.cordis.yml', import.meta.url))
|
||||
const FS_CONFIG = fileURLToPath(new URL('../fs.cordis.yml', import.meta.url))
|
||||
const SESSION_QUERY_CONFIG = fileURLToPath(new URL('../session-query.cordis.yml', import.meta.url))
|
||||
const IMAGE_CONFIG = fileURLToPath(new URL('../image.cordis.yml', import.meta.url))
|
||||
const IMAGE_TEXT_ROUTE_CONFIG = fileURLToPath(new URL('../image-text-route.cordis.yml', import.meta.url))
|
||||
const PTY_CONFIG = fileURLToPath(new URL('../pty.cordis.yml', import.meta.url))
|
||||
const DEPTH_TWO_CONFIG = fileURLToPath(new URL('../depth-two.cordis.yml', import.meta.url))
|
||||
const CHILD_QUESTION_CONFIG = fileURLToPath(new URL('../child-question.cordis.yml', import.meta.url))
|
||||
@@ -153,6 +155,30 @@ const SCENARIOS: Scenario[] = [
|
||||
configPath: SESSION_QUERY_CONFIG,
|
||||
posixOnly: true,
|
||||
},
|
||||
// Authored keyless replays through the assembled app: the replay catalog
|
||||
// declares flash image-capable (success) or text-only (refusal), and the
|
||||
// real read_image tool executes against the workspace fixture and the real
|
||||
// attachment store. Both boot the same composed header (the tool registers
|
||||
// with the attachment store, independent of route), so they share one class.
|
||||
{
|
||||
name: 'read-image',
|
||||
hasModelTurn: true,
|
||||
recorded: false,
|
||||
pinsHeader: true,
|
||||
headerClass: 'image',
|
||||
// The overlay adds no prompt section (read_image carries no guidance), so
|
||||
// the composed system prompt is byte-identical to the default class; only
|
||||
// the tool-schema sidecar is class-specific.
|
||||
systemPromptSource: 'text-turn',
|
||||
configPath: IMAGE_CONFIG,
|
||||
},
|
||||
{
|
||||
name: 'read-image-text-route',
|
||||
hasModelTurn: true,
|
||||
recorded: false,
|
||||
headerClass: 'image',
|
||||
configPath: IMAGE_TEXT_ROUTE_CONFIG,
|
||||
},
|
||||
{
|
||||
name: 'pty-tools',
|
||||
hasModelTurn: true,
|
||||
|
||||
Reference in New Issue
Block a user