@warble/claude-agent-sdk 0.10.0 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -9,10 +9,11 @@ import {
9
9
  discoverClaudeModels,
10
10
  emitAgentModule,
11
11
  parseRenderFlavor,
12
+ parseSlotFlags,
12
13
  prepareDispatch,
13
14
  prepareDisplayManifest,
14
15
  runDispatch
15
- } from "./chunk-Y5BDZDXF.js";
16
+ } from "./chunk-7XQ5F6FM.js";
16
17
 
17
18
  // src/cli.ts
18
19
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
@@ -21,6 +22,13 @@ import { dirname, join, resolve } from "path";
21
22
  import { createInterface } from "readline";
22
23
  import { parseArgs } from "util";
23
24
  import { fileURLToPath } from "url";
25
+ function parseSlotFlagsOrFail(flags) {
26
+ try {
27
+ return parseSlotFlags(flags);
28
+ } catch (e) {
29
+ fail(e instanceof Error ? e.message : String(e));
30
+ }
31
+ }
24
32
  function fail(message) {
25
33
  process.stderr.write(`error: ${message}
26
34
  `);
@@ -90,7 +98,8 @@ async function main() {
90
98
  "stream-json": { type: "boolean" },
91
99
  resume: { type: "string" },
92
100
  timeout: { type: "string" },
93
- "include-unavailable": { type: "boolean" }
101
+ "include-unavailable": { type: "boolean" },
102
+ slot: { type: "string", multiple: true }
94
103
  }
95
104
  });
96
105
  const [subcommand, irArg, question] = positionals;
@@ -116,7 +125,15 @@ async function main() {
116
125
  const flavor = parseRenderFlavor(values["render-flavor"] ?? "programmatic");
117
126
  const models = buildModels(values);
118
127
  const raw = readFileSync(resolve(irArg), "utf8");
119
- const common = { target, flavor, models, raw, irPath: irArg, project: values.project };
128
+ const common = {
129
+ target,
130
+ flavor,
131
+ models,
132
+ raw,
133
+ irPath: irArg,
134
+ project: values.project,
135
+ slots: parseSlotFlagsOrFail(values.slot ?? [])
136
+ };
120
137
  if (subcommand === "emit") {
121
138
  return runEmit(common, values.out, Boolean(values.standalone));
122
139
  }
@@ -130,6 +147,7 @@ async function main() {
130
147
  }
131
148
  function runEmit(common, outArg, standalone) {
132
149
  const prepared = prepareDispatch({
150
+ slots: common.slots,
133
151
  ir: common.raw,
134
152
  target: common.target,
135
153
  flavor: common.flavor,
@@ -155,7 +173,7 @@ function runManifest(common, outArg, includeUnavailable) {
155
173
  irPath: common.irPath,
156
174
  ...common.project !== void 0 ? { project: common.project } : {}
157
175
  };
158
- const prepared = includeUnavailable ? prepareDisplayManifest(input) : prepareDispatch(input);
176
+ const prepared = includeUnavailable ? prepareDisplayManifest({ ...input, slots: common.slots }) : prepareDispatch({ ...input, slots: common.slots });
159
177
  for (const c of prepared.components) {
160
178
  if ("report" in c) printResolutionSummary(common.target, c.id, c.report);
161
179
  }
@@ -184,6 +202,7 @@ async function runDispatchCmd(common, values, question) {
184
202
  const warbleBin = values["warble-bin"] ?? defaultWarbleBin();
185
203
  const title = values.title;
186
204
  const prepared = prepareDispatch({
205
+ slots: common.slots,
187
206
  ir: common.raw,
188
207
  question: question ?? "",
189
208
  target: common.target,
@@ -230,6 +249,7 @@ async function runChatCmd(common, values) {
230
249
  const warbleBin = values["warble-bin"] ?? defaultWarbleBin();
231
250
  const componentId = values.component ?? "answer_query";
232
251
  const prepared = prepareDispatch({
252
+ slots: common.slots,
233
253
  ir: common.raw,
234
254
  target: common.target,
235
255
  flavor: common.flavor,
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\n/**\n * `warble-agent-sdk` — the Claude Agent SDK back-end CLI.\n *\n * warble-agent-sdk dispatch <ir.json> \"<question>\" [--target …] [--models-config m.yml]\n * [--render-flavor programmatic|prompt] [--out ./run] [--project <dir>]\n * [--strong opus] [--cheap haiku] [--orchestrator sonnet]\n * [--warble-bin <path>] [--max-turns N] [--title <t>] [--dry-run]\n *\n * warble-agent-sdk emit <ir.json> [--out agent.ts] [--standalone] [--target …] [--models-config …]\n * [--render-flavor …] [--project <dir>] [--strong/--cheap/--orchestrator …]\n *\n * warble-agent-sdk manifest <ir.json> [--include-unavailable] [--out manifest.json] [--target …] [--models-config …]\n * [--render-flavor …] [--project <dir>] [--strong/--cheap/--orchestrator …]\n *\n * warble-agent-sdk chat <ir.json> [--project <dir>] [--component answer_query] [--out ./run]\n * [--target …] [--models-config m.yml] [--render-flavor programmatic|prompt] [--warble-bin <path>]\n * [--stream-json] [--resume <session-id>]\n *\n * `chat --stream-json` emits per-step/per-tool NDJSON events (one `WarbleChatEvent`, events.ts, per\n * line) to stdout as each turn runs, ending with a terminal `{\"t\":\"answer\",\"text\":…}` line, instead of\n * the default plain final-answer-text-per-turn output — for a consumer that wants to build a live,\n * expandable work log rather than just the finished text. Every turn also emits a\n * `{\"t\":\"session\",\"id\":…}` line (on success AND on a failed turn) carrying that turn's SDK session id.\n *\n * `--resume <session-id>` seeds a brand-new `chat` process's FIRST turn with a session id captured by\n * an earlier `chat` process (from its `{\"t\":\"session\",…}` line) — lets a caller resume a conversation\n * that a previous process started (e.g. one that ran out of turns), continuing the real SDK\n * conversation instead of re-dispatching a fresh prompt from scratch. Ignored after the first turn:\n * subsequent turns resume from this process's own prior turn, as usual.\n *\n * `dispatch` consumes the SAME `ir.json` a Rust `warble compile` emits and drives the SDK loop\n * in-process (`--dry-run` writes the assembled plan without calling `query()`). `emit` freezes the\n * resolved plan into an importable TS agent module (thin, or `--standalone`). `manifest` runs the\n * same preparation as `emit` (no `question`, no `query()` call) and instead serializes a display\n * manifest — the resolved agents/steps/tiers/capabilities/guardrails for THIS target, structurally\n * identical to the vercel back-end's bundle — so a consumer can source a display from whichever\n * back-end actually runs, instead of always reading the vercel bundle target's output. `chat` opens a\n * multi-turn session (session.ts, G1 — single profile, many turns) over one component, reading\n * questions from stdin line-by-line and resuming the SDK session turn over turn.\n */\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { createRequire } from \"node:module\";\nimport { dirname, join, resolve } from \"node:path\";\nimport { createInterface } from \"node:readline\";\nimport { parseArgs } from \"node:util\";\nimport { fileURLToPath } from \"node:url\";\n\nimport { emitAgentModule } from \"./codegen.js\";\nimport { prepareDisplayManifest, prepareDispatch, type PreparedDispatch } from \"./dispatch.js\";\nimport { DispatchError } from \"./error.js\";\nimport type { WarbleChatEvent } from \"./events.js\";\nimport { buildManifest } from \"./manifest.js\";\nimport { ModelConfig } from \"./models.js\";\nimport { discoverClaudeModels } from \"./model_catalog.js\";\nimport { parseRenderFlavor, type RenderFlavor } from \"./options.js\";\nimport { DispatchSessionError, runDispatch } from \"./run.js\";\nimport { createChatSession } from \"./session.js\";\nimport { type ResolutionReport } from \"./resolve.js\";\nimport { DEFAULT_TARGET } from \"./targets.js\";\n\nfunction fail(message: string): never {\n process.stderr.write(`error: ${message}\\n`);\n process.exit(1);\n}\n\nconst USAGE =\n 'usage: warble-agent-sdk <dispatch|emit|manifest|chat> <ir.json> [\"<question>\"] [options]\\n' +\n \" warble-agent-sdk list-models [--project <dir>] [--timeout <ms>]\";\n\n// `require(\"../package.json\")` resolves relative to *this* file's own location, one directory up —\n// which is the package root in both the dev tree (src/cli.ts → ../package.json) and the published\n// layout (dist/cli.js → ../package.json; package.json ships in every npm package regardless of the\n// \"files\" allowlist). That keeps the reported version tied to the package's real `version` field\n// instead of a literal that could drift from it.\nconst requireFromHere = createRequire(import.meta.url);\n\nfunction packageVersion(): string {\n return (requireFromHere(\"../package.json\") as { version: string }).version;\n}\n\n/** Locate the reference `warble` binary: --warble-bin, else PATH, else this repo's release build. */\nfunction defaultWarbleBin(): string {\n const here = dirname(fileURLToPath(import.meta.url));\n const repoBuilt = resolve(here, \"../../../target/release/warble\");\n return existsSync(repoBuilt) ? repoBuilt : \"warble\";\n}\n\nfunction printResolutionSummary(target: string, id: string, report: ResolutionReport): void {\n process.stderr.write(`warble-agent-sdk: capability resolution for '${target}' (component '${id}'):\\n`);\n for (const e of report) {\n const note = e.note ? ` — ${e.note}` : \"\";\n process.stderr.write(\n ` ${e.capability.padEnd(28)} ${e.outcome.padEnd(12)} (${e.provided_by}, ${e.criticality})${note}\\n`,\n );\n }\n}\n\ninterface CommonArgs {\n target: string;\n flavor: RenderFlavor;\n models: ModelConfig;\n raw: string;\n irPath: string;\n project: string | undefined;\n}\n\nfunction buildModels(values: Record<string, string | boolean | undefined>): ModelConfig {\n const cfgPath = values[\"models-config\"];\n if (typeof cfgPath === \"string\") {\n return ModelConfig.fromYaml(readFileSync(resolve(cfgPath), \"utf8\"));\n }\n return ModelConfig.fromFlags(\n (values.strong as string) ?? \"opus\",\n (values.cheap as string) ?? \"haiku\",\n (values.orchestrator as string) ?? \"sonnet\",\n );\n}\n\nasync function main(): Promise<void> {\n // Handle `--version`/`-V` and `--help`/`-h` up front, before the strict `parseArgs` below —\n // neither is a declared option there, so leaving them for `parseArgs` to see would throw\n // `ERR_PARSE_ARGS_UNKNOWN_OPTION` instead of doing what every other CLI does with them.\n const firstArg = process.argv[2];\n if (firstArg === \"--version\" || firstArg === \"-V\") {\n process.stdout.write(`${packageVersion()}\\n`);\n return;\n }\n if (firstArg === \"--help\" || firstArg === \"-h\") {\n process.stdout.write(`${USAGE}\\n`);\n return;\n }\n\n const { values, positionals } = parseArgs({\n allowPositionals: true,\n options: {\n target: { type: \"string\" },\n out: { type: \"string\" },\n \"models-config\": { type: \"string\" },\n \"render-flavor\": { type: \"string\" },\n strong: { type: \"string\" },\n cheap: { type: \"string\" },\n orchestrator: { type: \"string\" },\n project: { type: \"string\" },\n \"warble-bin\": { type: \"string\" },\n \"max-turns\": { type: \"string\" },\n title: { type: \"string\" },\n \"dry-run\": { type: \"boolean\" },\n standalone: { type: \"boolean\" },\n component: { type: \"string\" },\n \"stream-json\": { type: \"boolean\" },\n resume: { type: \"string\" },\n timeout: { type: \"string\" },\n \"include-unavailable\": { type: \"boolean\" },\n },\n });\n\n const [subcommand, irArg, question] = positionals;\n if (\n subcommand !== \"dispatch\" &&\n subcommand !== \"emit\" &&\n subcommand !== \"manifest\" &&\n subcommand !== \"chat\" &&\n subcommand !== \"list-models\"\n ) {\n fail(USAGE);\n }\n if (subcommand === \"list-models\") {\n if (irArg !== undefined || question !== undefined) fail(\"list-models does not take an <ir.json> or question\");\n const timeout = values.timeout === undefined ? undefined : Number(values.timeout);\n if (timeout !== undefined && (!Number.isFinite(timeout) || timeout <= 0)) fail(\"--timeout must be a positive number\");\n const catalog = await discoverClaudeModels({\n ...(values.project ? { cwd: values.project } : {}),\n ...(timeout !== undefined ? { timeoutMs: timeout } : {}),\n });\n process.stdout.write(`${JSON.stringify(catalog)}\\n`);\n return;\n }\n if (values.timeout !== undefined) fail(\"--timeout is only supported by list-models\");\n if (values[\"include-unavailable\"] && subcommand !== \"manifest\") fail(\"--include-unavailable is only supported by manifest\");\n if (!irArg) fail(\"missing <ir.json> argument\");\n\n const target = values.target ?? DEFAULT_TARGET;\n const flavor = parseRenderFlavor(values[\"render-flavor\"] ?? \"programmatic\");\n const models = buildModels(values);\n const raw = readFileSync(resolve(irArg), \"utf8\");\n\n const common: CommonArgs = { target, flavor, models, raw, irPath: irArg, project: values.project };\n\n if (subcommand === \"emit\") {\n return runEmit(common, values.out, Boolean(values.standalone));\n }\n if (subcommand === \"manifest\") {\n return runManifest(common, values.out, Boolean(values[\"include-unavailable\"]));\n }\n if (subcommand === \"chat\") {\n return runChatCmd(common, values);\n }\n return runDispatchCmd(common, values, question);\n}\n\nfunction runEmit(common: CommonArgs, outArg: string | undefined, standalone: boolean): void {\n const prepared: PreparedDispatch = prepareDispatch({\n ir: common.raw,\n target: common.target,\n flavor: common.flavor,\n models: common.models,\n irPath: common.irPath,\n ...(common.project !== undefined ? { project: common.project } : {}),\n });\n for (const c of prepared.components) printResolutionSummary(common.target, c.id, c.report);\n\n const outPath = resolve(outArg ?? \"agent.ts\");\n mkdirSync(dirname(outPath), { recursive: true });\n writeFileSync(outPath, emitAgentModule(prepared, { standalone }), \"utf8\");\n process.stderr.write(\n `warble-agent-sdk: emit — wrote ${outPath} (${prepared.components.length} component(s), ${standalone ? \"standalone\" : \"thin\"}).\\n`,\n );\n}\n\n/**\n * `manifest` — same preparation as `emit` (no `question`, `query()` never called), but instead of\n * freezing an importable agent module, serializes the display manifest (see `manifest.ts`) to stdout\n * or `--out`. Capability resolution summaries still go to stderr so stdout stays pure JSON.\n */\nfunction runManifest(common: CommonArgs, outArg: string | undefined, includeUnavailable: boolean): void {\n const input = {\n ir: common.raw,\n target: common.target,\n flavor: common.flavor,\n models: common.models,\n irPath: common.irPath,\n ...(common.project !== undefined ? { project: common.project } : {}),\n } as const;\n const prepared = includeUnavailable ? prepareDisplayManifest(input) : prepareDispatch(input);\n for (const c of prepared.components) {\n if (\"report\" in c) printResolutionSummary(common.target, c.id, c.report);\n }\n\n const manifest = buildManifest(prepared, common.raw);\n const json = `${JSON.stringify(manifest, null, 2)}\\n`;\n\n if (outArg) {\n const outPath = resolve(outArg);\n mkdirSync(dirname(outPath), { recursive: true });\n writeFileSync(outPath, json, \"utf8\");\n process.stderr.write(\n `warble-agent-sdk: manifest — wrote ${outPath} (${prepared.components.length} agent(s)).\\n`,\n );\n } else {\n process.stdout.write(json);\n }\n}\n\nasync function runDispatchCmd(\n common: CommonArgs,\n values: Record<string, string | boolean | undefined>,\n question: string | undefined,\n): Promise<void> {\n const dryRun = Boolean(values[\"dry-run\"]);\n if (!question && !dryRun) fail('missing \"<question>\" argument (or pass --dry-run)');\n\n const maxTurnsRaw = values[\"max-turns\"];\n const maxTurns = typeof maxTurnsRaw === \"string\" ? Number(maxTurnsRaw) : undefined;\n if (maxTurns !== undefined && !Number.isFinite(maxTurns)) fail(\"--max-turns must be a number\");\n\n const outDir = resolve((values.out as string) ?? \"./run\");\n const warbleBin = (values[\"warble-bin\"] as string) ?? defaultWarbleBin();\n const title = values.title as string | undefined;\n\n const prepared = prepareDispatch({\n ir: common.raw,\n question: question ?? \"\",\n target: common.target,\n flavor: common.flavor,\n models: common.models,\n irPath: common.irPath,\n ...(common.project !== undefined ? { project: common.project } : {}),\n ...(maxTurns !== undefined ? { maxTurns } : {}),\n });\n\n mkdirSync(outDir, { recursive: true });\n for (const c of prepared.components) printResolutionSummary(common.target, c.id, c.report);\n\n for (const c of prepared.components) {\n if (dryRun) {\n const planPath = join(outDir, `${c.node.verb}.plan.json`);\n writeFileSync(\n planPath,\n JSON.stringify({ prompt: c.plan.prompt, options: c.plan.options, meta: c.plan.meta }, null, 2) + \"\\n\",\n \"utf8\",\n );\n process.stderr.write(\n `warble-agent-sdk: dry-run — wrote plan ${planPath} (model=${c.plan.meta.model}, split=${c.plan.meta.split}, render=${c.plan.meta.render.kind}); query() not called.\\n`,\n );\n continue;\n }\n const result = await runDispatch(c.plan, { outDir, warbleBin, ...(title ? { title } : {}) });\n process.stderr.write(\n `warble-agent-sdk: ran '${c.node.verb}' → ${result.htmlPath ?? \"(no html)\"}; ` +\n `${result.denials.length} guardrail denial(s); trace at ${join(outDir, \"trace.json\")}\\n`,\n );\n }\n\n writeFileSync(\n join(outDir, \"capability-report.json\"),\n JSON.stringify(\n { target: common.target, components: prepared.components.map((c) => ({ id: c.id, capabilities: c.report })) },\n null,\n 2,\n ) + \"\\n\",\n \"utf8\",\n );\n}\n\n/**\n * `chat` — a multi-turn session (session.ts, G1) over ONE prepared component, reading questions from\n * stdin line-by-line. Each turn's answer is printed to stdout; the SDK session is resumed turn over\n * turn (`ChatSession` handles the `resume: session_id` plumbing). Manual/live use only — not exercised\n * by the offline test suite.\n *\n * `--stream-json` (opt-in): instead of printing the turn's plain final-answer text, stream one\n * `WarbleChatEvent` NDJSON line per event as the turn runs (via `session.ask`'s `onEvent`), followed\n * by a terminal `{\"t\":\"answer\",\"text\":…}` line. Without the flag, behavior is byte-for-byte unchanged\n * from before this option existed.\n */\nasync function runChatCmd(\n common: CommonArgs,\n values: Record<string, string | boolean | undefined>,\n): Promise<void> {\n const outDir = resolve((values.out as string) ?? \"./run\");\n const warbleBin = (values[\"warble-bin\"] as string) ?? defaultWarbleBin();\n const componentId = (values.component as string) ?? \"answer_query\";\n\n // Scoped to `componentId`: only its own required capabilities are resolved, so a *different*\n // component's unmet requirements (e.g. a sibling gated-tool with no approval channel wired on\n // this target) can never block dispatching this one. See `DispatchInput.componentId`.\n const prepared = prepareDispatch({\n ir: common.raw,\n target: common.target,\n flavor: common.flavor,\n models: common.models,\n irPath: common.irPath,\n componentId,\n ...(common.project !== undefined ? { project: common.project } : {}),\n });\n\n // `prepareDispatch` with `componentId` set either returns exactly this one component or throws\n // (caught by `main().catch()` below) — this is a defensive invariant check, not a reachable\n // \"not found\" path; that path's error text now comes from `prepareDispatch` itself.\n const component = prepared.components[0];\n if (!component) fail(`internal error: no component prepared for '${componentId}'`);\n for (const c of prepared.components) printResolutionSummary(common.target, c.id, c.report);\n\n mkdirSync(outDir, { recursive: true });\n const resumeSessionId = values.resume as string | undefined;\n const session = createChatSession(component.plan, { outDir, warbleBin }, resumeSessionId);\n\n process.stderr.write(\n `warble-agent-sdk: chat — component '${componentId}'; type a question per line (Ctrl-D to end).\\n`,\n );\n\n const streamJson = Boolean(values[\"stream-json\"]);\n const onEvent = streamJson\n ? (event: WarbleChatEvent): void => {\n process.stdout.write(`${JSON.stringify(event)}\\n`);\n }\n : undefined;\n\n const emitSession = (id: string | null): void => {\n if (!streamJson) return;\n const sessionEvent: WarbleChatEvent = { t: \"session\", id };\n process.stdout.write(`${JSON.stringify(sessionEvent)}\\n`);\n };\n\n const rl = createInterface({ input: process.stdin, crlfDelay: Infinity });\n for await (const line of rl) {\n const question = line.trim();\n if (!question) continue;\n let turn;\n try {\n turn = await session.ask(question, onEvent ? { onEvent } : {});\n } catch (err) {\n // A failed turn (e.g. error_max_turns) still surfaces its session id, when the SDK's result\n // message carried one, so a caller can resume this same conversation instead of starting over.\n emitSession(err instanceof DispatchSessionError ? err.sessionId : null);\n throw err;\n }\n emitSession(turn.sessionId);\n if (streamJson) {\n const answerEvent: WarbleChatEvent = { t: \"answer\", text: turn.finalText };\n process.stdout.write(`${JSON.stringify(answerEvent)}\\n`);\n } else {\n process.stdout.write(`${turn.finalText}\\n`);\n }\n }\n}\n\nmain().catch((e: unknown) => {\n if (e instanceof DispatchError) fail(e.message);\n fail(e instanceof Error ? (e.stack ?? e.message) : String(e));\n});\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\n/**\n * `warble-agent-sdk` — the Claude Agent SDK back-end CLI.\n *\n * warble-agent-sdk dispatch <ir.json> \"<question>\" [--target …] [--models-config m.yml]\n * [--render-flavor programmatic|prompt] [--out ./run] [--project <dir>]\n * [--strong opus] [--cheap haiku] [--orchestrator sonnet]\n * [--warble-bin <path>] [--max-turns N] [--title <t>] [--dry-run]\n *\n * warble-agent-sdk emit <ir.json> [--out agent.ts] [--standalone] [--target …] [--models-config …]\n * [--render-flavor …] [--project <dir>] [--strong/--cheap/--orchestrator …]\n *\n * warble-agent-sdk manifest <ir.json> [--include-unavailable] [--out manifest.json] [--target …] [--models-config …]\n * [--render-flavor …] [--project <dir>] [--strong/--cheap/--orchestrator …]\n *\n * warble-agent-sdk chat <ir.json> [--project <dir>] [--component answer_query] [--out ./run]\n * [--target …] [--models-config m.yml] [--render-flavor programmatic|prompt] [--warble-bin <path>]\n * [--stream-json] [--resume <session-id>]\n *\n * `--slot NAME=VARIANT` fills a named prompt slot with that variant; `--slot NAME=` removes a slot\n * whose condition does not hold. Repeatable, accepted by every subcommand, and mirroring the `warble`\n * CLI's flag of the same name. A slot nobody names takes its declared default — except one carrying\n * a `present_when` condition, which is refused when unanswered on any path whose text reaches a\n * model, because shipping wording for something that may have been withheld is worse than shipping\n * none. `manifest` is a display and renders such a default instead of refusing.\n *\n * `chat --stream-json` emits per-step/per-tool NDJSON events (one `WarbleChatEvent`, events.ts, per\n * line) to stdout as each turn runs, ending with a terminal `{\"t\":\"answer\",\"text\":…}` line, instead of\n * the default plain final-answer-text-per-turn output — for a consumer that wants to build a live,\n * expandable work log rather than just the finished text. Every turn also emits a\n * `{\"t\":\"session\",\"id\":…}` line (on success AND on a failed turn) carrying that turn's SDK session id.\n *\n * `--resume <session-id>` seeds a brand-new `chat` process's FIRST turn with a session id captured by\n * an earlier `chat` process (from its `{\"t\":\"session\",…}` line) — lets a caller resume a conversation\n * that a previous process started (e.g. one that ran out of turns), continuing the real SDK\n * conversation instead of re-dispatching a fresh prompt from scratch. Ignored after the first turn:\n * subsequent turns resume from this process's own prior turn, as usual.\n *\n * `dispatch` consumes the SAME `ir.json` a Rust `warble compile` emits and drives the SDK loop\n * in-process (`--dry-run` writes the assembled plan without calling `query()`). `emit` freezes the\n * resolved plan into an importable TS agent module (thin, or `--standalone`). `manifest` runs the\n * same preparation as `emit` (no `question`, no `query()` call) and instead serializes a display\n * manifest — the resolved agents/steps/tiers/capabilities/guardrails for THIS target, structurally\n * identical to the vercel back-end's bundle — so a consumer can source a display from whichever\n * back-end actually runs, instead of always reading the vercel bundle target's output. `chat` opens a\n * multi-turn session (session.ts, G1 — single profile, many turns) over one component, reading\n * questions from stdin line-by-line and resuming the SDK session turn over turn.\n */\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { createRequire } from \"node:module\";\nimport { dirname, join, resolve } from \"node:path\";\nimport { createInterface } from \"node:readline\";\nimport { parseArgs } from \"node:util\";\nimport { fileURLToPath } from \"node:url\";\n\nimport { emitAgentModule } from \"./codegen.js\";\nimport { prepareDisplayManifest, prepareDispatch, type PreparedDispatch } from \"./dispatch.js\";\nimport { parseSlotFlags } from \"./slots.js\";\nimport type { SlotSupply } from \"./slots.js\";\nimport { DispatchError } from \"./error.js\";\nimport type { WarbleChatEvent } from \"./events.js\";\nimport { buildManifest } from \"./manifest.js\";\nimport { ModelConfig } from \"./models.js\";\nimport { discoverClaudeModels } from \"./model_catalog.js\";\nimport { parseRenderFlavor, type RenderFlavor } from \"./options.js\";\nimport { DispatchSessionError, runDispatch } from \"./run.js\";\nimport { createChatSession } from \"./session.js\";\nimport { type ResolutionReport } from \"./resolve.js\";\nimport { DEFAULT_TARGET } from \"./targets.js\";\n\n/** `parseSlotFlags` throws; this CLI reports a bad flag as a usage failure instead. */\nfunction parseSlotFlagsOrFail(flags: readonly string[]): SlotSupply {\n try {\n return parseSlotFlags(flags);\n } catch (e) {\n fail(e instanceof Error ? e.message : String(e));\n }\n}\n\nfunction fail(message: string): never {\n process.stderr.write(`error: ${message}\\n`);\n process.exit(1);\n}\n\nconst USAGE =\n 'usage: warble-agent-sdk <dispatch|emit|manifest|chat> <ir.json> [\"<question>\"] [options]\\n' +\n \" warble-agent-sdk list-models [--project <dir>] [--timeout <ms>]\";\n\n// `require(\"../package.json\")` resolves relative to *this* file's own location, one directory up —\n// which is the package root in both the dev tree (src/cli.ts → ../package.json) and the published\n// layout (dist/cli.js → ../package.json; package.json ships in every npm package regardless of the\n// \"files\" allowlist). That keeps the reported version tied to the package's real `version` field\n// instead of a literal that could drift from it.\nconst requireFromHere = createRequire(import.meta.url);\n\nfunction packageVersion(): string {\n return (requireFromHere(\"../package.json\") as { version: string }).version;\n}\n\n/** Locate the reference `warble` binary: --warble-bin, else PATH, else this repo's release build. */\nfunction defaultWarbleBin(): string {\n const here = dirname(fileURLToPath(import.meta.url));\n const repoBuilt = resolve(here, \"../../../target/release/warble\");\n return existsSync(repoBuilt) ? repoBuilt : \"warble\";\n}\n\nfunction printResolutionSummary(target: string, id: string, report: ResolutionReport): void {\n process.stderr.write(`warble-agent-sdk: capability resolution for '${target}' (component '${id}'):\\n`);\n for (const e of report) {\n const note = e.note ? ` — ${e.note}` : \"\";\n process.stderr.write(\n ` ${e.capability.padEnd(28)} ${e.outcome.padEnd(12)} (${e.provided_by}, ${e.criticality})${note}\\n`,\n );\n }\n}\n\ninterface CommonArgs {\n target: string;\n flavor: RenderFlavor;\n models: ModelConfig;\n raw: string;\n irPath: string;\n project: string | undefined;\n /** The host's slot table, from `--slot`. Empty when none was given. */\n slots: SlotSupply;\n}\n\nfunction buildModels(values: Record<string, string | string[] | boolean | undefined>): ModelConfig {\n const cfgPath = values[\"models-config\"];\n if (typeof cfgPath === \"string\") {\n return ModelConfig.fromYaml(readFileSync(resolve(cfgPath), \"utf8\"));\n }\n return ModelConfig.fromFlags(\n (values.strong as string) ?? \"opus\",\n (values.cheap as string) ?? \"haiku\",\n (values.orchestrator as string) ?? \"sonnet\",\n );\n}\n\nasync function main(): Promise<void> {\n // Handle `--version`/`-V` and `--help`/`-h` up front, before the strict `parseArgs` below —\n // neither is a declared option there, so leaving them for `parseArgs` to see would throw\n // `ERR_PARSE_ARGS_UNKNOWN_OPTION` instead of doing what every other CLI does with them.\n const firstArg = process.argv[2];\n if (firstArg === \"--version\" || firstArg === \"-V\") {\n process.stdout.write(`${packageVersion()}\\n`);\n return;\n }\n if (firstArg === \"--help\" || firstArg === \"-h\") {\n process.stdout.write(`${USAGE}\\n`);\n return;\n }\n\n const { values, positionals } = parseArgs({\n allowPositionals: true,\n options: {\n target: { type: \"string\" },\n out: { type: \"string\" },\n \"models-config\": { type: \"string\" },\n \"render-flavor\": { type: \"string\" },\n strong: { type: \"string\" },\n cheap: { type: \"string\" },\n orchestrator: { type: \"string\" },\n project: { type: \"string\" },\n \"warble-bin\": { type: \"string\" },\n \"max-turns\": { type: \"string\" },\n title: { type: \"string\" },\n \"dry-run\": { type: \"boolean\" },\n standalone: { type: \"boolean\" },\n component: { type: \"string\" },\n \"stream-json\": { type: \"boolean\" },\n resume: { type: \"string\" },\n timeout: { type: \"string\" },\n \"include-unavailable\": { type: \"boolean\" },\n slot: { type: \"string\", multiple: true },\n },\n });\n\n\n\n const [subcommand, irArg, question] = positionals;\n if (\n subcommand !== \"dispatch\" &&\n subcommand !== \"emit\" &&\n subcommand !== \"manifest\" &&\n subcommand !== \"chat\" &&\n subcommand !== \"list-models\"\n ) {\n fail(USAGE);\n }\n if (subcommand === \"list-models\") {\n if (irArg !== undefined || question !== undefined) fail(\"list-models does not take an <ir.json> or question\");\n const timeout = values.timeout === undefined ? undefined : Number(values.timeout);\n if (timeout !== undefined && (!Number.isFinite(timeout) || timeout <= 0)) fail(\"--timeout must be a positive number\");\n const catalog = await discoverClaudeModels({\n ...(values.project ? { cwd: values.project } : {}),\n ...(timeout !== undefined ? { timeoutMs: timeout } : {}),\n });\n process.stdout.write(`${JSON.stringify(catalog)}\\n`);\n return;\n }\n if (values.timeout !== undefined) fail(\"--timeout is only supported by list-models\");\n if (values[\"include-unavailable\"] && subcommand !== \"manifest\") fail(\"--include-unavailable is only supported by manifest\");\n if (!irArg) fail(\"missing <ir.json> argument\");\n\n const target = values.target ?? DEFAULT_TARGET;\n const flavor = parseRenderFlavor(values[\"render-flavor\"] ?? \"programmatic\");\n const models = buildModels(values);\n const raw = readFileSync(resolve(irArg), \"utf8\");\n\n // Parsed once and carried on CommonArgs, so every subcommand that builds prompts gets the same\n // table. Without this the seam would be reachable only by importing the library, and a profile\n // with a conditional slot could not be run through this CLI at all — it would always refuse for\n // want of an answer.\n const common: CommonArgs = {\n target,\n flavor,\n models,\n raw,\n irPath: irArg,\n project: values.project,\n slots: parseSlotFlagsOrFail(values.slot ?? []),\n };\n\n if (subcommand === \"emit\") {\n return runEmit(common, values.out, Boolean(values.standalone));\n }\n if (subcommand === \"manifest\") {\n return runManifest(common, values.out, Boolean(values[\"include-unavailable\"]));\n }\n if (subcommand === \"chat\") {\n return runChatCmd(common, values);\n }\n return runDispatchCmd(common, values, question);\n}\n\nfunction runEmit(common: CommonArgs, outArg: string | undefined, standalone: boolean): void {\n const prepared: PreparedDispatch = prepareDispatch({\n slots: common.slots,\n ir: common.raw,\n target: common.target,\n flavor: common.flavor,\n models: common.models,\n irPath: common.irPath,\n ...(common.project !== undefined ? { project: common.project } : {}),\n });\n for (const c of prepared.components) printResolutionSummary(common.target, c.id, c.report);\n\n const outPath = resolve(outArg ?? \"agent.ts\");\n mkdirSync(dirname(outPath), { recursive: true });\n writeFileSync(outPath, emitAgentModule(prepared, { standalone }), \"utf8\");\n process.stderr.write(\n `warble-agent-sdk: emit — wrote ${outPath} (${prepared.components.length} component(s), ${standalone ? \"standalone\" : \"thin\"}).\\n`,\n );\n}\n\n/**\n * `manifest` — same preparation as `emit` (no `question`, `query()` never called), but instead of\n * freezing an importable agent module, serializes the display manifest (see `manifest.ts`) to stdout\n * or `--out`. Capability resolution summaries still go to stderr so stdout stays pure JSON.\n */\nfunction runManifest(common: CommonArgs, outArg: string | undefined, includeUnavailable: boolean): void {\n const input = {\n ir: common.raw,\n target: common.target,\n flavor: common.flavor,\n models: common.models,\n irPath: common.irPath,\n ...(common.project !== undefined ? { project: common.project } : {}),\n } as const;\n const prepared = includeUnavailable ? prepareDisplayManifest({ ...input, slots: common.slots }) : prepareDispatch({ ...input, slots: common.slots });\n for (const c of prepared.components) {\n if (\"report\" in c) printResolutionSummary(common.target, c.id, c.report);\n }\n\n const manifest = buildManifest(prepared, common.raw);\n const json = `${JSON.stringify(manifest, null, 2)}\\n`;\n\n if (outArg) {\n const outPath = resolve(outArg);\n mkdirSync(dirname(outPath), { recursive: true });\n writeFileSync(outPath, json, \"utf8\");\n process.stderr.write(\n `warble-agent-sdk: manifest — wrote ${outPath} (${prepared.components.length} agent(s)).\\n`,\n );\n } else {\n process.stdout.write(json);\n }\n}\n\nasync function runDispatchCmd(\n common: CommonArgs,\n values: Record<string, string | string[] | boolean | undefined>,\n question: string | undefined,\n): Promise<void> {\n const dryRun = Boolean(values[\"dry-run\"]);\n if (!question && !dryRun) fail('missing \"<question>\" argument (or pass --dry-run)');\n\n const maxTurnsRaw = values[\"max-turns\"];\n const maxTurns = typeof maxTurnsRaw === \"string\" ? Number(maxTurnsRaw) : undefined;\n if (maxTurns !== undefined && !Number.isFinite(maxTurns)) fail(\"--max-turns must be a number\");\n\n const outDir = resolve((values.out as string) ?? \"./run\");\n const warbleBin = (values[\"warble-bin\"] as string) ?? defaultWarbleBin();\n const title = values.title as string | undefined;\n\n const prepared = prepareDispatch({\n slots: common.slots,\n ir: common.raw,\n question: question ?? \"\",\n target: common.target,\n flavor: common.flavor,\n models: common.models,\n irPath: common.irPath,\n ...(common.project !== undefined ? { project: common.project } : {}),\n ...(maxTurns !== undefined ? { maxTurns } : {}),\n });\n\n mkdirSync(outDir, { recursive: true });\n for (const c of prepared.components) printResolutionSummary(common.target, c.id, c.report);\n\n for (const c of prepared.components) {\n if (dryRun) {\n const planPath = join(outDir, `${c.node.verb}.plan.json`);\n writeFileSync(\n planPath,\n JSON.stringify({ prompt: c.plan.prompt, options: c.plan.options, meta: c.plan.meta }, null, 2) + \"\\n\",\n \"utf8\",\n );\n process.stderr.write(\n `warble-agent-sdk: dry-run — wrote plan ${planPath} (model=${c.plan.meta.model}, split=${c.plan.meta.split}, render=${c.plan.meta.render.kind}); query() not called.\\n`,\n );\n continue;\n }\n const result = await runDispatch(c.plan, { outDir, warbleBin, ...(title ? { title } : {}) });\n process.stderr.write(\n `warble-agent-sdk: ran '${c.node.verb}' → ${result.htmlPath ?? \"(no html)\"}; ` +\n `${result.denials.length} guardrail denial(s); trace at ${join(outDir, \"trace.json\")}\\n`,\n );\n }\n\n writeFileSync(\n join(outDir, \"capability-report.json\"),\n JSON.stringify(\n { target: common.target, components: prepared.components.map((c) => ({ id: c.id, capabilities: c.report })) },\n null,\n 2,\n ) + \"\\n\",\n \"utf8\",\n );\n}\n\n/**\n * `chat` — a multi-turn session (session.ts, G1) over ONE prepared component, reading questions from\n * stdin line-by-line. Each turn's answer is printed to stdout; the SDK session is resumed turn over\n * turn (`ChatSession` handles the `resume: session_id` plumbing). Manual/live use only — not exercised\n * by the offline test suite.\n *\n * `--stream-json` (opt-in): instead of printing the turn's plain final-answer text, stream one\n * `WarbleChatEvent` NDJSON line per event as the turn runs (via `session.ask`'s `onEvent`), followed\n * by a terminal `{\"t\":\"answer\",\"text\":…}` line. Without the flag, behavior is byte-for-byte unchanged\n * from before this option existed.\n */\nasync function runChatCmd(\n common: CommonArgs,\n values: Record<string, string | string[] | boolean | undefined>,\n): Promise<void> {\n const outDir = resolve((values.out as string) ?? \"./run\");\n const warbleBin = (values[\"warble-bin\"] as string) ?? defaultWarbleBin();\n const componentId = (values.component as string) ?? \"answer_query\";\n\n // Scoped to `componentId`: only its own required capabilities are resolved, so a *different*\n // component's unmet requirements (e.g. a sibling gated-tool with no approval channel wired on\n // this target) can never block dispatching this one. See `DispatchInput.componentId`.\n const prepared = prepareDispatch({\n slots: common.slots,\n ir: common.raw,\n target: common.target,\n flavor: common.flavor,\n models: common.models,\n irPath: common.irPath,\n componentId,\n ...(common.project !== undefined ? { project: common.project } : {}),\n });\n\n // `prepareDispatch` with `componentId` set either returns exactly this one component or throws\n // (caught by `main().catch()` below) — this is a defensive invariant check, not a reachable\n // \"not found\" path; that path's error text now comes from `prepareDispatch` itself.\n const component = prepared.components[0];\n if (!component) fail(`internal error: no component prepared for '${componentId}'`);\n for (const c of prepared.components) printResolutionSummary(common.target, c.id, c.report);\n\n mkdirSync(outDir, { recursive: true });\n const resumeSessionId = values.resume as string | undefined;\n const session = createChatSession(component.plan, { outDir, warbleBin }, resumeSessionId);\n\n process.stderr.write(\n `warble-agent-sdk: chat — component '${componentId}'; type a question per line (Ctrl-D to end).\\n`,\n );\n\n const streamJson = Boolean(values[\"stream-json\"]);\n const onEvent = streamJson\n ? (event: WarbleChatEvent): void => {\n process.stdout.write(`${JSON.stringify(event)}\\n`);\n }\n : undefined;\n\n const emitSession = (id: string | null): void => {\n if (!streamJson) return;\n const sessionEvent: WarbleChatEvent = { t: \"session\", id };\n process.stdout.write(`${JSON.stringify(sessionEvent)}\\n`);\n };\n\n const rl = createInterface({ input: process.stdin, crlfDelay: Infinity });\n for await (const line of rl) {\n const question = line.trim();\n if (!question) continue;\n let turn;\n try {\n turn = await session.ask(question, onEvent ? { onEvent } : {});\n } catch (err) {\n // A failed turn (e.g. error_max_turns) still surfaces its session id, when the SDK's result\n // message carried one, so a caller can resume this same conversation instead of starting over.\n emitSession(err instanceof DispatchSessionError ? err.sessionId : null);\n throw err;\n }\n emitSession(turn.sessionId);\n if (streamJson) {\n const answerEvent: WarbleChatEvent = { t: \"answer\", text: turn.finalText };\n process.stdout.write(`${JSON.stringify(answerEvent)}\\n`);\n } else {\n process.stdout.write(`${turn.finalText}\\n`);\n }\n }\n}\n\nmain().catch((e: unknown) => {\n if (e instanceof DispatchError) fail(e.message);\n fail(e instanceof Error ? (e.stack ?? e.message) : String(e));\n});\n"],"mappings":"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","names":[]}
package/dist/index.d.ts CHANGED
@@ -172,6 +172,21 @@ interface PreconditionResult {
172
172
  status: string;
173
173
  checks: PreconditionCheck[];
174
174
  }
175
+ /**
176
+ * A named position in prompt text, with the alternative wordings that may fill it (IR 0.7).
177
+ *
178
+ * `default` always names one of `variants` — compile refuses otherwise — so a consumer that has no
179
+ * opinion still has something to render. `present_when` is carried but never evaluated here: the
180
+ * spec assigns that to the host, and this back-end only asks the host for the answer.
181
+ */
182
+ interface SlotDecl {
183
+ name: string;
184
+ /** Always a key of `variants`. */
185
+ default: string;
186
+ variants: Record<string, string>;
187
+ /** Present only when the author declared a condition. Carried verbatim; not interpreted here. */
188
+ present_when?: unknown;
189
+ }
175
190
  interface ComponentNode {
176
191
  id: string;
177
192
  verb: string;
@@ -193,6 +208,9 @@ interface ComponentNode {
193
208
  eval: EvalSpec | null;
194
209
  /** Optional free-form framing shared by every step of this component (see `docs/spec/ir-schema.md`). */
195
210
  brief?: string;
211
+ /** Slots belonging to THIS component's own prompt text (its steps and `brief`). Profile-level
212
+ * slots live on the IR root instead and are deliberately not copied here. */
213
+ slots?: SlotDecl[];
196
214
  }
197
215
  interface WarbleIr {
198
216
  warble_ir_version: string;
@@ -200,6 +218,10 @@ interface WarbleIr {
200
218
  context_binding: ContextBinding;
201
219
  config: IrConfig;
202
220
  components: ComponentNode[];
221
+ /** Profile-level slots, belonging to the profile's `system_prompt`. Names are unique across the
222
+ * whole project — compile refuses a collision with any component's — so a consumer resolves
223
+ * `{{ slot.<name> }}` against one flat namespace rather than a per-layer precedence rule. */
224
+ slots?: SlotDecl[];
203
225
  }
204
226
  /**
205
227
  * IR versions this back-end understands. Older versions (0.1, 0.2) are no longer accepted now that
@@ -427,11 +449,11 @@ interface StepMessage {
427
449
  }
428
450
  /**
429
451
  * Build the messages for one staged step: the step's own prompt as the system message, and the user
430
- * message = the question plus each consumed slot's value marshaled in by name (the `produces`→`consumes`
452
+ * message = the question plus each consumed artifact's value marshaled in by name (the `produces`→`consumes`
431
453
  * hand-off). This is the same isolated-invocation contract the IR already carries for the file target's
432
454
  * subagents (ir.ts `consumes`/`produces`), generalized here across providers.
433
455
  */
434
- declare function buildStepMessages(step: StagedStep, question: string, slots: Readonly<Record<string, string>>): StepMessage[];
456
+ declare function buildStepMessages(step: StagedStep, question: string, artifacts: Readonly<Record<string, string>>): StepMessage[];
435
457
 
436
458
  /**
437
459
  * Minimal OpenAI-compatible chat client for the hybrid-staged path (see docs/spec/capability-model.md §7.2).
@@ -573,6 +595,9 @@ interface BuildConfig {
573
595
  /**
574
596
  * Build the `query({options})` for one resolved IR node. Loud-fails on any unsupported enum value
575
597
  * before producing anything (wall-hit), mirroring `emit.rs`.
598
+ *
599
+ * The assembled prompts are checked for surviving slot references on the way out — see
600
+ * {@link assertPlanHasNoSlotReferences} for why that check lives here and not only at resolution.
576
601
  */
577
602
  declare function buildDispatchPlan(node: ComponentNode, report: ResolutionReport, cfg: BuildConfig): DispatchPlan;
578
603
 
@@ -635,6 +660,97 @@ type WarbleChatEvent = {
635
660
  readonly id: string | null;
636
661
  };
637
662
 
663
+ /** Hash algorithm named in the output so a stored fingerprint stays readable if this ever changes. */
664
+ declare const ALGORITHM = "sha256";
665
+ /**
666
+ * One digest per surface, plus the total.
667
+ *
668
+ * **Per surface as well as in total, on purpose.** The total answers "did anything change"; only the
669
+ * per-surface digests answer "which prompt changed", and that is the question a trace disagreeing
670
+ * with its own hash actually raises. The cost is a few dozen bytes per run.
671
+ */
672
+ interface PromptFingerprint {
673
+ algorithm: typeof ALGORITHM;
674
+ /** Digest over every surface: name-sorted, with each name hashed alongside its text. */
675
+ digest: string;
676
+ /** Per-surface digest, keyed by a stable surface name. */
677
+ surfaces: Record<string, string>;
678
+ }
679
+ /**
680
+ * Fingerprint an arbitrary surface map. The core; both helpers below funnel through it.
681
+ *
682
+ * The total digest hashes each surface's **name and text together**, name-sorted. Including the name
683
+ * is what stops two different arrangements of the same strings — a prompt moved from one subagent to
684
+ * another, say — from colliding; sorting is what makes the result independent of key order.
685
+ */
686
+ declare function fingerprintSurfaces(surfaces: Record<string, string>): PromptFingerprint;
687
+ /**
688
+ * The prompt surfaces of the `query()` options a host is about to send.
689
+ *
690
+ * **This is the primitive, not {@link promptSurfaces}.** A host may assemble its own options from a
691
+ * plan rather than sending the plan's verbatim — the BIRD-Interact adapter does exactly that,
692
+ * replacing the system prompt with the component's `prompt_fragment` — and fingerprinting the plan
693
+ * in that case would record something other than what was sent. A fingerprint describing a prompt
694
+ * nobody received is worse than no fingerprint, because it reads as evidence.
695
+ *
696
+ * So take it as late as possible: over the options that actually reach `query()`.
697
+ */
698
+ declare function promptSurfacesOf(options: Options): Record<string, string>;
699
+ /**
700
+ * The prompt surfaces a plan **itself** determines — what the single and split paths send verbatim.
701
+ *
702
+ * Surfaces are **named, not positional**, so a plan that gains or loses a subagent changes which
703
+ * keys exist rather than silently shifting every digest after the insertion point.
704
+ *
705
+ * **What this deliberately does NOT cover, and why it would be wrong to.** A staged step is not sent
706
+ * as its `prompt`: the executor prepends a runtime preamble built from the working directory, and
707
+ * the hybrid-tool path sends a driver prompt it composes from the step list, which appears nowhere in
708
+ * the plan's options. Recording a `step.<name>` digest of the bare `prompt` here would produce a
709
+ * fingerprint that does not match the bytes sent — the exact failure this module's header calls worse
710
+ * than no fingerprint, because it reads as evidence. Reproducing the assembly here instead would
711
+ * duplicate it and drift.
712
+ *
713
+ * So those paths are fingerprinted where the bytes exist: `runDispatch` reports one fingerprint per
714
+ * turn it sends, through `RunConfig.onPromptFingerprint`. Use that for anything staged or hybrid; use
715
+ * this for a plan whose options go out as built.
716
+ *
717
+ * One surface that looks missing and is not: on the single-tier (collapse) path a component's
718
+ * `prompt_fragment` is folded into `systemPrompt`, and `llm_calls[].prompt` is not read at all. So a
719
+ * one-step component's step text is covered through the driver surface rather than a step surface.
720
+ */
721
+ declare function promptSurfaces(plan: DispatchPlan): Record<string, string>;
722
+ /** Fingerprint the prompts a plan assembled. See {@link promptSurfaces} on when this is the wrong one. */
723
+ declare function fingerprintPrompts(plan: DispatchPlan): PromptFingerprint;
724
+
725
+ /**
726
+ * Compose an embedding host's `canUseTool` with a guardrail floor's, so a host can add its own
727
+ * enforcement instead of having to choose between the two. Without this an embedder's callback is
728
+ * silently replaced, which is the same failure whichever way round it happens.
729
+ *
730
+ * **The order is load-bearing: the embedder runs first, the floor runs last.** A `canUseTool` may
731
+ * rewrite a tool's input on the way through (`updatedInput`), so a floor that ran first would be
732
+ * inspecting an input the embedder could still change afterwards — the floor has to see what the
733
+ * tool will actually receive. Running it last is what makes composition one-directional: either side
734
+ * may deny, neither can turn the other's denial into an allow, and an allowed input has passed
735
+ * through both.
736
+ *
737
+ * An embedder denial returns immediately without consulting the floor, so the floor's `denials`
738
+ * ledger stays a record of guardrail enforcement rather than a mixed log of both parties.
739
+ *
740
+ * With no embedder callback the floor's own callback is returned unchanged, so a run without an
741
+ * embedder behaves exactly as it did before this seam existed.
742
+ */
743
+ declare function composeCanUseTool(embedder: CanUseTool | undefined, floor: CanUseTool): CanUseTool;
744
+ /**
745
+ * Merge an embedding host's `hooks` with a guardrail's `PreToolUse` matchers, appending the
746
+ * guardrail's so the host's run first and neither set is dropped.
747
+ *
748
+ * This is the shape the main dispatch path already used inline; it is extracted here so the staged
749
+ * and hybrid-tool paths can stop discarding the host's hooks, and so there is one place to read
750
+ * rather than three to keep in step. `PreToolUse` is a separate control path from `canUseTool` (see
751
+ * `makeSetupReadDenyHook` below for the empirical note), which is why both have to compose.
752
+ */
753
+ declare function composeHooks(embedder: Options["hooks"], guardHooks: HookCallbackMatcher[]): Options["hooks"];
638
754
  /** A blocked tool call, recorded so the trace/report can prove enforcement actually fired. */
639
755
  interface Denial {
640
756
  tool: string;
@@ -757,6 +873,19 @@ interface RunConfig {
757
873
  * message stream is consumed, not batched after the fact. Only wired on the main (single/split) SDK
758
874
  * loop below — the hybrid-staged executor passes through with no events. */
759
875
  onEvent?: (event: WarbleChatEvent) => void;
876
+ /**
877
+ * Called once per turn this run sends, with a fingerprint of the prompts THAT turn carried.
878
+ *
879
+ * Reported here rather than derived from the plan because the staged and hybrid paths do not send
880
+ * the plan's text as built: a step's options carry a runtime preamble ahead of its prompt, and the
881
+ * hybrid-tool driver composes a prompt that appears nowhere in the plan. A plan-derived digest
882
+ * would name bytes that were never sent, which is worse than none — it reads as evidence.
883
+ *
884
+ * Several turns therefore report several fingerprints. A consumer that wants one value per run
885
+ * should deduplicate by digest: one entry means the prompts held steady, more than one means they
886
+ * changed across the run, which is itself the finding.
887
+ */
888
+ onPromptFingerprint?: (fingerprint: PromptFingerprint) => void;
760
889
  }
761
890
  /**
762
891
  * A dispatch failure that still carries the SDK's session id, when the result message had one —
@@ -787,6 +916,78 @@ declare function buildToolDriverPrompt(steps: readonly StagedStep[]): string;
787
916
  */
788
917
  declare function runHybridTool(plan: DispatchPlan, cfg: RunConfig): Promise<RunResult>;
789
918
 
919
+ /**
920
+ * What a host says about each slot, keyed by slot name:
921
+ *
922
+ * - a string — render this variant;
923
+ * - `null` — the slot's `present_when` does not hold, so remove it entirely;
924
+ * - absent — the host has no opinion, so render the declared `default`.
925
+ *
926
+ * A plain table rather than a callback, so what the model was told is decided before the run rather
927
+ * than during it: it can be recorded, compared and fingerprinted. A callback could not be.
928
+ */
929
+ type SlotSupply = Readonly<Record<string, string | null>>;
930
+ /**
931
+ * What to do with a conditional slot the host did not answer.
932
+ *
933
+ * `"fail"` on any path whose text reaches a model: `default` covers "no opinion on the wording", and
934
+ * it cannot cover "no opinion on whether this exists at all" — defaulting there ships instructions
935
+ * for a capability that may have been withheld, which is the failure `present_when` exists to
936
+ * prevent.
937
+ *
938
+ * `"default"` on a display path. The rule above protects a model, not a reader, and a structural
939
+ * view that refuses to render a valid profile is worse than one showing the default wording. Note
940
+ * this is a real difference in meaning, not a relaxation for convenience: a display says "this is
941
+ * what the default binding would say", never "this is what will be sent".
942
+ */
943
+ type UnansweredCondition = "fail" | "default";
944
+ /**
945
+ * Resolve each declared slot to the text that will replace its references, or to `null` when the
946
+ * host said it is not present.
947
+ *
948
+ * A slot's chosen variant may itself reference other slots — the compiler collects references from
949
+ * variant text and validates them, so this is authored-legal — hence the recursion, with a visiting
950
+ * set so a cycle is reported rather than spun on.
951
+ *
952
+ * @param decls every slot in scope for the text being resolved. That is the profile's slots PLUS
953
+ * the component's, together: compile checks the two layers separately, but it also folds the
954
+ * profile's `system_prompt` into each component's `brief` (`render_brief`), so by the time a
955
+ * consumer sees the IR one string carries references from both. Names are unique project-wide —
956
+ * compile refuses a collision — which is what makes one combined table unambiguous.
957
+ * @param supply the host's table.
958
+ * @param scope names the scope in errors ("component 'x'").
959
+ */
960
+ declare function resolveSlots(decls: readonly SlotDecl[], supply: SlotSupply, scope: string, unanswered?: UnansweredCondition): ReadonlyMap<string, string | null>;
961
+ /**
962
+ * Apply a resolved scope to one piece of prompt text.
963
+ *
964
+ * A slot resolved to `null` leaves nothing behind — deliberately the empty string rather than any
965
+ * variant, since the point of a condition that does not hold is that the wording must not appear.
966
+ */
967
+ declare function applySlots(raw: string, resolved: ReadonlyMap<string, string | null>, scope: string): string;
968
+ /**
969
+ * Refuse prompt text that still carries a slot reference.
970
+ *
971
+ * The guard, not a formality. Every other failure in this file is loud on its own; this one catches
972
+ * the case where a surface was never routed through {@link applySlots} at all — a new prompt-carrying
973
+ * field, a path that assembles text somewhere unexpected — which is exactly how the original defect
974
+ * arrived: the IR grew slots and nothing downstream was taught to consume them.
975
+ */
976
+ declare function assertNoSlotReferences(raw: string, owner: string): void;
977
+ /**
978
+ * Parse repeated `--slot name=variant` / `--slot name=` flags into a {@link SlotSupply}.
979
+ *
980
+ * Lives here rather than in the CLI so it is reachable by a test and by any host that wants the same
981
+ * surface; the CLI turns the thrown error into its own usage failure. Mirrors the Rust CLI's flag of
982
+ * the same name — two user-facing surfaces that disagreed about what `name=` means would be worse
983
+ * than either one alone.
984
+ *
985
+ * An empty value is **not** an empty variant name: it is the host saying the slot's condition does
986
+ * not hold and the wording must not appear at all. That distinction is why the flag takes a trailing
987
+ * `=` rather than requiring a variant.
988
+ */
989
+ declare function parseSlotFlags(flags: readonly string[]): SlotSupply;
990
+
790
991
  interface RenderResult {
791
992
  outPath: string;
792
993
  /** stderr from `warble render` (it logs "wrote … (N block(s))"). */
@@ -910,6 +1111,16 @@ declare function createChatSession(plan: DispatchPlan, runCfg: RunConfig, initia
910
1111
  interface DispatchInput {
911
1112
  /** A parsed IR or a raw JSON string. */
912
1113
  ir: WarbleIr | string;
1114
+ /**
1115
+ * What this host says about each declared slot: a variant name to render, `null` to remove the
1116
+ * slot because its `present_when` does not hold, or nothing at all to take the declared default.
1117
+ *
1118
+ * The IR carries every variant and picks none — picking is the host's job, and so is answering a
1119
+ * condition. Omit this entirely for an IR that declares no slots; supplying it then is harmless
1120
+ * but pointless. An IR that DOES declare a conditional slot and gets no answer for it is a loud
1121
+ * failure rather than a silent default (see `resolveSlots`).
1122
+ */
1123
+ slots?: SlotSupply;
913
1124
  /** The data question to answer (the `query()` prompt). Optional for prepare-only (dry-run/emit). */
914
1125
  question?: string;
915
1126
  target?: string;
@@ -962,7 +1173,24 @@ interface UnavailableDisplayComponent {
962
1173
  reason: typeof UNAVAILABLE_COMPONENT_REASON;
963
1174
  };
964
1175
  }
965
- type DisplayComponent = PreparedComponent | UnavailableDisplayComponent;
1176
+ /**
1177
+ * A component in a display manifest that the target CAN run.
1178
+ *
1179
+ * Deliberately **not** a {@link PreparedComponent}: it carries no `plan`. A plan built for a display
1180
+ * is resolved under the lenient unanswered-condition policy, so handing one out would let a consumer
1181
+ * do the natural "preview it, then dispatch what was previewed" — `runDispatch(component.plan, cfg)`
1182
+ * type-checks with no cast — and send a model wording for a condition nobody ever answered. That is
1183
+ * exactly the failure the strict policy exists to prevent, arriving through the display door.
1184
+ *
1185
+ * A plan is still built during preparation, because that is what surfaces an unsupported enum as a
1186
+ * wall-hit; it is discarded rather than returned. Nothing in the manifest builders reads it.
1187
+ */
1188
+ interface AvailableDisplayComponent {
1189
+ id: string;
1190
+ node: ComponentNode;
1191
+ report: ResolutionReport;
1192
+ }
1193
+ type DisplayComponent = AvailableDisplayComponent | UnavailableDisplayComponent;
966
1194
  interface PreparedDisplayManifest {
967
1195
  target: string;
968
1196
  components: DisplayComponent[];
@@ -1132,7 +1360,12 @@ interface Manifest {
1132
1360
  }
1133
1361
  /** Port of `emit.rs::build_agent_bundle`, minus the tool-map parameter (this back-end's is fixed,
1134
1362
  * see `LOCAL_TOOL_MAP`). */
1135
- declare function buildAgentManifest(component: PreparedComponent): AvailableAgentManifest;
1363
+ /**
1364
+ * Takes the plan-less display shape deliberately. A {@link PreparedComponent} is still accepted —
1365
+ * it satisfies this structurally — but nothing here reads a plan, so nothing here should require
1366
+ * one; see `AvailableDisplayComponent` for why a display must not carry it.
1367
+ */
1368
+ declare function buildAgentManifest(component: AvailableDisplayComponent): AvailableAgentManifest;
1136
1369
  /** Never derives a plan, tool, or capability grant for an unavailable component. */
1137
1370
  declare function buildUnavailableAgentManifest(component: UnavailableDisplayComponent): UnavailableAgentManifest;
1138
1371
  /** Build the full display manifest for a `prepareDispatch` result. `raw` is the same IR the
@@ -1140,4 +1373,4 @@ declare function buildUnavailableAgentManifest(component: UnavailableDisplayComp
1140
1373
  * `profile`, which `PreparedDispatch` does not itself carry. */
1141
1374
  declare function buildManifest(prepared: PreparedDispatch | PreparedDisplayManifest, raw: string): Manifest;
1142
1375
 
1143
- export { type AgentManifest, type AskOptions, type AvailableAgentManifest, type BuildConfig, COMPONENT_TYPES, type CallLocalOptions, type CapabilityEntry, type CapabilityOutcome, type CapabilityProfile, type ChatRequest, ChatSession, type ClarifyOutcome, type CompatibilityPolicy, type ComponentNode, type ComponentOutcome, type ComponentType, type ContextBinding, type Criticality, DEFAULT_CLARIFY_THRESHOLD, DEFAULT_RENDER_FLAVOR, DEFAULT_TARGET, DESTRUCTIVE_BASH_DENY, type Denial, type DiscoverClaudeModelsOptions, DispatchError, type DispatchInput, type DispatchMeta, type DispatchOutcome, type DispatchPlan, type DispatchRunConfig, DispatchSessionError, type DisplayComponent, type Effect, type EmitOptions, type GateFailureMode, type GateKind, type GuardConfig, type Guardrail, type GuardrailManifest, type IrConfig, type LlmCall, MODEL_CATALOG_VERSION, type Manifest, type ModelCatalogModel, type ModelCatalogResult, type ModelCatalogUnavailableCode, ModelConfig, OUTCOME_KINDS, type Outcome, type OutcomeKind, type PreconditionResult, type PreparedComponent, type PreparedDispatch, type PreparedDisplayManifest, type ProvidedBy, type Provider, REALIZATION_KINDS, type RealizationKind, type RenderBlock, type RenderFlavor, type RenderGate, type RenderResult, type ResolutionReport, type ResolvedCapability, type ResolvedIntent, type RoutingMode, type RoutingPlan, type RunConfig, type RunResult, SUPPORTED_IR_VERSIONS, type SessionState, type StagedStep, type StepManifest, type StepMessage, type StepRealization, type StepUsage, TRIGGER_KINDS, type TargetId, type TierBinding, type ToolPlan, type ToolRef, type Trace, type Trigger, type TriggerKind, type Turn, type TurnResult, UNAVAILABLE_COMPONENT_REASON, type UnavailableAgentManifest, type UnavailableDisplayComponent, type WarbleIr, type WhenGuardOut, aggregateTrace, appendTurn, buildAgentManifest, buildChatRequest, buildDispatchPlan, buildManifest, buildStepMessages, buildToolDriverPrompt, buildTurnPrompt, buildUnavailableAgentManifest, callOpenAiCompat, collectRequiredCapabilities, createChatSession, createSessionState, decideClarify, discoverClaudeModels, dispatch, distillFollowup, distinctProviders, distinctTiers, emitAgentModule, extractCompletionText, inspectNodeCapabilities, isKnownTarget, knownTargetNames, lastResolvedIntent, lastSessionId, localProfile, makeReadOnlyGuard, parseIr, parseRenderFlavor, planProviderRouting, prepareDispatch, prepareDisplayManifest, profileFor, renderEnvelope, resolveCapabilities, resolveNodeCapabilities, resolveProjectCwd, resolveStagedSteps, runDispatch, runHybridTool, shouldSplitPerStepTier, usesLocalProvider };
1376
+ export { type AgentManifest, type AskOptions, type AvailableAgentManifest, type AvailableDisplayComponent, type BuildConfig, COMPONENT_TYPES, type CallLocalOptions, type CapabilityEntry, type CapabilityOutcome, type CapabilityProfile, type ChatRequest, ChatSession, type ClarifyOutcome, type CompatibilityPolicy, type ComponentNode, type ComponentOutcome, type ComponentType, type ContextBinding, type Criticality, DEFAULT_CLARIFY_THRESHOLD, DEFAULT_RENDER_FLAVOR, DEFAULT_TARGET, DESTRUCTIVE_BASH_DENY, type Denial, type DiscoverClaudeModelsOptions, DispatchError, type DispatchInput, type DispatchMeta, type DispatchOutcome, type DispatchPlan, type DispatchRunConfig, DispatchSessionError, type DisplayComponent, type Effect, type EmitOptions, type GateFailureMode, type GateKind, type GuardConfig, type Guardrail, type GuardrailManifest, type IrConfig, type LlmCall, MODEL_CATALOG_VERSION, type Manifest, type ModelCatalogModel, type ModelCatalogResult, type ModelCatalogUnavailableCode, ModelConfig, OUTCOME_KINDS, type Outcome, type OutcomeKind, type PreconditionResult, type PreparedComponent, type PreparedDispatch, type PreparedDisplayManifest, type PromptFingerprint, type ProvidedBy, type Provider, REALIZATION_KINDS, type RealizationKind, type RenderBlock, type RenderFlavor, type RenderGate, type RenderResult, type ResolutionReport, type ResolvedCapability, type ResolvedIntent, type RoutingMode, type RoutingPlan, type RunConfig, type RunResult, SUPPORTED_IR_VERSIONS, type SessionState, type SlotSupply, type StagedStep, type StepManifest, type StepMessage, type StepRealization, type StepUsage, TRIGGER_KINDS, type TargetId, type TierBinding, type ToolPlan, type ToolRef, type Trace, type Trigger, type TriggerKind, type Turn, type TurnResult, UNAVAILABLE_COMPONENT_REASON, type UnansweredCondition, type UnavailableAgentManifest, type UnavailableDisplayComponent, type WarbleIr, type WhenGuardOut, aggregateTrace, appendTurn, applySlots, assertNoSlotReferences, buildAgentManifest, buildChatRequest, buildDispatchPlan, buildManifest, buildStepMessages, buildToolDriverPrompt, buildTurnPrompt, buildUnavailableAgentManifest, callOpenAiCompat, collectRequiredCapabilities, composeCanUseTool, composeHooks, createChatSession, createSessionState, decideClarify, discoverClaudeModels, dispatch, distillFollowup, distinctProviders, distinctTiers, emitAgentModule, extractCompletionText, fingerprintPrompts, fingerprintSurfaces, inspectNodeCapabilities, isKnownTarget, knownTargetNames, lastResolvedIntent, lastSessionId, localProfile, makeReadOnlyGuard, parseIr, parseRenderFlavor, parseSlotFlags, planProviderRouting, prepareDispatch, prepareDisplayManifest, profileFor, promptSurfaces, promptSurfacesOf, renderEnvelope, resolveCapabilities, resolveNodeCapabilities, resolveProjectCwd, resolveSlots, resolveStagedSteps, runDispatch, runHybridTool, shouldSplitPerStepTier, usesLocalProvider };
package/dist/index.js CHANGED
@@ -16,6 +16,8 @@ import {
16
16
  UNAVAILABLE_COMPONENT_REASON,
17
17
  aggregateTrace,
18
18
  appendTurn,
19
+ applySlots,
20
+ assertNoSlotReferences,
19
21
  buildAgentManifest,
20
22
  buildChatRequest,
21
23
  buildDispatchPlan,
@@ -26,6 +28,8 @@ import {
26
28
  buildUnavailableAgentManifest,
27
29
  callOpenAiCompat,
28
30
  collectRequiredCapabilities,
31
+ composeCanUseTool,
32
+ composeHooks,
29
33
  createChatSession,
30
34
  createSessionState,
31
35
  decideClarify,
@@ -36,6 +40,8 @@ import {
36
40
  distinctTiers,
37
41
  emitAgentModule,
38
42
  extractCompletionText,
43
+ fingerprintPrompts,
44
+ fingerprintSurfaces,
39
45
  inspectNodeCapabilities,
40
46
  isKnownTarget,
41
47
  knownTargetNames,
@@ -45,20 +51,24 @@ import {
45
51
  makeReadOnlyGuard,
46
52
  parseIr,
47
53
  parseRenderFlavor,
54
+ parseSlotFlags,
48
55
  planProviderRouting,
49
56
  prepareDispatch,
50
57
  prepareDisplayManifest,
51
58
  profileFor,
59
+ promptSurfaces,
60
+ promptSurfacesOf,
52
61
  renderEnvelope,
53
62
  resolveCapabilities,
54
63
  resolveNodeCapabilities,
55
64
  resolveProjectCwd,
65
+ resolveSlots,
56
66
  resolveStagedSteps,
57
67
  runDispatch,
58
68
  runHybridTool,
59
69
  shouldSplitPerStepTier,
60
70
  usesLocalProvider
61
- } from "./chunk-Y5BDZDXF.js";
71
+ } from "./chunk-7XQ5F6FM.js";
62
72
  export {
63
73
  COMPONENT_TYPES,
64
74
  ChatSession,
@@ -77,6 +87,8 @@ export {
77
87
  UNAVAILABLE_COMPONENT_REASON,
78
88
  aggregateTrace,
79
89
  appendTurn,
90
+ applySlots,
91
+ assertNoSlotReferences,
80
92
  buildAgentManifest,
81
93
  buildChatRequest,
82
94
  buildDispatchPlan,
@@ -87,6 +99,8 @@ export {
87
99
  buildUnavailableAgentManifest,
88
100
  callOpenAiCompat,
89
101
  collectRequiredCapabilities,
102
+ composeCanUseTool,
103
+ composeHooks,
90
104
  createChatSession,
91
105
  createSessionState,
92
106
  decideClarify,
@@ -97,6 +111,8 @@ export {
97
111
  distinctTiers,
98
112
  emitAgentModule,
99
113
  extractCompletionText,
114
+ fingerprintPrompts,
115
+ fingerprintSurfaces,
100
116
  inspectNodeCapabilities,
101
117
  isKnownTarget,
102
118
  knownTargetNames,
@@ -106,14 +122,18 @@ export {
106
122
  makeReadOnlyGuard,
107
123
  parseIr,
108
124
  parseRenderFlavor,
125
+ parseSlotFlags,
109
126
  planProviderRouting,
110
127
  prepareDispatch,
111
128
  prepareDisplayManifest,
112
129
  profileFor,
130
+ promptSurfaces,
131
+ promptSurfacesOf,
113
132
  renderEnvelope,
114
133
  resolveCapabilities,
115
134
  resolveNodeCapabilities,
116
135
  resolveProjectCwd,
136
+ resolveSlots,
117
137
  resolveStagedSteps,
118
138
  runDispatch,
119
139
  runHybridTool,