import { type ImagePart, type FilePart } from "smoltalk"; /** * Reply attachments: the channel by which a TOOL hands images back to the * model. `attachToReply` (std::thread) queues onto the calling tool * invocation's branch-local stack via `StateStack.queueReplyAttachment` * (serialized — survives a mid-round interrupt); the tool loop drains the * branch queue at invocation completion, harvests it here into the prompt's * `runnerState` (per-llm()-call, serialized, fork-safe), and appends a * marker to that tool's result text; after the full tool round the loop * injects ONE labeled user message built here. See * docs/superpowers/specs/2026-07-02-tool-reply-attachments-design.md and * docs/dev/reply-attachments.md. * * The marker strings below are MODEL-FACING API — tests pin them; do not * reword casually. (They contain em-dashes, not hyphens.) */ /** A tool-produced attachment is exactly a smoltalk user-content image or * file part — the same shapes `image()` / `file()` (std::thread) build. */ export type ReplyAttachmentPart = ImagePart | FilePart; export type HarvestedReplyAttachment = { id: string; toolName: string; part: ReplyAttachmentPart; }; /** Gate each drained entry, move survivors into `runnerState[BUFFER_KEY]`, * and return the marker text to append to that tool's result (empty string * when nothing was queued). Runs inside the idempotent per-tool invoke step * of the tool loop, so it executes exactly once per tool call, including * across interrupt/resume. */ export declare function harvestReplyAttachments(args: { queued: ReplyAttachmentPart[]; runnerState: Record; model: unknown; toolName: string; }): string; /** Append the harvest marker to a (possibly non-string) capped tool * result. Kept here so the "" no-marker sentinel never leaks decisions * into prompt.ts — the caller composes unconditionally. */ export declare function appendReplyMarker(cappedResult: unknown, marker: string, stringify: (value: unknown) => string): unknown; /** Build the parts array for the injected user message: one label text part * immediately before each attachment part. Path sources are inlined to * base64 HERE (not at send) so the persistent thread never re-reads a file * that may later be deleted or edited; url/base64/provider sources pass * through. Never throws: an unreadable path becomes a text part naming the * failure. */ export declare function buildReplyUserMessage(harvested: HarvestedReplyAttachment[]): unknown[];