@elie-laloum/outpost 9.1.1 → 10.0.1

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.
Files changed (69) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/dist/application/dispatch-validation.js +3 -6
  3. package/dist/application/dispatch-validation.js.map +1 -1
  4. package/dist/application/execution.js +8 -17
  5. package/dist/application/execution.js.map +1 -1
  6. package/dist/application/interactive-task-protocol.js +2 -0
  7. package/dist/application/interactive-task-protocol.js.map +1 -1
  8. package/dist/application/interactive-task.constants.d.ts +53 -0
  9. package/dist/application/interactive-task.constants.js +29 -0
  10. package/dist/application/interactive-task.constants.js.map +1 -1
  11. package/dist/application/steering-turns.js +12 -1
  12. package/dist/application/steering-turns.js.map +1 -1
  13. package/dist/application/workflow-job.js +4 -1
  14. package/dist/application/workflow-job.js.map +1 -1
  15. package/dist/domain/errors.types.d.ts +1 -1
  16. package/dist/domain/errors.types.js.map +1 -1
  17. package/dist/domain/replay.constants.js +1 -0
  18. package/dist/domain/replay.constants.js.map +1 -1
  19. package/dist/domain/replay.js +4 -0
  20. package/dist/domain/replay.js.map +1 -1
  21. package/dist/domain/response-instructions.d.ts +2 -0
  22. package/dist/domain/response-instructions.js +20 -0
  23. package/dist/domain/response-instructions.js.map +1 -0
  24. package/dist/domain/response-schema.d.ts +4 -0
  25. package/dist/domain/response-schema.js +46 -0
  26. package/dist/domain/response-schema.js.map +1 -0
  27. package/dist/domain/response.js +8 -3
  28. package/dist/domain/response.js.map +1 -1
  29. package/dist/domain/response.types.d.ts +10 -2
  30. package/dist/domain/response.types.js.map +1 -1
  31. package/dist/domain/standard-schema.constants.d.ts +1 -0
  32. package/dist/domain/standard-schema.constants.js +2 -0
  33. package/dist/domain/standard-schema.constants.js.map +1 -0
  34. package/dist/domain/standard-schema.js +1 -1
  35. package/dist/domain/standard-schema.js.map +1 -1
  36. package/dist/domain/tool.constants.d.ts +0 -1
  37. package/dist/domain/tool.constants.js +0 -1
  38. package/dist/domain/tool.constants.js.map +1 -1
  39. package/dist/domain/workflow/failure.d.ts +2 -1
  40. package/dist/domain/workflow/failure.js +2 -0
  41. package/dist/domain/workflow/failure.js.map +1 -1
  42. package/dist/domain/workflow/gates.js +6 -1
  43. package/dist/domain/workflow/gates.js.map +1 -1
  44. package/dist/domain/workflow/loop-runner.js +8 -1
  45. package/dist/domain/workflow/loop-runner.js.map +1 -1
  46. package/dist/domain/workflow/task-runner.js +6 -2
  47. package/dist/domain/workflow/task-runner.js.map +1 -1
  48. package/dist/domain/workflow/termination.d.ts +3 -0
  49. package/dist/domain/workflow/termination.js +29 -0
  50. package/dist/domain/workflow/termination.js.map +1 -0
  51. package/dist/domain/workflow/workflow-scheduler.js +9 -18
  52. package/dist/domain/workflow/workflow-scheduler.js.map +1 -1
  53. package/dist/domain/workflow/workflow-state.js +6 -1
  54. package/dist/domain/workflow/workflow-state.js.map +1 -1
  55. package/dist/domain/workflow.d.ts +1 -1
  56. package/dist/domain/workflow.js.map +1 -1
  57. package/dist/domain/workflow.types.d.ts +5 -1
  58. package/dist/domain/workflow.types.js.map +1 -1
  59. package/dist/index.d.ts +1 -1
  60. package/dist/index.js.map +1 -1
  61. package/dist/providers/daytona.js +3 -0
  62. package/dist/providers/daytona.js.map +1 -1
  63. package/dist/providers/daytona.types.d.ts +1 -0
  64. package/dist/providers/daytona.types.js.map +1 -1
  65. package/dist/providers/vercel.js +3 -1
  66. package/dist/providers/vercel.js.map +1 -1
  67. package/dist/providers/vercel.types.d.ts +1 -0
  68. package/dist/providers/vercel.types.js.map +1 -1
  69. package/package.json +4 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # Changelog
2
2
 
3
+ ## Unreleased
4
+
5
+ ## 10.0.1
6
+
7
+ - **Breaking:** Report gate refusals as workflow status `rejected`. Add typed `terminationCode` to workflow results, finish events and queued workflow summaries, and expose it on `WorkflowFailure.code`; preserve classified faults, deadlines, budget stops and checkpointed rejection audit trails. Consumers checking only `failed` must also handle `rejected`. Deterministic regression tests cover the termination semantics; no live agent or provider calls are required.
8
+ - Accept explicit `repositoryMode: "isolated"` on Vercel and Daytona, matching their existing private-checkout default. Reject unsupported modes before allocation. Deterministic provider fixtures verify Git metadata separation, commit/file synchronization and recovery after concurrent host edits; live cloud validation of this explicit option remains outstanding.
9
+ - Automatically append tagged final-answer instructions and input JSON Schema for typed responses, including repairs and resumed turns. **Breaking:** `defineJsonResponse()` now requires Standard JSON Schema conversion or an explicit `jsonSchema`; parsing functions and validation-only schemas must declare their input schema. Existing parsing and validation behavior is preserved.
10
+ - Update the bilingual guides, API reference and offline examples. Deterministic tests do not establish live agent compliance with the injected instructions.
11
+ - Pin the transitive `shell-quote` dependency to 1.11.0 and documentation `sharp` to 0.35.5 to resolve the dependency audits blocking CI.
12
+ - Resume quota-interrupted workflow fixtures explicitly from durable checkpoints, preserving conversation continuation and fallback checks without relying on process startup completing before a simulated reset.
13
+
14
+ The v10.0.0 release was blocked by a timing-sensitive Windows fixture and was not published.
15
+
3
16
  ## 9.1.1
4
17
 
5
18
  - Add typed System One decisions (`defineDecision`, `decide`, `defineDecisionTask`) and one bounded HTTP provider for Jev and compatible Laya endpoints. Preserve native distributions, metadata and input-truncation diagnostics.
@@ -1,7 +1,6 @@
1
- import { readFile } from "node:fs/promises";
2
- import { resolve } from "node:path";
3
1
  import { invariant, positive } from "../domain/errors.js";
4
2
  import { validateBrief } from "../domain/prompts.js";
3
+ import { responseInstructions } from "../domain/response-instructions.js";
5
4
  import { steeringChannel } from "../domain/steering.js";
6
5
  import { dispatchDeadlines, executionDefaults } from "./execution.constants.js";
7
6
  export function validateDispatch(options) {
@@ -9,6 +8,8 @@ export function validateDispatch(options) {
9
8
  if (options.steering)
10
9
  steeringChannel(options.steering);
11
10
  validateBrief(options.brief);
11
+ if (options.response)
12
+ responseInstructions(options.response);
12
13
  positive(options.passes ?? executionDefaults.passes, "passes");
13
14
  invariant(Number.isSafeInteger(options.passes ?? executionDefaults.passes), "passes must be an integer");
14
15
  for (const key of dispatchDeadlines)
@@ -35,10 +36,6 @@ export async function preflightDispatch(options, _repository, agent) {
35
36
  return;
36
37
  if (options.response.repairs > 0)
37
38
  invariant(agent?.resumable ?? !!agent?.storage, "Response repair requires an adapter that supports continuation");
38
- const brief = options.brief;
39
- const text = brief.text ?? (await readFile(resolve(brief.file), "utf8"));
40
- const resolved = text.replace(/\{\{\s*(\w+)\s*\}\}/g, (token, key) => brief.values?.[key] === undefined ? token : String(brief.values[key]));
41
- invariant(resolved.includes(`<${options.response.tag}>`), `Brief must request an opening <${options.response.tag}> tag`);
42
39
  }
43
40
  function validateSteering(agent) {
44
41
  invariant(agent.kind !== "replay", "Replay agents reproduce a recording and cannot be steered");
@@ -1 +1 @@
1
- {"version":3,"file":"dispatch-validation.js","sourceRoot":"","sources":["../../src/application/dispatch-validation.ts"],"names":[],"mappings":"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","sourcesContent":["import { readFile } from \"node:fs/promises\";\nimport { resolve } from \"node:path\";\nimport type { Agent } from \"../domain/agent.types.ts\";\nimport { invariant, positive } from \"../domain/errors.ts\";\nimport { validateBrief } from \"../domain/prompts.ts\";\nimport { steeringChannel } from \"../domain/steering.ts\";\nimport { dispatchDeadlines, executionDefaults } from \"./execution.constants.ts\";\nimport type { DispatchOptions } from \"./execution.types.ts\";\n\nexport function validateDispatch(options: DispatchOptions<unknown>): void {\n options.signal?.throwIfAborted();\n if (options.steering) steeringChannel(options.steering);\n validateBrief(options.brief);\n positive(options.passes ?? executionDefaults.passes, \"passes\");\n invariant(\n Number.isSafeInteger(options.passes ?? executionDefaults.passes),\n \"passes must be an integer\",\n );\n for (const key of dispatchDeadlines)\n if (options[key] !== undefined) positive(options[key], key);\n if (options.response || options.continuation)\n invariant(\n (options.passes ?? executionDefaults.passes) === 1,\n \"Structured responses and continuations require one pass\",\n );\n const markers =\n options.until === undefined\n ? []\n : typeof options.until === \"string\"\n ? [options.until]\n : options.until;\n invariant(\n markers.every((marker) => marker.length > 0),\n \"Completion markers cannot be empty\",\n );\n}\n\nexport async function preflightDispatch(\n options: DispatchOptions<unknown>,\n _repository: string,\n agent?: Agent,\n): Promise<void> {\n validateDispatch(options);\n if (options.steering && agent) validateSteering(agent);\n if (options.continuation)\n invariant(\n agent?.resumable !== false,\n `${agent?.name} does not support continuation or fork in Outpost`,\n );\n if (options.continuation?.fork)\n invariant(\n agent?.forkable !== false,\n `${agent?.name} does not support automated fork in Outpost`,\n );\n if (!options.response) return;\n if (options.response.repairs > 0)\n invariant(\n agent?.resumable ?? !!agent?.storage,\n \"Response repair requires an adapter that supports continuation\",\n );\n const brief = options.brief;\n const text = brief.text ?? (await readFile(resolve(brief.file!), \"utf8\"));\n const resolved = text.replace(/\\{\\{\\s*(\\w+)\\s*\\}\\}/g, (token, key: string) =>\n brief.values?.[key] === undefined ? token : String(brief.values[key]),\n );\n invariant(\n resolved.includes(`<${options.response.tag}>`),\n `Brief must request an opening <${options.response.tag}> tag`,\n );\n}\n\nfunction validateSteering(agent: Agent): void {\n invariant(\n agent.kind !== \"replay\",\n \"Replay agents reproduce a recording and cannot be steered\",\n );\n invariant(\n agent.kind === \"custom\" || agent.liveInput || agent.resumable,\n `${agent.name} cannot be steered: it accepts no live input and cannot resume its conversation`,\n );\n}\n"]}
1
+ {"version":3,"file":"dispatch-validation.js","sourceRoot":"","sources":["../../src/application/dispatch-validation.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Agent } from \"../domain/agent.types.ts\";\nimport { invariant, positive } from \"../domain/errors.ts\";\nimport { validateBrief } from \"../domain/prompts.ts\";\nimport { responseInstructions } from \"../domain/response-instructions.ts\";\nimport { steeringChannel } from \"../domain/steering.ts\";\nimport { dispatchDeadlines, executionDefaults } from \"./execution.constants.ts\";\nimport type { DispatchOptions } from \"./execution.types.ts\";\n\nexport function validateDispatch(options: DispatchOptions<unknown>): void {\n options.signal?.throwIfAborted();\n if (options.steering) steeringChannel(options.steering);\n validateBrief(options.brief);\n if (options.response) responseInstructions(options.response);\n positive(options.passes ?? executionDefaults.passes, \"passes\");\n invariant(\n Number.isSafeInteger(options.passes ?? executionDefaults.passes),\n \"passes must be an integer\",\n );\n for (const key of dispatchDeadlines)\n if (options[key] !== undefined) positive(options[key], key);\n if (options.response || options.continuation)\n invariant(\n (options.passes ?? executionDefaults.passes) === 1,\n \"Structured responses and continuations require one pass\",\n );\n const markers =\n options.until === undefined\n ? []\n : typeof options.until === \"string\"\n ? [options.until]\n : options.until;\n invariant(\n markers.every((marker) => marker.length > 0),\n \"Completion markers cannot be empty\",\n );\n}\n\nexport async function preflightDispatch(\n options: DispatchOptions<unknown>,\n _repository: string,\n agent?: Agent,\n): Promise<void> {\n validateDispatch(options);\n if (options.steering && agent) validateSteering(agent);\n if (options.continuation)\n invariant(\n agent?.resumable !== false,\n `${agent?.name} does not support continuation or fork in Outpost`,\n );\n if (options.continuation?.fork)\n invariant(\n agent?.forkable !== false,\n `${agent?.name} does not support automated fork in Outpost`,\n );\n if (!options.response) return;\n if (options.response.repairs > 0)\n invariant(\n agent?.resumable ?? !!agent?.storage,\n \"Response repair requires an adapter that supports continuation\",\n );\n}\n\nfunction validateSteering(agent: Agent): void {\n invariant(\n agent.kind !== \"replay\",\n \"Replay agents reproduce a recording and cannot be steered\",\n );\n invariant(\n agent.kind === \"custom\" || agent.liveInput || agent.resumable,\n `${agent.name} cannot be steered: it accepts no live input and cannot resume its conversation`,\n );\n}\n"]}
@@ -1,4 +1,3 @@
1
- import { invariant } from "../domain/errors.js";
2
1
  import { ResponseError } from "../domain/response.js";
3
2
  import { addUsage } from "../domain/usage.js";
4
3
  import { turn } from "./agent-turn.js";
@@ -36,23 +35,15 @@ export async function execute(workspace, lease, agent, host, options, afterTurn)
36
35
  });
37
36
  const prompt = repair ??
38
37
  (await renderBrief(options.brief, workspace, lease, host, options));
39
- if (options.response && !repair)
40
- invariant(prompt.includes(`<${options.response.tag}>`), `Brief must request an opening <${options.response.tag}> tag`);
41
- notify(options.observe, {
42
- kind: "prompt",
43
- text: prompt,
44
- pass: index + 1,
45
- at: new Date().toISOString(),
46
- });
47
- notify(options.observe, {
48
- kind: "phase",
49
- name: "running",
50
- agent: agent.name,
51
- branch: workspace.branch,
52
- pass: index + 1,
53
- at: new Date().toISOString(),
54
- });
55
38
  const steered = await steeringTurns(agent, options, prompt, continuation, index + 1, async (text, resumed) => {
39
+ notify(options.observe, {
40
+ kind: "phase",
41
+ name: "running",
42
+ agent: agent.name,
43
+ branch: workspace.branch,
44
+ pass: index + 1,
45
+ at: new Date().toISOString(),
46
+ });
56
47
  const finished = await turn(lease, agent, text, options, resumed, markers, index + 1, { repository: workspace.repository, repair: repair !== undefined });
57
48
  return afterTurn ? await afterTurn(finished) : finished;
58
49
  });
@@ -1 +1 @@
1
- {"version":3,"file":"execution.js","sourceRoot":"","sources":["../../src/application/execution.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Agent, Usage } from \"../domain/agent.types.ts\";\nimport { invariant } from \"../domain/errors.ts\";\nimport { ResponseError } from \"../domain/response.ts\";\nimport type { SandboxLease } from \"../domain/sandbox.types.ts\";\nimport { addUsage } from \"../domain/usage.ts\";\nimport type { WorkspaceRecord } from \"../domain/workspace.types.ts\";\nimport { turn } from \"./agent-turn.ts\";\nimport { steeringTurns } from \"./steering-turns.ts\";\nimport { renderBrief } from \"./brief-renderer.ts\";\nimport { validateDispatch } from \"./dispatch-validation.ts\";\nimport { executionDefaults } from \"./execution.constants.ts\";\nimport type { DispatchOptions, Execution, Turn } from \"./execution.types.ts\";\nimport { notify } from \"./observation.ts\";\n\nexport { renderBrief } from \"./brief-renderer.ts\";\nexport { preflightDispatch, validateDispatch } from \"./dispatch-validation.ts\";\nexport type { DispatchOptions, Execution, Turn } from \"./execution.types.ts\";\nexport { notify } from \"./observation.ts\";\n\nexport async function execute<T>(\n workspace: WorkspaceRecord,\n lease: SandboxLease,\n agent: Agent,\n host: boolean,\n options: DispatchOptions<T>,\n afterTurn?: (turn: Turn) => Promise<Turn>,\n): Promise<Execution<T>> {\n validateDispatch(options);\n const markers =\n options.until === undefined\n ? [executionDefaults.completion]\n : typeof options.until === \"string\"\n ? [options.until]\n : options.until;\n const turns: Turn[] = [];\n let value: T = undefined as T,\n completed = false,\n continuation = options.continuation;\n let repair: string | undefined;\n const attempts = options.response\n ? 1 + options.response.repairs\n : (options.passes ?? executionDefaults.passes);\n for (let index = 0; index < attempts; index++) {\n options.signal?.throwIfAborted();\n notify(options.observe, {\n kind: \"phase\",\n name: \"preparing prompt\",\n agent: agent.name,\n branch: workspace.branch,\n directory: workspace.directory,\n pass: index + 1,\n at: new Date().toISOString(),\n });\n const prompt =\n repair ??\n (await renderBrief(options.brief, workspace, lease, host, options));\n if (options.response && !repair)\n invariant(\n prompt.includes(`<${options.response.tag}>`),\n `Brief must request an opening <${options.response.tag}> tag`,\n );\n notify(options.observe, {\n kind: \"prompt\",\n text: prompt,\n pass: index + 1,\n at: new Date().toISOString(),\n });\n notify(options.observe, {\n kind: \"phase\",\n name: \"running\",\n agent: agent.name,\n branch: workspace.branch,\n pass: index + 1,\n at: new Date().toISOString(),\n });\n const steered = await steeringTurns(\n agent,\n options,\n prompt,\n continuation,\n index + 1,\n async (text, resumed) => {\n const finished = await turn(\n lease,\n agent,\n text,\n options,\n resumed,\n markers,\n index + 1,\n { repository: workspace.repository, repair: repair !== undefined },\n );\n return afterTurn ? await afterTurn(finished) : finished;\n },\n );\n turns.push(...steered);\n const current = steered.at(-1)!;\n notify(options.observe, {\n kind: \"summary\",\n durationMs: steered.reduce((sum, item) => sum + item.durationMs, 0),\n status: current.status,\n tokens: steered.reduce((sum, item) => addUsage(sum, item.usage), {\n input: 0,\n cached: 0,\n output: 0,\n } as Usage),\n pass: index + 1,\n at: new Date().toISOString(),\n });\n completed = markers.some((marker) => current.text.includes(marker));\n if (options.response) {\n try {\n value = await options.response.read(current.text);\n completed = true;\n break;\n } catch (error) {\n if (!(error instanceof ResponseError)) throw error;\n error.recovery = {\n conversation: current.conversation,\n branch: workspace.branch,\n directory: workspace.directory,\n turns,\n };\n if (index + 1 >= attempts || !current.conversation) throw error;\n continuation = { id: current.conversation };\n repair = [\n `Correct the response inside <${options.response.tag}> and </${options.response.tag}>.`,\n `Validation failure: ${error.message}`,\n `Previous content: ${error.raw ?? \"No complete tagged response was returned.\"}`,\n `Cause: ${error.cause instanceof Error ? error.cause.message : (JSON.stringify(error.cause) ?? \"unspecified\")}`,\n `Further repair attempts after this one: ${attempts - index - 2}.`,\n \"Do not edit files, run commands or continue implementation. Only return the corrected response.\",\n ].join(\"\\n\");\n }\n }\n if (!options.response && completed) break;\n }\n const conversation = turns.at(-1)?.conversation;\n const completion = markers.find((marker) =>\n turns.at(-1)?.text.includes(marker),\n );\n return {\n text: turns.map((item) => item.text).join(\"\\n\"),\n turns,\n value,\n completed,\n ...(completion ? { completion } : {}),\n ...(conversation ? { conversation } : {}),\n usage: turns.reduce((sum, item) => addUsage(sum, item.usage), {\n input: 0,\n cached: 0,\n output: 0,\n } as Usage),\n };\n}\n"]}
1
+ {"version":3,"file":"execution.js","sourceRoot":"","sources":["../../src/application/execution.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Agent, Usage } from \"../domain/agent.types.ts\";\nimport { ResponseError } from \"../domain/response.ts\";\nimport type { SandboxLease } from \"../domain/sandbox.types.ts\";\nimport { addUsage } from \"../domain/usage.ts\";\nimport type { WorkspaceRecord } from \"../domain/workspace.types.ts\";\nimport { turn } from \"./agent-turn.ts\";\nimport { steeringTurns } from \"./steering-turns.ts\";\nimport { renderBrief } from \"./brief-renderer.ts\";\nimport { validateDispatch } from \"./dispatch-validation.ts\";\nimport { executionDefaults } from \"./execution.constants.ts\";\nimport type { DispatchOptions, Execution, Turn } from \"./execution.types.ts\";\nimport { notify } from \"./observation.ts\";\n\nexport { renderBrief } from \"./brief-renderer.ts\";\nexport { preflightDispatch, validateDispatch } from \"./dispatch-validation.ts\";\nexport type { DispatchOptions, Execution, Turn } from \"./execution.types.ts\";\nexport { notify } from \"./observation.ts\";\n\nexport async function execute<T>(\n workspace: WorkspaceRecord,\n lease: SandboxLease,\n agent: Agent,\n host: boolean,\n options: DispatchOptions<T>,\n afterTurn?: (turn: Turn) => Promise<Turn>,\n): Promise<Execution<T>> {\n validateDispatch(options);\n const markers =\n options.until === undefined\n ? [executionDefaults.completion]\n : typeof options.until === \"string\"\n ? [options.until]\n : options.until;\n const turns: Turn[] = [];\n let value: T = undefined as T,\n completed = false,\n continuation = options.continuation;\n let repair: string | undefined;\n const attempts = options.response\n ? 1 + options.response.repairs\n : (options.passes ?? executionDefaults.passes);\n for (let index = 0; index < attempts; index++) {\n options.signal?.throwIfAborted();\n notify(options.observe, {\n kind: \"phase\",\n name: \"preparing prompt\",\n agent: agent.name,\n branch: workspace.branch,\n directory: workspace.directory,\n pass: index + 1,\n at: new Date().toISOString(),\n });\n const prompt =\n repair ??\n (await renderBrief(options.brief, workspace, lease, host, options));\n const steered = await steeringTurns(\n agent,\n options,\n prompt,\n continuation,\n index + 1,\n async (text, resumed) => {\n notify(options.observe, {\n kind: \"phase\",\n name: \"running\",\n agent: agent.name,\n branch: workspace.branch,\n pass: index + 1,\n at: new Date().toISOString(),\n });\n const finished = await turn(\n lease,\n agent,\n text,\n options,\n resumed,\n markers,\n index + 1,\n { repository: workspace.repository, repair: repair !== undefined },\n );\n return afterTurn ? await afterTurn(finished) : finished;\n },\n );\n turns.push(...steered);\n const current = steered.at(-1)!;\n notify(options.observe, {\n kind: \"summary\",\n durationMs: steered.reduce((sum, item) => sum + item.durationMs, 0),\n status: current.status,\n tokens: steered.reduce((sum, item) => addUsage(sum, item.usage), {\n input: 0,\n cached: 0,\n output: 0,\n } as Usage),\n pass: index + 1,\n at: new Date().toISOString(),\n });\n completed = markers.some((marker) => current.text.includes(marker));\n if (options.response) {\n try {\n value = await options.response.read(current.text);\n completed = true;\n break;\n } catch (error) {\n if (!(error instanceof ResponseError)) throw error;\n error.recovery = {\n conversation: current.conversation,\n branch: workspace.branch,\n directory: workspace.directory,\n turns,\n };\n if (index + 1 >= attempts || !current.conversation) throw error;\n continuation = { id: current.conversation };\n repair = [\n `Correct the response inside <${options.response.tag}> and </${options.response.tag}>.`,\n `Validation failure: ${error.message}`,\n `Previous content: ${error.raw ?? \"No complete tagged response was returned.\"}`,\n `Cause: ${error.cause instanceof Error ? error.cause.message : (JSON.stringify(error.cause) ?? \"unspecified\")}`,\n `Further repair attempts after this one: ${attempts - index - 2}.`,\n \"Do not edit files, run commands or continue implementation. Only return the corrected response.\",\n ].join(\"\\n\");\n }\n }\n if (!options.response && completed) break;\n }\n const conversation = turns.at(-1)?.conversation;\n const completion = markers.find((marker) =>\n turns.at(-1)?.text.includes(marker),\n );\n return {\n text: turns.map((item) => item.text).join(\"\\n\"),\n turns,\n value,\n completed,\n ...(completion ? { completion } : {}),\n ...(conversation ? { conversation } : {}),\n usage: turns.reduce((sum, item) => addUsage(sum, item.usage), {\n input: 0,\n cached: 0,\n output: 0,\n } as Usage),\n };\n}\n"]}
@@ -1,9 +1,11 @@
1
1
  import { invariant } from "../domain/errors.js";
2
2
  import { defineJsonResponse } from "../domain/response.js";
3
+ import { interactiveResponseSchema } from "./interactive-task.constants.js";
3
4
  import { checkpointValue } from "../domain/workflow/checkpoint-value.js";
4
5
  import { inputObject, validateInputQuestion, } from "../domain/workflow/input-validation.js";
5
6
  export const interactiveResponse = defineJsonResponse({
6
7
  tag: "interaction",
8
+ jsonSchema: interactiveResponseSchema,
7
9
  repairs: 1,
8
10
  schema(value) {
9
11
  invariant(inputObject(value), "Interactive response must be an object");
@@ -1 +1 @@
1
- {"version":3,"file":"interactive-task-protocol.js","sourceRoot":"","sources":["../../src/application/interactive-task-protocol.ts"],"names":[],"mappings":"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","sourcesContent":["import { invariant } from \"../domain/errors.ts\";\nimport { defineJsonResponse } from \"../domain/response.ts\";\nimport { checkpointValue } from \"../domain/workflow/checkpoint-value.ts\";\nimport {\n inputObject,\n validateInputQuestion,\n} from \"../domain/workflow/input-validation.ts\";\nimport type { WorkflowJson } from \"../domain/workflow/checkpoint.types.ts\";\nimport type {\n InteractiveAgentState,\n InteractiveAgentTurn,\n} from \"./interactive-task.types.ts\";\n\nexport const interactiveResponse = defineJsonResponse<InteractiveAgentTurn>({\n tag: \"interaction\",\n repairs: 1,\n schema(value) {\n invariant(inputObject(value), \"Interactive response must be an object\");\n if (value.kind === \"question\") {\n validateInputQuestion(value);\n return {\n kind: \"question\",\n question: value.question,\n ...(value.choices ? { choices: value.choices } : {}),\n ...(value.allowFreeText !== undefined\n ? { allowFreeText: value.allowFreeText }\n : {}),\n };\n }\n invariant(\n value.kind === \"completed\" && Object.hasOwn(value, \"output\"),\n \"Expected a question or completed output\",\n );\n const output = checkpointValue(value.output);\n invariant(\n output.kind === \"json\",\n \"Interactive output must be lossless JSON\",\n );\n return { kind: \"completed\", output: output.value };\n },\n});\n\nexport function interactiveState(\n value: WorkflowJson | undefined,\n): InteractiveAgentState | undefined {\n if (value === undefined) return undefined;\n assertState(value);\n return value;\n}\n\nfunction assertState(value: unknown): asserts value is InteractiveAgentState {\n invariant(\n inputObject(value) &&\n typeof value.turns === \"number\" &&\n Number.isSafeInteger(value.turns) &&\n value.turns >= 0 &&\n typeof value.branch === \"string\" &&\n !!value.branch &&\n typeof value.directory === \"string\" &&\n !!value.directory &&\n (value.conversation === undefined ||\n (typeof value.conversation === \"string\" && !!value.conversation)) &&\n (value.turns === 0 || !!value.conversation),\n \"Invalid interactive agent checkpoint state\",\n );\n if (value.completed === undefined) return;\n const completed = value.completed;\n invariant(\n inputObject(completed) &&\n Object.hasOwn(completed, \"output\") &&\n completed.conversation === value.conversation &&\n completed.branch === value.branch &&\n completed.directory === value.directory &&\n completed.turns === value.turns,\n \"Invalid completed interactive agent checkpoint\",\n );\n checkpointValue(completed.output);\n}\n"]}
1
+ {"version":3,"file":"interactive-task-protocol.js","sourceRoot":"","sources":["../../src/application/interactive-task-protocol.ts"],"names":[],"mappings":"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","sourcesContent":["import { invariant } from \"../domain/errors.ts\";\nimport { defineJsonResponse } from \"../domain/response.ts\";\nimport { interactiveResponseSchema } from \"./interactive-task.constants.ts\";\nimport { checkpointValue } from \"../domain/workflow/checkpoint-value.ts\";\nimport {\n inputObject,\n validateInputQuestion,\n} from \"../domain/workflow/input-validation.ts\";\nimport type { WorkflowJson } from \"../domain/workflow/checkpoint.types.ts\";\nimport type {\n InteractiveAgentState,\n InteractiveAgentTurn,\n} from \"./interactive-task.types.ts\";\n\nexport const interactiveResponse = defineJsonResponse<InteractiveAgentTurn>({\n tag: \"interaction\",\n jsonSchema: interactiveResponseSchema,\n repairs: 1,\n schema(value) {\n invariant(inputObject(value), \"Interactive response must be an object\");\n if (value.kind === \"question\") {\n validateInputQuestion(value);\n return {\n kind: \"question\",\n question: value.question,\n ...(value.choices ? { choices: value.choices } : {}),\n ...(value.allowFreeText !== undefined\n ? { allowFreeText: value.allowFreeText }\n : {}),\n };\n }\n invariant(\n value.kind === \"completed\" && Object.hasOwn(value, \"output\"),\n \"Expected a question or completed output\",\n );\n const output = checkpointValue(value.output);\n invariant(\n output.kind === \"json\",\n \"Interactive output must be lossless JSON\",\n );\n return { kind: \"completed\", output: output.value };\n },\n});\n\nexport function interactiveState(\n value: WorkflowJson | undefined,\n): InteractiveAgentState | undefined {\n if (value === undefined) return undefined;\n assertState(value);\n return value;\n}\n\nfunction assertState(value: unknown): asserts value is InteractiveAgentState {\n invariant(\n inputObject(value) &&\n typeof value.turns === \"number\" &&\n Number.isSafeInteger(value.turns) &&\n value.turns >= 0 &&\n typeof value.branch === \"string\" &&\n !!value.branch &&\n typeof value.directory === \"string\" &&\n !!value.directory &&\n (value.conversation === undefined ||\n (typeof value.conversation === \"string\" && !!value.conversation)) &&\n (value.turns === 0 || !!value.conversation),\n \"Invalid interactive agent checkpoint state\",\n );\n if (value.completed === undefined) return;\n const completed = value.completed;\n invariant(\n inputObject(completed) &&\n Object.hasOwn(completed, \"output\") &&\n completed.conversation === value.conversation &&\n completed.branch === value.branch &&\n completed.directory === value.directory &&\n completed.turns === value.turns,\n \"Invalid completed interactive agent checkpoint\",\n );\n checkpointValue(completed.output);\n}\n"]}
@@ -1,4 +1,57 @@
1
1
  export declare const interactiveTaskDefaults: {
2
2
  readonly maxTurns: 12;
3
3
  };
4
+ export declare const interactiveResponseSchema: {
5
+ anyOf: ({
6
+ type: string;
7
+ properties: {
8
+ kind: {
9
+ const: string;
10
+ };
11
+ question: {
12
+ type: string;
13
+ pattern: string;
14
+ };
15
+ choices: {
16
+ type: string;
17
+ items: {
18
+ type: string;
19
+ pattern: string;
20
+ };
21
+ minItems: number;
22
+ uniqueItems: boolean;
23
+ };
24
+ allowFreeText: {
25
+ type: string;
26
+ };
27
+ output?: never;
28
+ };
29
+ required: string[];
30
+ if: {
31
+ properties: {
32
+ allowFreeText: {
33
+ const: boolean;
34
+ };
35
+ };
36
+ required: string[];
37
+ };
38
+ then: {
39
+ required: string[];
40
+ };
41
+ } | {
42
+ type: string;
43
+ properties: {
44
+ kind: {
45
+ const: string;
46
+ };
47
+ output: {};
48
+ question?: never;
49
+ choices?: never;
50
+ allowFreeText?: never;
51
+ };
52
+ required: string[];
53
+ if?: never;
54
+ then?: never;
55
+ })[];
56
+ };
4
57
  export declare const interactiveTurnInstructions = "This is a durable interactive task. End each turn with exactly one JSON response inside <interaction> and </interaction>.\nWhen human input is needed, return {\"kind\":\"question\",\"question\":\"Your question\",\"choices\":[\"Optional choice\"],\"allowFreeText\":true}. Omit choices for free text. Set allowFreeText to false only when choices are supplied and the user must choose one.\nWhen the entire task is complete, return {\"kind\":\"completed\",\"output\":<your JSON result>}.\nAsk one focused question at a time and adapt subsequent questions to the answers in this conversation. Do not invent a human answer. Do not wait for terminal input.\nThe sandbox is recreated between turns. Keep required project files in the repository. Do not switch branches, integrate or push changes. The workflow will retain the workspace.";
@@ -1,4 +1,33 @@
1
1
  export const interactiveTaskDefaults = { maxTurns: 12 };
2
+ export const interactiveResponseSchema = {
3
+ anyOf: [
4
+ {
5
+ type: "object",
6
+ properties: {
7
+ kind: { const: "question" },
8
+ question: { type: "string", pattern: "\\S" },
9
+ choices: {
10
+ type: "array",
11
+ items: { type: "string", pattern: "\\S" },
12
+ minItems: 1,
13
+ uniqueItems: true,
14
+ },
15
+ allowFreeText: { type: "boolean" },
16
+ },
17
+ required: ["kind", "question"],
18
+ if: {
19
+ properties: { allowFreeText: { const: false } },
20
+ required: ["allowFreeText"],
21
+ },
22
+ then: { required: ["choices"] },
23
+ },
24
+ {
25
+ type: "object",
26
+ properties: { kind: { const: "completed" }, output: {} },
27
+ required: ["kind", "output"],
28
+ },
29
+ ],
30
+ };
2
31
  export const interactiveTurnInstructions = `This is a durable interactive task. End each turn with exactly one JSON response inside <interaction> and </interaction>.
3
32
  When human input is needed, return {"kind":"question","question":"Your question","choices":["Optional choice"],"allowFreeText":true}. Omit choices for free text. Set allowFreeText to false only when choices are supplied and the user must choose one.
4
33
  When the entire task is complete, return {"kind":"completed","output":<your JSON result>}.
@@ -1 +1 @@
1
- {"version":3,"file":"interactive-task.constants.js","sourceRoot":"","sources":["../../src/application/interactive-task.constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,uBAAuB,GAAG,EAAE,QAAQ,EAAE,EAAE,EAAW,CAAC;AAEjE,MAAM,CAAC,MAAM,2BAA2B,GAAG;;;;kLAIuI,CAAC","sourcesContent":["export const interactiveTaskDefaults = { maxTurns: 12 } as const;\n\nexport const interactiveTurnInstructions = `This is a durable interactive task. End each turn with exactly one JSON response inside <interaction> and </interaction>.\nWhen human input is needed, return {\"kind\":\"question\",\"question\":\"Your question\",\"choices\":[\"Optional choice\"],\"allowFreeText\":true}. Omit choices for free text. Set allowFreeText to false only when choices are supplied and the user must choose one.\nWhen the entire task is complete, return {\"kind\":\"completed\",\"output\":<your JSON result>}.\nAsk one focused question at a time and adapt subsequent questions to the answers in this conversation. Do not invent a human answer. Do not wait for terminal input.\nThe sandbox is recreated between turns. Keep required project files in the repository. Do not switch branches, integrate or push changes. The workflow will retain the workspace.`;\n"]}
1
+ {"version":3,"file":"interactive-task.constants.js","sourceRoot":"","sources":["../../src/application/interactive-task.constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,uBAAuB,GAAG,EAAE,QAAQ,EAAE,EAAE,EAAW,CAAC;AAEjE,MAAM,CAAC,MAAM,yBAAyB,GAAG;IACvC,KAAK,EAAE;QACL;YACE,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE;gBACV,IAAI,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE;gBAC3B,QAAQ,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE;gBAC5C,OAAO,EAAE;oBACP,IAAI,EAAE,OAAO;oBACb,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE;oBACzC,QAAQ,EAAE,CAAC;oBACX,WAAW,EAAE,IAAI;iBAClB;gBACD,aAAa,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE;aACnC;YACD,QAAQ,EAAE,CAAC,MAAM,EAAE,UAAU,CAAC;YAC9B,EAAE,EAAE;gBACF,UAAU,EAAE,EAAE,aAAa,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;gBAC/C,QAAQ,EAAE,CAAC,eAAe,CAAC;aAC5B;YACD,IAAI,EAAE,EAAE,QAAQ,EAAE,CAAC,SAAS,CAAC,EAAE;SAChC;QACD;YACE,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE;YACxD,QAAQ,EAAE,CAAC,MAAM,EAAE,QAAQ,CAAC;SAC7B;KACF;CACF,CAAC;AAEF,MAAM,CAAC,MAAM,2BAA2B,GAAG;;;;kLAIuI,CAAC","sourcesContent":["export const interactiveTaskDefaults = { maxTurns: 12 } as const;\n\nexport const interactiveResponseSchema = {\n anyOf: [\n {\n type: \"object\",\n properties: {\n kind: { const: \"question\" },\n question: { type: \"string\", pattern: \"\\\\S\" },\n choices: {\n type: \"array\",\n items: { type: \"string\", pattern: \"\\\\S\" },\n minItems: 1,\n uniqueItems: true,\n },\n allowFreeText: { type: \"boolean\" },\n },\n required: [\"kind\", \"question\"],\n if: {\n properties: { allowFreeText: { const: false } },\n required: [\"allowFreeText\"],\n },\n then: { required: [\"choices\"] },\n },\n {\n type: \"object\",\n properties: { kind: { const: \"completed\" }, output: {} },\n required: [\"kind\", \"output\"],\n },\n ],\n};\n\nexport const interactiveTurnInstructions = `This is a durable interactive task. End each turn with exactly one JSON response inside <interaction> and </interaction>.\nWhen human input is needed, return {\"kind\":\"question\",\"question\":\"Your question\",\"choices\":[\"Optional choice\"],\"allowFreeText\":true}. Omit choices for free text. Set allowFreeText to false only when choices are supplied and the user must choose one.\nWhen the entire task is complete, return {\"kind\":\"completed\",\"output\":<your JSON result>}.\nAsk one focused question at a time and adapt subsequent questions to the answers in this conversation. Do not invent a human answer. Do not wait for terminal input.\nThe sandbox is recreated between turns. Keep required project files in the repository. Do not switch branches, integrate or push changes. The workflow will retain the workspace.`;\n"]}
@@ -1,4 +1,5 @@
1
1
  import { mainLoopSteering, steeringInbox } from "../domain/steering.js";
2
+ import { responseInstructions } from "../domain/response-instructions.js";
2
3
  import { notify } from "./observation.js";
3
4
  import { deliverSteering, rejectSubagentSteering } from "./steering-scope.js";
4
5
  /** Runs one pass, resuming the conversation while steering messages remain. */
@@ -11,9 +12,19 @@ export async function steeringTurns(agent, options, prompt, continuation, pass,
11
12
  rejectSubagentSteering(inbox);
12
13
  const messages = inbox?.take(mainLoopSteering) ?? [];
13
14
  deliverSteering(messages, next.mode, pass, options.observe);
14
- const text = [next.prompt, ...messages.map((message) => message.text)]
15
+ const text = [
16
+ next.prompt,
17
+ ...messages.map((message) => message.text),
18
+ ...(options.response ? [responseInstructions(options.response)] : []),
19
+ ]
15
20
  .filter(Boolean)
16
21
  .join("\n\n");
22
+ notify(options.observe, {
23
+ kind: "prompt",
24
+ text,
25
+ pass,
26
+ at: new Date().toISOString(),
27
+ });
17
28
  const turn = await run(text, next.continuation);
18
29
  turns.push(turn);
19
30
  const recorded = agent.kind === "replay" ? agent.pendingSteering() : [];
@@ -1 +1 @@
1
- {"version":3,"file":"steering-turns.js","sourceRoot":"","sources":["../../src/application/steering-turns.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAExE,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,eAAe,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAG9E,+EAA+E;AAC/E,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,KAAY,EACZ,OAAiC,EACjC,MAAc,EACd,YAA6C,EAC7C,IAAY,EACZ,GAGkB;IAElB,MAAM,KAAK,GAAG,aAAa,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC9C,MAAM,KAAK,GAAW,EAAE,CAAC;IACzB,IAAI,IAAI,GAAsB,EAAE,MAAM,EAAE,YAAY,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC;IACzE,SAAS,CAAC;QACR,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ;YAAE,sBAAsB,CAAC,KAAK,CAAC,CAAC;QAC3D,MAAM,QAAQ,GAAG,KAAK,EAAE,IAAI,CAAC,gBAAgB,CAAC,IAAI,EAAE,CAAC;QACrD,eAAe,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;QAC5D,MAAM,IAAI,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;aACnE,MAAM,CAAC,OAAO,CAAC;aACf,IAAI,CAAC,MAAM,CAAC,CAAC;QAChB,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;QAChD,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjB,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACxE,IAAI,QAAQ,EAAE,MAAM,EAAE,CAAC;YACrB,KAAK,MAAM,WAAW,IAAI,QAAQ;gBAChC,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE;oBACtB,IAAI,EAAE,OAAO;oBACb,IAAI,EAAE,WAAW;oBACjB,IAAI,EAAE,SAAS;oBACf,IAAI;oBACJ,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;iBAC7B,CAAC,CAAC;YACL,IAAI,GAAG;gBACL,MAAM,EAAE,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC;gBAC7B,YAAY,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,SAAS;gBACvE,IAAI,EAAE,SAAS;aAChB,CAAC;YACF,SAAS;QACX,CAAC;QACD,IACE,CAAC,KAAK,EAAE,KAAK,CAAC,gBAAgB,CAAC;YAC/B,CAAC,IAAI,CAAC,YAAY;YAClB,KAAK,CAAC,SAAS,KAAK,KAAK;YAEzB,OAAO,KAAK,CAAC;QACf,IAAI,GAAG;YACL,MAAM,EAAE,EAAE;YACV,YAAY,EAAE,EAAE,EAAE,EAAE,IAAI,CAAC,YAAY,EAAE;YACvC,IAAI,EAAE,SAAS;SAChB,CAAC;IACJ,CAAC;AACH,CAAC","sourcesContent":["import type { Agent } from \"../domain/agent.types.ts\";\nimport { mainLoopSteering, steeringInbox } from \"../domain/steering.ts\";\nimport type { DispatchOptions, Turn } from \"./execution.types.ts\";\nimport { notify } from \"./observation.ts\";\nimport { deliverSteering, rejectSubagentSteering } from \"./steering-scope.ts\";\nimport type { SteeringTurnInput } from \"./steering-turns.types.ts\";\n\n/** Runs one pass, resuming the conversation while steering messages remain. */\nexport async function steeringTurns(\n agent: Agent,\n options: DispatchOptions<unknown>,\n prompt: string,\n continuation: DispatchOptions[\"continuation\"],\n pass: number,\n run: (\n prompt: string,\n continuation: DispatchOptions[\"continuation\"],\n ) => Promise<Turn>,\n): Promise<Turn[]> {\n const inbox = steeringInbox(options.steering);\n const turns: Turn[] = [];\n let next: SteeringTurnInput = { prompt, continuation, mode: \"injected\" };\n for (;;) {\n if (agent.kind !== \"custom\") rejectSubagentSteering(inbox);\n const messages = inbox?.take(mainLoopSteering) ?? [];\n deliverSteering(messages, next.mode, pass, options.observe);\n const text = [next.prompt, ...messages.map((message) => message.text)]\n .filter(Boolean)\n .join(\"\\n\\n\");\n const turn = await run(text, next.continuation);\n turns.push(turn);\n const recorded = agent.kind === \"replay\" ? agent.pendingSteering() : [];\n if (recorded?.length) {\n for (const instruction of recorded)\n notify(options.observe, {\n kind: \"steer\",\n text: instruction,\n mode: \"resumed\",\n pass,\n at: new Date().toISOString(),\n });\n next = {\n prompt: recorded.join(\"\\n\\n\"),\n continuation: turn.conversation ? { id: turn.conversation } : undefined,\n mode: \"resumed\",\n };\n continue;\n }\n if (\n !inbox?.count(mainLoopSteering) ||\n !turn.conversation ||\n agent.resumable === false\n )\n return turns;\n next = {\n prompt: \"\",\n continuation: { id: turn.conversation },\n mode: \"resumed\",\n };\n }\n}\n"]}
1
+ {"version":3,"file":"steering-turns.js","sourceRoot":"","sources":["../../src/application/steering-turns.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACxE,OAAO,EAAE,oBAAoB,EAAE,MAAM,oCAAoC,CAAC;AAE1E,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,eAAe,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAG9E,+EAA+E;AAC/E,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,KAAY,EACZ,OAAiC,EACjC,MAAc,EACd,YAA6C,EAC7C,IAAY,EACZ,GAGkB;IAElB,MAAM,KAAK,GAAG,aAAa,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC9C,MAAM,KAAK,GAAW,EAAE,CAAC;IACzB,IAAI,IAAI,GAAsB,EAAE,MAAM,EAAE,YAAY,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC;IACzE,SAAS,CAAC;QACR,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ;YAAE,sBAAsB,CAAC,KAAK,CAAC,CAAC;QAC3D,MAAM,QAAQ,GAAG,KAAK,EAAE,IAAI,CAAC,gBAAgB,CAAC,IAAI,EAAE,CAAC;QACrD,eAAe,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;QAC5D,MAAM,IAAI,GAAG;YACX,IAAI,CAAC,MAAM;YACX,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;YAC1C,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,oBAAoB,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;SACtE;aACE,MAAM,CAAC,OAAO,CAAC;aACf,IAAI,CAAC,MAAM,CAAC,CAAC;QAChB,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE;YACtB,IAAI,EAAE,QAAQ;YACd,IAAI;YACJ,IAAI;YACJ,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SAC7B,CAAC,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;QAChD,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjB,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACxE,IAAI,QAAQ,EAAE,MAAM,EAAE,CAAC;YACrB,KAAK,MAAM,WAAW,IAAI,QAAQ;gBAChC,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE;oBACtB,IAAI,EAAE,OAAO;oBACb,IAAI,EAAE,WAAW;oBACjB,IAAI,EAAE,SAAS;oBACf,IAAI;oBACJ,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;iBAC7B,CAAC,CAAC;YACL,IAAI,GAAG;gBACL,MAAM,EAAE,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC;gBAC7B,YAAY,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,SAAS;gBACvE,IAAI,EAAE,SAAS;aAChB,CAAC;YACF,SAAS;QACX,CAAC;QACD,IACE,CAAC,KAAK,EAAE,KAAK,CAAC,gBAAgB,CAAC;YAC/B,CAAC,IAAI,CAAC,YAAY;YAClB,KAAK,CAAC,SAAS,KAAK,KAAK;YAEzB,OAAO,KAAK,CAAC;QACf,IAAI,GAAG;YACL,MAAM,EAAE,EAAE;YACV,YAAY,EAAE,EAAE,EAAE,EAAE,IAAI,CAAC,YAAY,EAAE;YACvC,IAAI,EAAE,SAAS;SAChB,CAAC;IACJ,CAAC;AACH,CAAC","sourcesContent":["import type { Agent } from \"../domain/agent.types.ts\";\nimport { mainLoopSteering, steeringInbox } from \"../domain/steering.ts\";\nimport { responseInstructions } from \"../domain/response-instructions.ts\";\nimport type { DispatchOptions, Turn } from \"./execution.types.ts\";\nimport { notify } from \"./observation.ts\";\nimport { deliverSteering, rejectSubagentSteering } from \"./steering-scope.ts\";\nimport type { SteeringTurnInput } from \"./steering-turns.types.ts\";\n\n/** Runs one pass, resuming the conversation while steering messages remain. */\nexport async function steeringTurns(\n agent: Agent,\n options: DispatchOptions<unknown>,\n prompt: string,\n continuation: DispatchOptions[\"continuation\"],\n pass: number,\n run: (\n prompt: string,\n continuation: DispatchOptions[\"continuation\"],\n ) => Promise<Turn>,\n): Promise<Turn[]> {\n const inbox = steeringInbox(options.steering);\n const turns: Turn[] = [];\n let next: SteeringTurnInput = { prompt, continuation, mode: \"injected\" };\n for (;;) {\n if (agent.kind !== \"custom\") rejectSubagentSteering(inbox);\n const messages = inbox?.take(mainLoopSteering) ?? [];\n deliverSteering(messages, next.mode, pass, options.observe);\n const text = [\n next.prompt,\n ...messages.map((message) => message.text),\n ...(options.response ? [responseInstructions(options.response)] : []),\n ]\n .filter(Boolean)\n .join(\"\\n\\n\");\n notify(options.observe, {\n kind: \"prompt\",\n text,\n pass,\n at: new Date().toISOString(),\n });\n const turn = await run(text, next.continuation);\n turns.push(turn);\n const recorded = agent.kind === \"replay\" ? agent.pendingSteering() : [];\n if (recorded?.length) {\n for (const instruction of recorded)\n notify(options.observe, {\n kind: \"steer\",\n text: instruction,\n mode: \"resumed\",\n pass,\n at: new Date().toISOString(),\n });\n next = {\n prompt: recorded.join(\"\\n\\n\"),\n continuation: turn.conversation ? { id: turn.conversation } : undefined,\n mode: \"resumed\",\n };\n continue;\n }\n if (\n !inbox?.count(mainLoopSteering) ||\n !turn.conversation ||\n agent.resumable === false\n )\n return turns;\n next = {\n prompt: \"\",\n continuation: { id: turn.conversation },\n mode: \"resumed\",\n };\n }\n}\n"]}
@@ -15,6 +15,9 @@ function summary(runId, version, result) {
15
15
  version,
16
16
  executionId: result.executionId,
17
17
  status: result.status,
18
+ ...(result.terminationCode
19
+ ? { terminationCode: result.terminationCode }
20
+ : {}),
18
21
  tasks: result.tasks.map((record) => ({
19
22
  key: record.key,
20
23
  status: record.status,
@@ -65,7 +68,7 @@ export function defineWorkflowJob(options) {
65
68
  },
66
69
  });
67
70
  const tokens = result.usage.tokens;
68
- const failed = result.status === "failed" || result.status === "cancelled";
71
+ const failed = ["failed", "cancelled", "rejected"].includes(result.status);
69
72
  return {
70
73
  value: summary(runId, version, result),
71
74
  usage: {
@@ -1 +1 @@
1
- {"version":3,"file":"workflow-job.js","sourceRoot":"","sources":["../../src/application/workflow-job.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash } from \"node:crypto\";\nimport { queueMaxStringLength } from \"../domain/task-queue.constants.ts\";\nimport { triggerJobInput } from \"../domain/trigger-job.ts\";\nimport { canonicalJson } from \"../domain/workflow/canonical-json.ts\";\nimport type { QueueResult } from \"../domain/task-queue.types.ts\";\nimport type { WorkflowResult } from \"../domain/workflow.types.ts\";\nimport type { WorkflowJson } from \"../domain/workflow/checkpoint.types.ts\";\nimport type { QueueHandler } from \"./queue-worker.types.ts\";\nimport type { WorkflowJobOptions } from \"./workflow-job.types.ts\";\n\nfunction inputVersion(version: string, input: WorkflowJson): string {\n const digest = createHash(\"sha256\")\n .update(canonicalJson(input))\n .digest(\"hex\")\n .slice(0, 32);\n return `${version}#input:${digest}`;\n}\n\nfunction summary(\n runId: string,\n version: string,\n result: WorkflowResult,\n): WorkflowJson {\n return {\n runId,\n version,\n executionId: result.executionId,\n status: result.status,\n tasks: result.tasks.map((record) => ({\n key: record.key,\n status: record.status,\n })),\n pauses: result.tasks.flatMap((record) =>\n record.pause && record.status === \"paused\"\n ? [\n {\n key: record.key,\n id: record.pause.id,\n kind: record.pause.kind,\n prompt: record.pause.prompt,\n actors: [...record.pause.actors],\n },\n ]\n : [],\n ),\n inputRequests: result.inputRequests.map((request) => ({\n key: request.key,\n id: request.id,\n question: request.question,\n })),\n };\n}\n\nfunction failure(result: WorkflowResult): string {\n const [first] = result.errors;\n const detail = first instanceof Error ? `: ${first.message}` : \"\";\n return `Workflow ${result.status}${detail}`.slice(0, queueMaxStringLength);\n}\n\n/** Queue handler running one checkpointed workflow per trigger job. */\nexport function defineWorkflowJob(options: WorkflowJobOptions): QueueHandler {\n if (typeof options.workflow !== \"function\")\n throw new Error(\"defineWorkflowJob() requires a workflow factory\");\n if (!options.checkpoint?.store || !options.checkpoint.version)\n throw new Error(\n \"defineWorkflowJob() requires a checkpoint store and version\",\n );\n return async (value, context): Promise<QueueResult> => {\n const { runId, input } = triggerJobInput(value);\n const workflow = await options.workflow(input, { ...context, runId });\n const version = inputVersion(options.checkpoint.version, input);\n const result = await workflow.start({\n ...options.start,\n signal: context.signal,\n checkpoint: {\n store: options.checkpoint.store,\n runId,\n version,\n ...(options.checkpoint.resume\n ? { resume: options.checkpoint.resume }\n : {}),\n },\n });\n const tokens = result.usage.tokens;\n const failed = result.status === \"failed\" || result.status === \"cancelled\";\n return {\n value: summary(runId, version, result),\n usage: {\n input: tokens.input,\n output: tokens.output,\n cached: tokens.cached,\n ...(tokens.cacheCreated === undefined\n ? {}\n : { cacheCreated: tokens.cacheCreated }),\n },\n ...(failed ? { error: failure(result) } : {}),\n };\n };\n}\n"]}
1
+ {"version":3,"file":"workflow-job.js","sourceRoot":"","sources":["../../src/application/workflow-job.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash } from \"node:crypto\";\nimport { queueMaxStringLength } from \"../domain/task-queue.constants.ts\";\nimport { triggerJobInput } from \"../domain/trigger-job.ts\";\nimport { canonicalJson } from \"../domain/workflow/canonical-json.ts\";\nimport type { QueueResult } from \"../domain/task-queue.types.ts\";\nimport type { WorkflowResult } from \"../domain/workflow.types.ts\";\nimport type { WorkflowJson } from \"../domain/workflow/checkpoint.types.ts\";\nimport type { QueueHandler } from \"./queue-worker.types.ts\";\nimport type { WorkflowJobOptions } from \"./workflow-job.types.ts\";\n\nfunction inputVersion(version: string, input: WorkflowJson): string {\n const digest = createHash(\"sha256\")\n .update(canonicalJson(input))\n .digest(\"hex\")\n .slice(0, 32);\n return `${version}#input:${digest}`;\n}\n\nfunction summary(\n runId: string,\n version: string,\n result: WorkflowResult,\n): WorkflowJson {\n return {\n runId,\n version,\n executionId: result.executionId,\n status: result.status,\n ...(result.terminationCode\n ? { terminationCode: result.terminationCode }\n : {}),\n tasks: result.tasks.map((record) => ({\n key: record.key,\n status: record.status,\n })),\n pauses: result.tasks.flatMap((record) =>\n record.pause && record.status === \"paused\"\n ? [\n {\n key: record.key,\n id: record.pause.id,\n kind: record.pause.kind,\n prompt: record.pause.prompt,\n actors: [...record.pause.actors],\n },\n ]\n : [],\n ),\n inputRequests: result.inputRequests.map((request) => ({\n key: request.key,\n id: request.id,\n question: request.question,\n })),\n };\n}\n\nfunction failure(result: WorkflowResult): string {\n const [first] = result.errors;\n const detail = first instanceof Error ? `: ${first.message}` : \"\";\n return `Workflow ${result.status}${detail}`.slice(0, queueMaxStringLength);\n}\n\n/** Queue handler running one checkpointed workflow per trigger job. */\nexport function defineWorkflowJob(options: WorkflowJobOptions): QueueHandler {\n if (typeof options.workflow !== \"function\")\n throw new Error(\"defineWorkflowJob() requires a workflow factory\");\n if (!options.checkpoint?.store || !options.checkpoint.version)\n throw new Error(\n \"defineWorkflowJob() requires a checkpoint store and version\",\n );\n return async (value, context): Promise<QueueResult> => {\n const { runId, input } = triggerJobInput(value);\n const workflow = await options.workflow(input, { ...context, runId });\n const version = inputVersion(options.checkpoint.version, input);\n const result = await workflow.start({\n ...options.start,\n signal: context.signal,\n checkpoint: {\n store: options.checkpoint.store,\n runId,\n version,\n ...(options.checkpoint.resume\n ? { resume: options.checkpoint.resume }\n : {}),\n },\n });\n const tokens = result.usage.tokens;\n const failed = [\"failed\", \"cancelled\", \"rejected\"].includes(result.status);\n return {\n value: summary(runId, version, result),\n usage: {\n input: tokens.input,\n output: tokens.output,\n cached: tokens.cached,\n ...(tokens.cacheCreated === undefined\n ? {}\n : { cacheCreated: tokens.cacheCreated }),\n },\n ...(failed ? { error: failure(result) } : {}),\n };\n };\n}\n"]}
@@ -1 +1 @@
1
- export type FaultCode = "configuration" | "process" | "timeout" | "aborted" | "workspace" | "conflict" | "prompt" | "response" | "session" | "provider" | "limit" | "quota" | "replay" | "steering";
1
+ export type FaultCode = "rejected" | "configuration" | "process" | "timeout" | "aborted" | "workspace" | "conflict" | "prompt" | "response" | "session" | "provider" | "limit" | "quota" | "replay" | "steering";
@@ -1 +1 @@
1
- {"version":3,"file":"errors.types.js","sourceRoot":"","sources":["../../src/domain/errors.types.ts"],"names":[],"mappings":"","sourcesContent":["export type FaultCode =\n | \"configuration\"\n | \"process\"\n | \"timeout\"\n | \"aborted\"\n | \"workspace\"\n | \"conflict\"\n | \"prompt\"\n | \"response\"\n | \"session\"\n | \"provider\"\n | \"limit\"\n | \"quota\"\n | \"replay\"\n | \"steering\";\n"]}
1
+ {"version":3,"file":"errors.types.js","sourceRoot":"","sources":["../../src/domain/errors.types.ts"],"names":[],"mappings":"","sourcesContent":["export type FaultCode =\n | \"rejected\"\n | \"configuration\"\n | \"process\"\n | \"timeout\"\n | \"aborted\"\n | \"workspace\"\n | \"conflict\"\n | \"prompt\"\n | \"response\"\n | \"session\"\n | \"provider\"\n | \"limit\"\n | \"quota\"\n | \"replay\"\n | \"steering\";\n"]}
@@ -24,6 +24,7 @@ export const replayExecutionEvents = new Set([
24
24
  "fallback",
25
25
  ]);
26
26
  export const replayFaultCodes = new Set([
27
+ "rejected",
27
28
  "configuration",
28
29
  "process",
29
30
  "timeout",
@@ -1 +1 @@
1
- {"version":3,"file":"replay.constants.js","sourceRoot":"","sources":["../../src/domain/replay.constants.ts"],"names":[],"mappings":"AAKA,MAAM,CAAC,MAAM,mBAAmB,GAAG,IAAI,GAAG,CAAC;IACzC,UAAU;IACV,kBAAkB;IAClB,mBAAmB;CACpB,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,cAAc,GAAG,MAAM,CAAC,MAAM,CAAC;IAC1C,IAAI,EAAE,QAAQ;IACd,UAAU,EAAE,MAAM;IAClB,UAAU,EAAE,qDAAqD;IACjE,UAAU,EAAE,wCAAwC;CACrD,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,mBAAmB,GAAwB,IAAI,GAAG,CAAC;IAC9D,KAAK;IACL,IAAI;IACJ,QAAQ;IACR,OAAO;IACP,OAAO;IACP,MAAM;CACP,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,qBAAqB,GAAwB,IAAI,GAAG,CAAC;IAChE,OAAO;IACP,QAAQ;IACR,SAAS;IACT,UAAU;CACX,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,gBAAgB,GAAwB,IAAI,GAAG,CAAC;IAC3D,eAAe;IACf,SAAS;IACT,SAAS;IACT,SAAS;IACT,WAAW;IACX,UAAU;IACV,QAAQ;IACR,UAAU;IACV,SAAS;IACT,UAAU;IACV,OAAO;IACP,OAAO;IACP,QAAQ;IACR,UAAU;CACX,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,wBAAwB,GAEjC,MAAM,CAAC,MAAM,CAAC;IAChB,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CACnB,eAAe,IAAI,oDAAoD;IACzE,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CACrB,eAAe,IAAI,gEAAgE;IACrF,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,CACzB,eAAe,IAAI,oDAAoD,MAAM,EAAE;IACjF,SAAS,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,kCAAkC,IAAI,EAAE;IACjE,UAAU,EAAE,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,CACjC,eAAe,IAAI,uCAAuC,QAAQ,EAAE;CACvE,CAAC,CAAC","sourcesContent":["import type {\n ReplayDivergenceDetails,\n ReplayDivergenceKind,\n} from \"./replay.types.ts\";\n\nexport const replayDecisionKinds = new Set([\n \"decision\",\n \"decision-request\",\n \"decision-response\",\n]);\n\nexport const replayDefaults = Object.freeze({\n name: \"replay\",\n divergence: \"fail\",\n unrecorded: \"The journal was recorded without logging.replayable\",\n unfinished: \"The recorded agent turn did not finish\",\n});\n\nexport const replayJournalFields: ReadonlySet<string> = new Set([\n \"seq\",\n \"at\",\n \"source\",\n \"scope\",\n \"label\",\n \"pass\",\n]);\n\nexport const replayExecutionEvents: ReadonlySet<string> = new Set([\n \"phase\",\n \"prompt\",\n \"summary\",\n \"fallback\",\n]);\n\nexport const replayFaultCodes: ReadonlySet<string> = new Set([\n \"configuration\",\n \"process\",\n \"timeout\",\n \"aborted\",\n \"workspace\",\n \"conflict\",\n \"prompt\",\n \"response\",\n \"session\",\n \"provider\",\n \"limit\",\n \"quota\",\n \"replay\",\n \"steering\",\n]);\n\nexport const replayDivergenceMessages: Readonly<\n Record<ReplayDivergenceKind, (details: ReplayDivergenceDetails) => string>\n> = Object.freeze({\n prompt: ({ turn }) =>\n `Replay turn ${turn} received a prompt that differs from the recording`,\n baseline: ({ turn }) =>\n `Replay turn ${turn} started from a workspace tree that differs from the recording`,\n tree: ({ turn, commit }) =>\n `Replay turn ${turn} could not reproduce the tree of recorded commit ${commit}`,\n exhausted: ({ turn }) => `The replay journal has no turn ${turn}`,\n unrecorded: ({ turn, expected }) =>\n `Replay turn ${turn} has no recorded workspace commits: ${expected}`,\n});\n"]}
1
+ {"version":3,"file":"replay.constants.js","sourceRoot":"","sources":["../../src/domain/replay.constants.ts"],"names":[],"mappings":"AAKA,MAAM,CAAC,MAAM,mBAAmB,GAAG,IAAI,GAAG,CAAC;IACzC,UAAU;IACV,kBAAkB;IAClB,mBAAmB;CACpB,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,cAAc,GAAG,MAAM,CAAC,MAAM,CAAC;IAC1C,IAAI,EAAE,QAAQ;IACd,UAAU,EAAE,MAAM;IAClB,UAAU,EAAE,qDAAqD;IACjE,UAAU,EAAE,wCAAwC;CACrD,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,mBAAmB,GAAwB,IAAI,GAAG,CAAC;IAC9D,KAAK;IACL,IAAI;IACJ,QAAQ;IACR,OAAO;IACP,OAAO;IACP,MAAM;CACP,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,qBAAqB,GAAwB,IAAI,GAAG,CAAC;IAChE,OAAO;IACP,QAAQ;IACR,SAAS;IACT,UAAU;CACX,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,gBAAgB,GAAwB,IAAI,GAAG,CAAC;IAC3D,UAAU;IACV,eAAe;IACf,SAAS;IACT,SAAS;IACT,SAAS;IACT,WAAW;IACX,UAAU;IACV,QAAQ;IACR,UAAU;IACV,SAAS;IACT,UAAU;IACV,OAAO;IACP,OAAO;IACP,QAAQ;IACR,UAAU;CACX,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,wBAAwB,GAEjC,MAAM,CAAC,MAAM,CAAC;IAChB,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CACnB,eAAe,IAAI,oDAAoD;IACzE,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CACrB,eAAe,IAAI,gEAAgE;IACrF,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,CACzB,eAAe,IAAI,oDAAoD,MAAM,EAAE;IACjF,SAAS,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,kCAAkC,IAAI,EAAE;IACjE,UAAU,EAAE,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,CACjC,eAAe,IAAI,uCAAuC,QAAQ,EAAE;CACvE,CAAC,CAAC","sourcesContent":["import type {\n ReplayDivergenceDetails,\n ReplayDivergenceKind,\n} from \"./replay.types.ts\";\n\nexport const replayDecisionKinds = new Set([\n \"decision\",\n \"decision-request\",\n \"decision-response\",\n]);\n\nexport const replayDefaults = Object.freeze({\n name: \"replay\",\n divergence: \"fail\",\n unrecorded: \"The journal was recorded without logging.replayable\",\n unfinished: \"The recorded agent turn did not finish\",\n});\n\nexport const replayJournalFields: ReadonlySet<string> = new Set([\n \"seq\",\n \"at\",\n \"source\",\n \"scope\",\n \"label\",\n \"pass\",\n]);\n\nexport const replayExecutionEvents: ReadonlySet<string> = new Set([\n \"phase\",\n \"prompt\",\n \"summary\",\n \"fallback\",\n]);\n\nexport const replayFaultCodes: ReadonlySet<string> = new Set([\n \"rejected\",\n \"configuration\",\n \"process\",\n \"timeout\",\n \"aborted\",\n \"workspace\",\n \"conflict\",\n \"prompt\",\n \"response\",\n \"session\",\n \"provider\",\n \"limit\",\n \"quota\",\n \"replay\",\n \"steering\",\n]);\n\nexport const replayDivergenceMessages: Readonly<\n Record<ReplayDivergenceKind, (details: ReplayDivergenceDetails) => string>\n> = Object.freeze({\n prompt: ({ turn }) =>\n `Replay turn ${turn} received a prompt that differs from the recording`,\n baseline: ({ turn }) =>\n `Replay turn ${turn} started from a workspace tree that differs from the recording`,\n tree: ({ turn, commit }) =>\n `Replay turn ${turn} could not reproduce the tree of recorded commit ${commit}`,\n exhausted: ({ turn }) => `The replay journal has no turn ${turn}`,\n unrecorded: ({ turn, expected }) =>\n `Replay turn ${turn} has no recorded workspace commits: ${expected}`,\n});\n"]}
@@ -95,6 +95,10 @@ function replayRecording(journal) {
95
95
  if (origin === "harness")
96
96
  source = "harness";
97
97
  if (event.kind === "prompt") {
98
+ if (current?.resumedBy && current.events.length === 0) {
99
+ current.prompt = text(event, "text", index);
100
+ continue;
101
+ }
98
102
  current = {
99
103
  prompt: text(event, "text", index),
100
104
  events: [],