- Check pauseForApproval BEFORE createApprovalRequest so a gate with create-but-no-pause default-denies without orphaning a pending approval record (greptile P1). - prompt-builder: whitespace-only prompt yields no text block (code/comment mismatch) + regression test. - onLoad logs arg count, not raw args (args can carry inline tokens). - Document that engine-driven session resume (loadAcpSession) is deferred v1. - Strengthen tests: eviction path observed end-to-end, id-normalization asserted via differing raw forms, loadSession receives the normalized id. Skipped with reasons (recorded in review thread reply): exports-to-dist, README title (package name is correct), Surface Enumeration boilerplate, heavy-lift streaming-read/path-jail rework, and two suggestions that would weaken the default-deny floor. 182 tests green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
50 lines
1.6 KiB
TypeScript
50 lines
1.6 KiB
TypeScript
// Builds ACP `ContentBlock[]` from a Fusion prompt.
|
|
//
|
|
// U3 core path: a plain string prompt becomes a single `{ type: "text", text }`
|
|
// block. The runtime may later pass structured content (e.g. an attached image);
|
|
// when present we emit the matching block. Keep this small and pure.
|
|
|
|
import type { ContentBlock } from "@agentclientprotocol/sdk";
|
|
|
|
/** Optional structured content the runtime may attach alongside the text prompt. */
|
|
export interface PromptImage {
|
|
/** Base64-encoded image data (no data: prefix). */
|
|
data: string;
|
|
/** MIME type, e.g. "image/png". */
|
|
mimeType: string;
|
|
/** Optional source URI for the image. */
|
|
uri?: string;
|
|
}
|
|
|
|
export interface BuildPromptOptions {
|
|
/** Image content to append as image block(s) after the text. */
|
|
images?: PromptImage[];
|
|
}
|
|
|
|
/**
|
|
* Build the ACP prompt content blocks for a turn.
|
|
*
|
|
* A non-empty string yields one text block. An empty/whitespace-only string
|
|
* yields no text block (but any attached images are still included), so we never
|
|
* send a meaningless empty text block. Images, when supplied, are appended as
|
|
* `image` blocks (passthrough — KTD ContentBlock image variant).
|
|
*/
|
|
export function buildPromptBlocks(prompt: string, opts?: BuildPromptOptions): ContentBlock[] {
|
|
const blocks: ContentBlock[] = [];
|
|
|
|
if (typeof prompt === "string" && prompt.trim().length > 0) {
|
|
blocks.push({ type: "text", text: prompt });
|
|
}
|
|
|
|
for (const image of opts?.images ?? []) {
|
|
blocks.push({
|
|
type: "image",
|
|
data: image.data,
|
|
mimeType: image.mimeType,
|
|
...(image.uri ? { uri: image.uri } : {}),
|
|
});
|
|
}
|
|
|
|
return blocks;
|
|
}
|