zidane 5.14.4 → 6.0.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.
Files changed (202) hide show
  1. package/dist/{acp-24uU2WDs.js → acp-Irby04Us.js} +7 -8
  2. package/dist/{acp-24uU2WDs.js.map → acp-Irby04Us.js.map} +1 -1
  3. package/dist/acp-cli.js +7 -7
  4. package/dist/acp.d.ts +2 -3
  5. package/dist/acp.d.ts.map +1 -1
  6. package/dist/acp.js +1 -1
  7. package/dist/{agent-Cch2ayTt.js → agent-DkSmGkDM.js} +10871 -5411
  8. package/dist/agent-DkSmGkDM.js.map +1 -0
  9. package/dist/agent.d.ts +1 -2
  10. package/dist/agent.js +2 -2
  11. package/dist/{anthropic-RGqsJlC8.js → anthropic-CTHsdFG9.js} +46 -6
  12. package/dist/anthropic-CTHsdFG9.js.map +1 -0
  13. package/dist/{auth-C-ms5N2x.js → auth-BDSu_0t3.js} +13 -86
  14. package/dist/auth-BDSu_0t3.js.map +1 -0
  15. package/dist/chat/pure.d.ts +4 -4
  16. package/dist/chat/pure.js +4 -3
  17. package/dist/chat.d.ts +45 -8
  18. package/dist/chat.d.ts.map +1 -1
  19. package/dist/chat.js +9 -6
  20. package/dist/chat.js.map +1 -1
  21. package/dist/completion-core-CXYSVhZo.js +147 -0
  22. package/dist/completion-core-CXYSVhZo.js.map +1 -0
  23. package/dist/{context-breakdown-kO-pDsay.js → context-breakdown-Dzo25N45.js} +2 -23
  24. package/dist/context-breakdown-Dzo25N45.js.map +1 -0
  25. package/dist/contexts/daytona.d.ts +3 -3
  26. package/dist/contexts/daytona.js +1 -1
  27. package/dist/contexts/docker.d.ts +10 -2
  28. package/dist/contexts/docker.d.ts.map +1 -1
  29. package/dist/contexts/docker.js +142 -103
  30. package/dist/contexts/docker.js.map +1 -1
  31. package/dist/contexts/e2b.d.ts +2 -2
  32. package/dist/contexts/e2b.js +1 -1
  33. package/dist/contexts/sandbox.d.ts +1 -1
  34. package/dist/contexts/sandbox.js +4 -1
  35. package/dist/contexts/sandbox.js.map +1 -1
  36. package/dist/{contexts-Lzf5huID.js → contexts-Vone3qQQ.js} +26 -37
  37. package/dist/contexts-Vone3qQQ.js.map +1 -0
  38. package/dist/contexts.d.ts +3 -3
  39. package/dist/contexts.js +1 -1
  40. package/dist/errors.d.ts +1 -2
  41. package/dist/errors.js +1 -1
  42. package/dist/eval.d.ts +1 -1
  43. package/dist/eval.js +3 -3
  44. package/dist/exec-file-size-PXkr-MGA.js +63 -0
  45. package/dist/exec-file-size-PXkr-MGA.js.map +1 -0
  46. package/dist/extensions.d.ts +2 -0
  47. package/dist/extensions.js +2 -0
  48. package/dist/generate-data-WL_yGVL6.js +324 -0
  49. package/dist/generate-data-WL_yGVL6.js.map +1 -0
  50. package/dist/headless.d.ts +1 -1
  51. package/dist/headless.js +15 -10
  52. package/dist/headless.js.map +1 -1
  53. package/dist/index-B8UtiZy7.d.ts +14967 -0
  54. package/dist/index-B8UtiZy7.d.ts.map +1 -0
  55. package/dist/{index-B3ciFUZx.d.ts → index-DsPQbyUn.d.ts} +2 -2
  56. package/dist/index-DsPQbyUn.d.ts.map +1 -0
  57. package/dist/index.d.ts +6 -12
  58. package/dist/index.js +20 -43
  59. package/dist/index.js.map +1 -1
  60. package/dist/{logger-Ktm-lj1s.js → logger-DBX9uYOw.js} +108 -5
  61. package/dist/logger-DBX9uYOw.js.map +1 -0
  62. package/dist/login-DOF8pMVM.js +539 -0
  63. package/dist/login-DOF8pMVM.js.map +1 -0
  64. package/dist/{mcp-Dn5W65Lv.js → mcp-CcvuVXB9.js} +2 -2
  65. package/dist/{mcp-Dn5W65Lv.js.map → mcp-CcvuVXB9.js.map} +1 -1
  66. package/dist/mcp.d.ts +1 -1
  67. package/dist/mcp.js +1 -1
  68. package/dist/{messages-YZQLKaz2.js → messages-CwujiS74.js} +4 -4
  69. package/dist/messages-CwujiS74.js.map +1 -0
  70. package/dist/{openai-compat-0Y7jcncn.js → openai-compat-BvgYGSR1.js} +7 -6
  71. package/dist/{openai-compat-0Y7jcncn.js.map → openai-compat-BvgYGSR1.js.map} +1 -1
  72. package/dist/output/stream-json.d.ts +1 -2
  73. package/dist/output/stream-json.d.ts.map +1 -1
  74. package/dist/output/terminal.d.ts +1 -2
  75. package/dist/output/terminal.d.ts.map +1 -1
  76. package/dist/{glob-DluQFSw1.js → output-cap-kBUHBlnq.js} +50 -2
  77. package/dist/output-cap-kBUHBlnq.js.map +1 -0
  78. package/dist/presets.d.ts +1 -2
  79. package/dist/presets.js +1 -1
  80. package/dist/providers/anthropic.d.ts +2 -2
  81. package/dist/providers/anthropic.js +2 -2
  82. package/dist/providers/arcee.d.ts +1 -1
  83. package/dist/providers/arcee.js +1 -1
  84. package/dist/providers/baseten.d.ts +1 -1
  85. package/dist/providers/baseten.js +1 -1
  86. package/dist/providers/cerebras.d.ts +1 -1
  87. package/dist/providers/cerebras.js +1 -1
  88. package/dist/providers/local.d.ts +1 -1
  89. package/dist/providers/local.js +1 -1
  90. package/dist/providers/openai-compat.d.ts +1 -1
  91. package/dist/providers/openai-compat.js +1 -1
  92. package/dist/providers/openai.d.ts +1 -1
  93. package/dist/providers/openai.js +4 -4
  94. package/dist/providers/openai.js.map +1 -1
  95. package/dist/providers/openrouter.d.ts +1 -1
  96. package/dist/providers/openrouter.js +1 -1
  97. package/dist/providers/xai.d.ts +1 -1
  98. package/dist/providers/xai.js +1 -1
  99. package/dist/{providers-DgmdYGKm.js → providers-z6LDMAr3.js} +3 -3
  100. package/dist/{providers-DgmdYGKm.js.map → providers-z6LDMAr3.js.map} +1 -1
  101. package/dist/providers.d.ts +1 -1
  102. package/dist/providers.js +4 -4
  103. package/dist/{read-state-BymF41Jb.js → read-state-Dq_TXUX1.js} +2 -2
  104. package/dist/{read-state-BymF41Jb.js.map → read-state-Dq_TXUX1.js.map} +1 -1
  105. package/dist/{interpolate-BtIgcCuz.js → resolve-Cr8JSL_O.js} +562 -136
  106. package/dist/resolve-Cr8JSL_O.js.map +1 -0
  107. package/dist/restate.d.ts +2 -2
  108. package/dist/restate.js +2 -2
  109. package/dist/{sandbox-Dgy-m6UF.d.ts → sandbox-CgjG2VvQ.d.ts} +2 -2
  110. package/dist/{sandbox-Dgy-m6UF.d.ts.map → sandbox-CgjG2VvQ.d.ts.map} +1 -1
  111. package/dist/session/sqlite.d.ts +1 -1
  112. package/dist/{session-CqrAFAKJ.js → session-CsdDIPY8.js} +108 -3
  113. package/dist/session-CsdDIPY8.js.map +1 -0
  114. package/dist/session.d.ts +2 -2
  115. package/dist/session.js +3 -3
  116. package/dist/skills-Bsb0rvWI.js +295 -0
  117. package/dist/skills-Bsb0rvWI.js.map +1 -0
  118. package/dist/skills.d.ts +2 -3
  119. package/dist/skills.js +3 -24
  120. package/dist/{errors-CkTvg97v.d.ts → timeout-8vSIRjzl.d.ts} +10 -2
  121. package/dist/timeout-8vSIRjzl.d.ts.map +1 -0
  122. package/dist/{timeout-kGGSXagK.js → timeout-BDetbuN6.js} +59 -2
  123. package/dist/timeout-BDetbuN6.js.map +1 -0
  124. package/dist/tool-formatters-DY0TDb1r.d.ts +378 -0
  125. package/dist/tool-formatters-DY0TDb1r.d.ts.map +1 -0
  126. package/dist/tools/fetch-url.d.ts +1 -1
  127. package/dist/tools/web-search.d.ts +1 -1
  128. package/dist/tools.d.ts +2 -3
  129. package/dist/tools.js +3 -4
  130. package/dist/{transcript-anchors-BHIgMlPq.d.ts → transcript-anchors-Cb-bDbNH.d.ts} +233 -640
  131. package/dist/transcript-anchors-Cb-bDbNH.d.ts.map +1 -0
  132. package/dist/{transcript-anchors-DsoBHg43.js → transcript-anchors-DSRPWjiH.js} +391 -961
  133. package/dist/transcript-anchors-DSRPWjiH.js.map +1 -0
  134. package/dist/tui.d.ts +335 -11
  135. package/dist/tui.d.ts.map +1 -1
  136. package/dist/tui.js +6375 -1892
  137. package/dist/tui.js.map +1 -1
  138. package/dist/{turn-operations-Dw02ZoSQ.d.ts → turn-operations-CgMROLsr.d.ts} +29 -4
  139. package/dist/turn-operations-CgMROLsr.d.ts.map +1 -0
  140. package/dist/{turn-operations-tG0vuBNc.js → turn-operations-Dq9Kx7m2.js} +321 -81
  141. package/dist/turn-operations-Dq9Kx7m2.js.map +1 -0
  142. package/dist/{types-BqdTeBaC.d.ts → types-BDccavwj.d.ts} +42 -1
  143. package/dist/types-BDccavwj.d.ts.map +1 -0
  144. package/dist/{types-CyVGdbia.js → types-BIarq1qE.js} +90 -2
  145. package/dist/types-BIarq1qE.js.map +1 -0
  146. package/dist/types.d.ts +5 -6
  147. package/dist/types.js +1 -1
  148. package/dist/{xai-tPdbAGkq.js → xai-B_e6TOA8.js} +2 -2
  149. package/dist/{xai-tPdbAGkq.js.map → xai-B_e6TOA8.js.map} +1 -1
  150. package/docs/ARCHITECTURE.md +1 -1
  151. package/docs/CHAT.md +7 -6
  152. package/docs/EXECUTION_CONTEXT.md +16 -0
  153. package/docs/EXTENSIONS.md +1063 -0
  154. package/docs/SKILL.md +16 -0
  155. package/docs/TUI.md +10 -3
  156. package/package.json +12 -3
  157. package/dist/agent-Cch2ayTt.js.map +0 -1
  158. package/dist/agent-EFWt6uQ_.d.ts +0 -6914
  159. package/dist/agent-EFWt6uQ_.d.ts.map +0 -1
  160. package/dist/anthropic-RGqsJlC8.js.map +0 -1
  161. package/dist/auth-C-ms5N2x.js.map +0 -1
  162. package/dist/context-breakdown-kO-pDsay.js.map +0 -1
  163. package/dist/contexts-Lzf5huID.js.map +0 -1
  164. package/dist/errors-CkTvg97v.d.ts.map +0 -1
  165. package/dist/glob-DluQFSw1.js.map +0 -1
  166. package/dist/glob-shell-rJMoCIGb.js +0 -21
  167. package/dist/glob-shell-rJMoCIGb.js.map +0 -1
  168. package/dist/index-B3ciFUZx.d.ts.map +0 -1
  169. package/dist/index-BtzE3Uaq.d.ts +0 -2738
  170. package/dist/index-BtzE3Uaq.d.ts.map +0 -1
  171. package/dist/index-tSzOaWNt.d.ts +0 -316
  172. package/dist/index-tSzOaWNt.d.ts.map +0 -1
  173. package/dist/interpolate-BtIgcCuz.js.map +0 -1
  174. package/dist/logger-DGiGf7DW.d.ts +0 -102
  175. package/dist/logger-DGiGf7DW.d.ts.map +0 -1
  176. package/dist/logger-Ktm-lj1s.js.map +0 -1
  177. package/dist/login-CCA-1lgK.js +0 -267
  178. package/dist/login-CCA-1lgK.js.map +0 -1
  179. package/dist/messages-YZQLKaz2.js.map +0 -1
  180. package/dist/policy-DcGlpaNs.d.ts +0 -129
  181. package/dist/policy-DcGlpaNs.d.ts.map +0 -1
  182. package/dist/presets-BQWYMHdd.js +0 -114
  183. package/dist/presets-BQWYMHdd.js.map +0 -1
  184. package/dist/run-summary-DkN8KsHM.d.ts +0 -249
  185. package/dist/run-summary-DkN8KsHM.d.ts.map +0 -1
  186. package/dist/session-CqrAFAKJ.js.map +0 -1
  187. package/dist/shell-quote-BmnhZmdM.js +0 -33
  188. package/dist/shell-quote-BmnhZmdM.js.map +0 -1
  189. package/dist/skills.js.map +0 -1
  190. package/dist/timeout-CpFm0jJ6.d.ts +0 -10
  191. package/dist/timeout-CpFm0jJ6.d.ts.map +0 -1
  192. package/dist/timeout-kGGSXagK.js.map +0 -1
  193. package/dist/tool-formatters-C6iLgc9f.d.ts +0 -1454
  194. package/dist/tool-formatters-C6iLgc9f.d.ts.map +0 -1
  195. package/dist/tools-CCd8e-HT.js +0 -1739
  196. package/dist/tools-CCd8e-HT.js.map +0 -1
  197. package/dist/transcript-anchors-BHIgMlPq.d.ts.map +0 -1
  198. package/dist/transcript-anchors-DsoBHg43.js.map +0 -1
  199. package/dist/turn-operations-Dw02ZoSQ.d.ts.map +0 -1
  200. package/dist/turn-operations-tG0vuBNc.js.map +0 -1
  201. package/dist/types-BqdTeBaC.d.ts.map +0 -1
  202. package/dist/types-CyVGdbia.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"headless.js","names":["basic"],"sources":["../src/headless.ts"],"sourcesContent":["/**\n * Headless mode — a non-interactive, fully-structured way to drive the agent\n * for automation and RL rollouts.\n *\n * `agent.run()` already returns rich {@link AgentStats}, the session captures a\n * lossless transcript (`session.turns`), and the hook bus exposes every\n * streaming/tool/turn event. What this module adds is the *contract* an RL loop\n * needs: one call (`runHeadless`) that runs a prompt to completion in a chosen\n * workdir, bounded by turns + wall-clock, and hands back a single serializable\n * {@link HeadlessResult} — final answer, verifiable structured output, usage,\n * and the complete trajectory — plus an optional live {@link HeadlessEvent}\n * stream (the in-process equivalent of `--output-format stream-json`).\n *\n * It is provider-agnostic: the caller passes a built {@link Provider} (e.g.\n * `local()` pointed at a vLLM server, or any of the named providers). The thin\n * CLI in `src/headless-cli.ts` wraps this with arg parsing, file/stdin I/O, and\n * JSONL transcript writing.\n */\n\nimport type { Hookable } from 'hookable'\nimport type { AgentHooks, AgentOptions } from './agent'\nimport type { ExecutionContext } from './contexts'\nimport type { Provider } from './providers'\nimport type { RunSummary } from './run-summary'\nimport type { Session, SessionStore } from './session'\nimport type { PairingRepair } from './session/messages'\nimport type { ToolDef } from './tools'\nimport type {\n AgentStats,\n McpServerConfig,\n PromptPart,\n SessionContentBlock,\n SessionTurn,\n ThinkingLevel,\n ToolResultContent,\n ToolResultDocumentContent,\n TurnFinishReason,\n} from './types'\nimport { createAgent } from './agent'\nimport { createProcessContext } from './contexts'\nimport { basic } from './presets'\nimport { createRunSummaryCollector } from './run-summary'\nimport { createMemoryStore, createSession, toAnthropic } from './session'\nimport { ensureToolResultPairing } from './session/messages'\nimport { audioFormatFromMediaType } from './tools/media-sniff'\nimport { assertResolvedMediaBlock, documentBlockMarker, toolResultToText } from './types'\n\n// ---------------------------------------------------------------------------\n// Public shapes\n// ---------------------------------------------------------------------------\n\nexport type HeadlessStatus = 'completed' | 'aborted' | 'error' | 'timeout'\n\nexport interface HeadlessUsage {\n input: number\n output: number\n cacheRead: number\n cacheCreation: number\n /** Cumulative USD cost when the provider/registry could price the run. */\n cost?: number\n}\n\nexport interface HeadlessErrorInfo {\n message: string\n /** Typed-error class name (`AgentAbortedError`, `AgentContextExceededError`, …). */\n type: string\n}\n\n/**\n * Strictly JSON-serializable postmortem of one headless run. Everything an RL\n * reward function needs: the final answer (`finalText`), the verifiable\n * structured output (`output`, present iff a `schema` was set), usage/turns,\n * and the lossless `transcript` (the SFT training data).\n */\nexport interface HeadlessResult {\n status: HeadlessStatus\n /** Concatenated text of the last assistant turn that produced any text. */\n finalText: string\n /** Schema-enforced structured output (only when `opts.schema` is set). */\n output?: Record<string, unknown>\n usage: HeadlessUsage\n turns: number\n durationMs: number\n /** Total `tool_call` blocks across the whole transcript. */\n numToolCalls: number\n /** Finish reason of the final turn that reported one. */\n finishReason?: TurnFinishReason\n error?: HeadlessErrorInfo\n sessionId: string\n /** Incident postmortem (errors, gate blocks, budget events) via run-summary. */\n summary?: RunSummary\n /** Lossless transcript — raw `session.turns`. Thinking stripped when `includeThinking: false`. */\n transcript: SessionTurn[]\n}\n\nexport type HeadlessOutputFormat = 'zidane' | 'provider'\n\nexport type ProviderTranscriptFormat = 'anthropic' | 'openai'\n\nexport type FormattedHeadlessResult\n = | HeadlessResult\n | unknown[]\n\nexport type FormattedHeadlessTurnEvent\n = | Extract<HeadlessEvent, { type: 'turn' }>\n | unknown[]\n\nexport function exitCodeForHeadlessResult(result: HeadlessResult): number {\n switch (result.status) {\n case 'completed': return 0\n case 'timeout': return 124\n case 'aborted': return 130\n case 'error':\n default: return 1\n }\n}\n\n/**\n * Live event union — the in-process equivalent of a `stream-json` line. Every\n * member is JSON-serializable; render to JSONL with {@link headlessEventToJsonl}.\n */\nexport type HeadlessEvent\n = | { type: 'start', runId: string, provider?: string }\n | { type: 'text', delta: string }\n | { type: 'thinking', delta: string }\n | { type: 'tool_call', callId: string, name: string, input: Record<string, unknown> }\n | { type: 'tool_result', callId: string, name: string, output: string, isError: boolean }\n | { type: 'turn', index: number, turn: SessionTurn }\n | { type: 'spawn', event: 'before' | 'complete' | 'error', id: string, info?: Record<string, unknown> }\n | { type: 'error', message: string, errorType?: string }\n | { type: 'result', result: HeadlessResult }\n\n/** Serialize one event as a newline-terminated JSON line (stream-json). */\nexport function headlessEventToJsonl(event: HeadlessEvent): string {\n return `${JSON.stringify(event)}\\n`\n}\n\nexport function formattedHeadlessTurnEventToJsonl(event: FormattedHeadlessTurnEvent): string {\n return `${JSON.stringify(event)}\\n`\n}\n\nexport function providerTranscriptFormatForProvider(providerName: string): ProviderTranscriptFormat {\n return providerName === 'anthropic' ? 'anthropic' : 'openai'\n}\n\nexport function transcriptToProviderMessages(\n turns: SessionTurn[],\n providerName: string,\n): unknown[] {\n const format = providerTranscriptFormatForProvider(providerName)\n if (format === 'anthropic') {\n return turns\n .filter((turn): turn is SessionTurn & { role: 'user' | 'assistant' } => turn.role === 'user' || turn.role === 'assistant')\n .map(turn => toAnthropic({ role: turn.role, content: turn.content }))\n }\n return transcriptToOpenAIMessages(turns, { strictToolPairing: false })\n}\n\nexport function formatHeadlessResult(\n result: HeadlessResult,\n options: { format: HeadlessOutputFormat, providerName: string },\n): FormattedHeadlessResult {\n if (options.format === 'zidane')\n return result\n return transcriptToProviderMessages(result.transcript, options.providerName)\n}\n\nexport function formatHeadlessTurnEvent(\n event: Extract<HeadlessEvent, { type: 'turn' }>,\n options: { format: HeadlessOutputFormat, providerName: string },\n): FormattedHeadlessTurnEvent {\n if (options.format === 'zidane')\n return event\n return transcriptToProviderMessages([event.turn], options.providerName)\n}\n\nexport interface HeadlessOptions {\n /** User prompt — plain string or multimodal `PromptPart[]`. */\n prompt: string | PromptPart[]\n /** Built provider (e.g. `local()`, `openaiCompat(...)`, `anthropic(...)`). */\n provider: Provider\n model?: string\n /** Override the preset system prompt for this run. */\n system?: string\n thinking?: ThinkingLevel\n maxTurns?: number\n maxTokens?: number\n /** Wall-clock cap; on expiry the run is aborted and `status` becomes `'timeout'`. */\n timeoutMs?: number\n /** External abort signal — chained with the internal timeout controller. */\n signal?: AbortSignal\n /** JSON Schema for structured-output enforcement → populates `result.output`. */\n schema?: Record<string, unknown>\n /** Agent behavior defaults for this headless run. Top-level shortcuts below override matching fields. */\n behavior?: AgentOptions['behavior']\n /** Tool overrides. Omit to use the basic preset's tools. */\n tools?: Record<string, ToolDef>\n mcpServers?: McpServerConfig[]\n skills?: AgentOptions['skills']\n /** Execution context. Defaults to a process context rooted at `cwd`. */\n execution?: ExecutionContext\n /** Working directory for the default process context (ignored if `execution` is set). */\n cwd?: string\n /** Reuse / resume an existing session. */\n session?: Session\n /** Session store for a fresh session (defaults to an in-memory store). */\n store?: SessionStore\n /** Keep `thinking` blocks in `result.transcript` (default true). */\n includeThinking?: boolean\n /** Live event callback — the in-process stream-json equivalent. */\n onEvent?: (event: HeadlessEvent) => void\n}\n\n// ---------------------------------------------------------------------------\n// runHeadless\n// ---------------------------------------------------------------------------\n\n/**\n * Run a prompt to completion, headless, and return a single serializable\n * {@link HeadlessResult}. Safe to call concurrently for parallel rollouts —\n * each call builds its own agent + session and tears them down in `finally`.\n */\nexport async function runHeadless(opts: HeadlessOptions): Promise<HeadlessResult> {\n const startedAt = Date.now()\n const execution = opts.execution ?? createProcessContext({ cwd: opts.cwd })\n const session = opts.session ?? await createSession({ store: opts.store ?? createMemoryStore() })\n\n const behavior: NonNullable<AgentOptions['behavior']> = { ...(opts.behavior ?? {}) }\n if (opts.maxTurns !== undefined)\n behavior.maxTurns = opts.maxTurns\n if (opts.maxTokens !== undefined)\n behavior.maxTokens = opts.maxTokens\n if (opts.schema !== undefined)\n behavior.schema = opts.schema\n\n const agent = createAgent({\n ...basic,\n provider: opts.provider,\n execution,\n session,\n behavior,\n ...(opts.tools !== undefined ? { tools: opts.tools } : {}),\n ...(opts.mcpServers !== undefined ? { mcpServers: opts.mcpServers } : {}),\n ...(opts.skills !== undefined ? { skills: opts.skills } : {}),\n })\n\n const collector = createRunSummaryCollector()\n const uninstallSummary = collector.install(agent.hooks)\n const uninstallEvents = opts.onEvent ? installHeadlessEventAdapter(agent.hooks, opts.onEvent) : noop\n\n // Resumed sessions carry turns from prior runs — remember where this run\n // starts so transcript/finalText/numToolCalls stay per-run, matching the\n // per-run usage/turns/durationMs stats.\n const runStartIndex = session.turns.length\n\n // Internal controller drives the wall-clock timeout and chains any external\n // signal so a host cancel and a timeout both abort the same run. The\n // listener is removed in `finally` — a long-lived host signal must not\n // accumulate one listener per rollout.\n const controller = new AbortController()\n const onExternalAbort = (): void => controller.abort(opts.signal!.reason)\n if (opts.signal) {\n if (opts.signal.aborted)\n controller.abort(opts.signal.reason)\n else\n opts.signal.addEventListener('abort', onExternalAbort, { once: true })\n }\n let timedOut = false\n const timer = opts.timeoutMs && opts.timeoutMs > 0\n ? setTimeout(() => {\n timedOut = true\n controller.abort(new Error(`Headless run timed out after ${opts.timeoutMs}ms`))\n }, opts.timeoutMs)\n : undefined\n\n let stats: AgentStats | undefined\n let error: HeadlessErrorInfo | undefined\n\n try {\n stats = await agent.run({\n prompt: opts.prompt,\n signal: controller.signal,\n ...(opts.model !== undefined ? { model: opts.model } : {}),\n ...(opts.system !== undefined ? { system: opts.system } : {}),\n ...(opts.thinking !== undefined ? { thinking: opts.thinking } : {}),\n })\n }\n catch (err) {\n // The agent loop throws typed errors (AgentAbortedError,\n // AgentContextExceededError, AgentProviderError, …) — their `name` already\n // classifies the failure, so surface it directly.\n const e = err instanceof Error ? err : new Error(String(err))\n error = { message: e.message, type: e.name }\n }\n finally {\n if (timer)\n clearTimeout(timer)\n opts.signal?.removeEventListener('abort', onExternalAbort)\n uninstallEvents()\n uninstallSummary()\n await agent.destroy()\n }\n\n // Status: a thrown error wins, but an abort/timeout can also surface as a\n // clean resolve (the loop returns partial stats), so check the signal too.\n let status: HeadlessStatus\n if (error)\n status = timedOut ? 'timeout' : controller.signal.aborted ? 'aborted' : 'error'\n else if (controller.signal.aborted)\n status = timedOut ? 'timeout' : 'aborted'\n else\n status = 'completed'\n\n const rawTranscript = session.turns.slice(runStartIndex)\n const transcript = opts.includeThinking === false ? stripThinking(rawTranscript) : rawTranscript\n const summary = collector.latest()\n\n const result: HeadlessResult = {\n status,\n finalText: extractFinalText(rawTranscript),\n ...(stats?.output ? { output: stats.output } : {}),\n usage: {\n input: stats?.totalIn ?? 0,\n output: stats?.totalOut ?? 0,\n cacheRead: stats?.totalCacheRead ?? 0,\n cacheCreation: stats?.totalCacheCreation ?? 0,\n ...(typeof stats?.cost === 'number' ? { cost: stats.cost } : {}),\n },\n turns: stats?.turns ?? 0,\n durationMs: stats?.elapsed ?? (Date.now() - startedAt),\n numToolCalls: countToolCalls(rawTranscript),\n // Suppress `finishReason` on abort/timeout: the last persisted turn can\n // carry `finishReason: 'stop'` (e.g. the model finished a turn, a follow-up\n // continued, then the run was cancelled), which would make a consumer\n // keyed on `finishReason === 'stop'` misread a cancel as \"model finished\".\n // `status` is authoritative for those exits; let it speak alone. The\n // `'pause'` exhaustion exit keeps `status: 'completed'` so it still\n // surfaces its `finishReason: 'pause'` here.\n ...(status !== 'aborted' && status !== 'timeout' && lastFinishReason(stats)\n ? { finishReason: lastFinishReason(stats) }\n : {}),\n ...(error ? { error } : {}),\n sessionId: session.id,\n ...(summary ? { summary } : {}),\n transcript,\n }\n\n opts.onEvent?.({ type: 'result', result })\n return result\n}\n\n// ---------------------------------------------------------------------------\n// Transcript → OpenAI chat messages (SFT-ready)\n// ---------------------------------------------------------------------------\n\nexport interface OpenAIChatMessage {\n role: 'system' | 'user' | 'assistant' | 'tool'\n content: string | null | OpenAIChatContentPart[]\n tool_calls?: Array<{ id: string, type: 'function', function: { name: string, arguments: string } }>\n tool_call_id?: string\n}\n\nexport type OpenAIChatContentPart\n = | { type: 'text', text: string }\n | { type: 'image_url', image_url: { url: string } }\n | { type: 'input_audio', input_audio: { data: string, format: string } }\n | { type: 'video_url', video_url: { url: string } }\n\n/**\n * Convert raw `session.turns` into standard OpenAI chat-completion messages:\n * assistant turns carry `tool_calls`, and each `tool_result` becomes its own\n * `role: 'tool'` message. This is the drop-in shape for an SFT renderer —\n * unlike `toOpenAI` (session/messages.ts), which emits an internal `_tag`\n * envelope meant for re-sending to a provider, not for training data.\n *\n * Fails closed on corrupt raw turns instead of fabricating tool results; silent\n * placeholders would create structurally-valid but semantically-poisoned SFT\n * examples.\n */\nexport function transcriptToOpenAIMessages(\n turns: SessionTurn[],\n options: { strictToolPairing?: boolean } = {},\n): OpenAIChatMessage[] {\n const { strictToolPairing = true } = options\n const messages: OpenAIChatMessage[] = []\n let chunk: Array<{ role: 'user' | 'assistant', content: SessionContentBlock[] }> = []\n const flushChunk = () => {\n if (chunk.length === 0)\n return\n let paired = chunk\n if (strictToolPairing) {\n const repairs: PairingRepair[] = []\n paired = ensureToolResultPairing(chunk, { onRepair: repair => repairs.push(repair) })\n if (repairs.length > 0) {\n throw new Error(\n `Cannot convert transcript to OpenAI messages: tool pairing repair required (${repairs.map(r => r.mode).join(', ')})`,\n )\n }\n }\n for (const msg of paired)\n pushOpenAIChatMessage(messages, msg)\n chunk = []\n }\n\n for (const turn of turns) {\n if (turn.role === 'system') {\n flushChunk()\n messages.push({ role: 'system', content: textOf(turn.content) })\n continue\n }\n chunk.push({ role: turn.role, content: turn.content })\n }\n flushChunk()\n\n return messages\n}\n\nfunction pushOpenAIChatMessage(messages: OpenAIChatMessage[], msg: { role: 'user' | 'assistant', content: SessionContentBlock[] }): void {\n const text = textOf(msg.content)\n\n if (msg.role === 'assistant') {\n const toolCalls = msg.content.filter((b): b is ToolCallBlock => b.type === 'tool_call')\n const out: OpenAIChatMessage = { role: 'assistant', content: text || null }\n if (toolCalls.length > 0) {\n out.tool_calls = toolCalls.map(b => ({\n id: b.id,\n type: 'function' as const,\n function: { name: b.name, arguments: JSON.stringify(b.input) },\n }))\n }\n messages.push(out)\n return\n }\n\n // user turn — may carry prompt text/images and/or tool_result blocks\n const userParts = contentPartsFromBlocks(msg.content)\n if (userParts.length > 0)\n messages.push({ role: 'user', content: simplifyOpenAIContent(userParts) })\n\n for (const tr of msg.content.filter((b): b is ToolResultBlock => b.type === 'tool_result')) {\n const { text, images } = summarizeToolResultForOpenAI(tr.output)\n if (images.length === 0) {\n messages.push({ role: 'tool', tool_call_id: tr.callId, content: text })\n continue\n }\n\n const noun = images.length === 1 ? 'image' : 'images'\n const marker = `[${images.length} ${noun} attached — see next user message]`\n messages.push({\n role: 'tool',\n tool_call_id: tr.callId,\n content: text.length > 0 ? `${text}\\n\\n${marker}` : marker,\n })\n messages.push({\n role: 'user',\n content: [\n ...images.map(toOpenAIImagePart),\n { type: 'text', text: `(${noun} returned by tool call ${tr.callId})` },\n ],\n })\n }\n}\n\n// ---------------------------------------------------------------------------\n// Internals\n// ---------------------------------------------------------------------------\n\ntype TextBlock = Extract<SessionContentBlock, { type: 'text' }>\ntype ToolCallBlock = Extract<SessionContentBlock, { type: 'tool_call' }>\ntype ToolResultBlock = Extract<SessionContentBlock, { type: 'tool_result' }>\n\nfunction noop(): void {}\n\nfunction textOf(content: SessionContentBlock[]): string {\n return content.filter((b): b is TextBlock => b.type === 'text').map(b => b.text).join('')\n}\n\nfunction contentPartsFromBlocks(content: SessionContentBlock[]): OpenAIChatContentPart[] {\n const parts: OpenAIChatContentPart[] = []\n for (const block of content) {\n if (block.type === 'image') {\n assertResolvedMediaBlock(block, 'OpenAI transcript messages')\n parts.push(toOpenAIImagePart(block))\n }\n else if (block.type === 'audio') {\n parts.push({ type: 'input_audio', input_audio: { data: block.data, format: audioFormatFromMediaType(block.mediaType) } })\n }\n else if (block.type === 'video') {\n parts.push({ type: 'video_url', video_url: { url: `data:${block.mediaType};base64,${block.data}` } })\n }\n else if (block.type === 'document') {\n assertResolvedMediaBlock(block, 'OpenAI transcript messages')\n parts.push({ type: 'text', text: documentMarker(block) })\n }\n else if (block.type === 'text' && block.text.length > 0) {\n parts.push({ type: 'text', text: block.text })\n }\n }\n return parts\n}\n\nfunction simplifyOpenAIContent(parts: OpenAIChatContentPart[]): string | OpenAIChatContentPart[] {\n if (parts.length === 1 && parts[0].type === 'text')\n return parts[0].text\n return parts\n}\n\nfunction toOpenAIImagePart(image: { mediaType: string, data: string }): OpenAIChatContentPart {\n return {\n type: 'image_url',\n image_url: { url: `data:${image.mediaType};base64,${image.data}` },\n }\n}\n\nfunction summarizeToolResultForOpenAI(output: string | ToolResultContent[]): {\n text: string\n images: Array<{ mediaType: string, data: string }>\n} {\n if (typeof output === 'string')\n return { text: output, images: [] }\n\n const texts: string[] = []\n const images: Array<{ mediaType: string, data: string }> = []\n for (const block of output) {\n if (block.type === 'text') {\n texts.push(block.text)\n }\n else if (block.type === 'image') {\n assertResolvedMediaBlock(block, 'OpenAI transcript messages')\n images.push({ mediaType: block.mediaType, data: block.data })\n }\n else if (block.type === 'audio') {\n texts.push(`[audio: ${block.mediaType}]`)\n }\n else if (block.type === 'video') {\n texts.push(`[video: ${block.mediaType}]`)\n }\n else {\n assertResolvedMediaBlock(block, 'OpenAI transcript messages')\n texts.push(documentMarker(block))\n }\n }\n return { text: texts.join('\\n'), images }\n}\n\nfunction documentMarker(doc: ToolResultDocumentContent): string {\n return documentBlockMarker(doc, 'document omitted')\n}\n\nfunction extractFinalText(turns: SessionTurn[]): string {\n for (let i = turns.length - 1; i >= 0; i--) {\n const turn = turns[i]\n if (turn.role !== 'assistant')\n continue\n const text = textOf(turn.content)\n if (text)\n return text\n }\n return ''\n}\n\nfunction countToolCalls(turns: SessionTurn[]): number {\n let n = 0\n for (const turn of turns) {\n for (const block of turn.content) {\n if (block.type === 'tool_call')\n n++\n }\n }\n return n\n}\n\nfunction lastFinishReason(stats?: AgentStats): TurnFinishReason | undefined {\n const usages = stats?.turnUsage\n if (!usages)\n return undefined\n for (let i = usages.length - 1; i >= 0; i--) {\n if (usages[i].finishReason)\n return usages[i].finishReason\n }\n return undefined\n}\n\nfunction stripThinking(turns: SessionTurn[]): SessionTurn[] {\n return turns.map(turn => ({\n ...turn,\n content: turn.content.filter(b => b.type !== 'thinking' && b.type !== 'redacted_thinking'),\n }))\n}\n\nexport function installHeadlessEventAdapter(\n hooks: Hookable<AgentHooks>,\n onEvent: (event: HeadlessEvent) => void,\n): () => void {\n const unregs: Array<() => void> = []\n const emittedTurnIds = new Set<string>()\n const emit = (event: HeadlessEvent): void => {\n try {\n onEvent(event)\n }\n catch {\n // A consumer's sink throwing is not the adapter's concern.\n }\n }\n\n unregs.push(hooks.hook('agent:start', ctx => emit({\n type: 'start',\n runId: ctx.runId,\n ...(ctx.providerName ? { provider: ctx.providerName } : {}),\n })))\n unregs.push(hooks.hook('stream:text', ctx => emit({ type: 'text', delta: ctx.delta })))\n unregs.push(hooks.hook('stream:thinking', ctx => emit({ type: 'thinking', delta: ctx.delta })))\n unregs.push(hooks.hook('tool:before', ctx => emit({\n type: 'tool_call',\n callId: ctx.callId,\n name: ctx.name,\n input: ctx.input,\n })))\n unregs.push(hooks.hook('tool:after', ctx => emit({\n type: 'tool_result',\n callId: ctx.callId,\n name: ctx.name,\n output: toolResultToText(ctx.result),\n isError: false,\n })))\n unregs.push(hooks.hook('tool:error', ctx => emit({\n type: 'tool_result',\n callId: ctx.callId,\n name: ctx.name,\n output: ctx.error.message,\n isError: true,\n })))\n unregs.push(hooks.hook('session:turns', (ctx) => {\n const startIndex = ctx.count - ctx.turns.length\n ctx.turns.forEach((turn, i) => {\n if (emittedTurnIds.has(turn.id))\n return\n emittedTurnIds.add(turn.id)\n emit({ type: 'turn', index: startIndex + i, turn })\n })\n }))\n unregs.push(hooks.hook('spawn:before', ctx => emit({ type: 'spawn', event: 'before', id: ctx.id })))\n unregs.push(hooks.hook('spawn:complete', ctx => emit({\n type: 'spawn',\n event: 'complete',\n id: ctx.id,\n info: { status: ctx.status ?? 'completed' },\n })))\n unregs.push(hooks.hook('spawn:error', ctx => emit({\n type: 'spawn',\n event: 'error',\n id: ctx.id,\n info: { message: ctx.error.message },\n })))\n unregs.push(hooks.hook('stream:error', ctx => emit({\n type: 'error',\n message: ctx.err instanceof Error ? ctx.err.message : String(ctx.err),\n ...(ctx.err instanceof Error ? { errorType: ctx.err.name } : {}),\n })))\n\n return () => {\n for (const un of unregs) {\n try {\n un()\n }\n catch {\n // ignore\n }\n }\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"headless.js","names":["basic"],"sources":["../src/headless.ts"],"sourcesContent":["/**\n * Headless mode — a non-interactive, fully-structured way to drive the agent\n * for automation and RL rollouts.\n *\n * `agent.run()` already returns rich {@link AgentStats}, the session captures a\n * lossless transcript (`session.turns`), and the hook bus exposes every\n * streaming/tool/turn event. What this module adds is the *contract* an RL loop\n * needs: one call (`runHeadless`) that runs a prompt to completion in a chosen\n * workdir, bounded by turns + wall-clock, and hands back a single serializable\n * {@link HeadlessResult} — final answer, verifiable structured output, usage,\n * and the complete trajectory — plus an optional live {@link HeadlessEvent}\n * stream (the in-process equivalent of `--output-format stream-json`).\n *\n * It is provider-agnostic: the caller passes a built {@link Provider} (e.g.\n * `local()` pointed at a vLLM server, or any of the named providers). The thin\n * CLI in `src/headless-cli.ts` wraps this with arg parsing, file/stdin I/O, and\n * JSONL transcript writing.\n */\n\nimport type { Hookable } from 'hookable'\nimport type { AgentHooks, AgentOptions } from './agent'\nimport type { ExecutionContext } from './contexts'\nimport type { ExtensionRegistry } from './extensions'\nimport type { Preset } from './presets'\nimport type { Provider } from './providers'\nimport type { RunSummary } from './run-summary'\nimport type { Session, SessionStore } from './session'\nimport type { PairingRepair } from './session/messages'\nimport type { ToolDef } from './tools'\nimport type {\n AgentStats,\n McpServerConfig,\n PromptPart,\n SessionContentBlock,\n SessionTurn,\n ThinkingLevel,\n ToolResultContent,\n ToolResultDocumentContent,\n TurnFinishReason,\n} from './types'\nimport { createAgent } from './agent'\nimport { createProcessContext } from './contexts'\nimport { basic } from './presets'\nimport { createRunSummaryCollector } from './run-summary'\nimport { createMemoryStore, createSession, toAnthropic } from './session'\nimport { ensureToolResultPairing } from './session/messages'\nimport { audioFormatFromMediaType } from './tools/media-sniff'\nimport { assertResolvedMediaBlock, documentBlockMarker, isWireTurn, toolResultToText } from './types'\n\n// ---------------------------------------------------------------------------\n// Public shapes\n// ---------------------------------------------------------------------------\n\nexport type HeadlessStatus = 'completed' | 'aborted' | 'error' | 'timeout'\n\nexport interface HeadlessUsage {\n input: number\n output: number\n cacheRead: number\n cacheCreation: number\n /** Cumulative USD cost when the provider/registry could price the run. */\n cost?: number\n}\n\nexport interface HeadlessErrorInfo {\n message: string\n /** Typed-error class name (`AgentAbortedError`, `AgentContextExceededError`, …). */\n type: string\n}\n\n/**\n * Strictly JSON-serializable postmortem of one headless run. Everything an RL\n * reward function needs: the final answer (`finalText`), the verifiable\n * structured output (`output`, present iff a `schema` was set), usage/turns,\n * and the lossless `transcript` (the SFT training data).\n */\nexport interface HeadlessResult {\n status: HeadlessStatus\n /** Concatenated text of the last assistant turn that produced any text. */\n finalText: string\n /** Schema-enforced structured output (only when `opts.schema` is set). */\n output?: Record<string, unknown>\n usage: HeadlessUsage\n turns: number\n durationMs: number\n /** Total `tool_call` blocks across the whole transcript. */\n numToolCalls: number\n /** Finish reason of the final turn that reported one. */\n finishReason?: TurnFinishReason\n error?: HeadlessErrorInfo\n sessionId: string\n /** Incident postmortem (errors, gate blocks, budget events) via run-summary. */\n summary?: RunSummary\n /** Lossless transcript — raw `session.turns`. Thinking stripped when `includeThinking: false`. */\n transcript: SessionTurn[]\n}\n\nexport type HeadlessOutputFormat = 'zidane' | 'provider'\n\nexport type ProviderTranscriptFormat = 'anthropic' | 'openai'\n\nexport type FormattedHeadlessResult\n = | HeadlessResult\n | unknown[]\n\nexport type FormattedHeadlessTurnEvent\n = | Extract<HeadlessEvent, { type: 'turn' }>\n | unknown[]\n\nexport function exitCodeForHeadlessResult(result: HeadlessResult): number {\n switch (result.status) {\n case 'completed': return 0\n case 'timeout': return 124\n case 'aborted': return 130\n case 'error':\n default: return 1\n }\n}\n\n/**\n * Live event union — the in-process equivalent of a `stream-json` line. Every\n * member is JSON-serializable; render to JSONL with {@link headlessEventToJsonl}.\n */\nexport type HeadlessEvent\n = | { type: 'start', runId: string, provider?: string }\n | { type: 'text', delta: string }\n | { type: 'thinking', delta: string }\n | { type: 'tool_call', callId: string, name: string, input: Record<string, unknown> }\n | { type: 'tool_result', callId: string, name: string, output: string, isError: boolean }\n | { type: 'turn', index: number, turn: SessionTurn }\n | { type: 'spawn', event: 'before' | 'complete' | 'error', id: string, info?: Record<string, unknown> }\n | { type: 'error', message: string, errorType?: string }\n | { type: 'result', result: HeadlessResult }\n\n/** Serialize one event as a newline-terminated JSON line (stream-json). */\nexport function headlessEventToJsonl(event: HeadlessEvent): string {\n return `${JSON.stringify(event)}\\n`\n}\n\nexport function formattedHeadlessTurnEventToJsonl(event: FormattedHeadlessTurnEvent): string {\n return `${JSON.stringify(event)}\\n`\n}\n\nexport function providerTranscriptFormatForProvider(providerName: string): ProviderTranscriptFormat {\n return providerName === 'anthropic' ? 'anthropic' : 'openai'\n}\n\nexport function transcriptToProviderMessages(\n turns: SessionTurn[],\n providerName: string,\n): unknown[] {\n const format = providerTranscriptFormatForProvider(providerName)\n if (format === 'anthropic') {\n return turns\n .filter(isWireTurn)\n .map(turn => toAnthropic({ role: turn.role, content: turn.content }))\n }\n return transcriptToOpenAIMessages(turns, { strictToolPairing: false })\n}\n\nexport function formatHeadlessResult(\n result: HeadlessResult,\n options: { format: HeadlessOutputFormat, providerName: string },\n): FormattedHeadlessResult {\n if (options.format === 'zidane')\n return result\n return transcriptToProviderMessages(result.transcript, options.providerName)\n}\n\nexport function formatHeadlessTurnEvent(\n event: Extract<HeadlessEvent, { type: 'turn' }>,\n options: { format: HeadlessOutputFormat, providerName: string },\n): FormattedHeadlessTurnEvent {\n if (options.format === 'zidane')\n return event\n return transcriptToProviderMessages([event.turn], options.providerName)\n}\n\nexport interface HeadlessOptions {\n /** User prompt — plain string or multimodal `PromptPart[]`. */\n prompt: string | PromptPart[]\n /** Built provider (e.g. `local()`, `openaiCompat(...)`, `anthropic(...)`). */\n provider: Provider\n model?: string\n /** Override the preset system prompt for this run. */\n system?: string\n thinking?: ThinkingLevel\n maxTurns?: number\n maxTokens?: number\n /** Wall-clock cap; on expiry the run is aborted and `status` becomes `'timeout'`. */\n timeoutMs?: number\n /** External abort signal — chained with the internal timeout controller. */\n signal?: AbortSignal\n /** JSON Schema for structured-output enforcement → populates `result.output`. */\n schema?: Record<string, unknown>\n /** Agent behavior defaults for this headless run. Top-level shortcuts below override matching fields. */\n behavior?: AgentOptions['behavior']\n /** Tool overrides. Omit to use the basic preset's tools. */\n tools?: Record<string, ToolDef>\n mcpServers?: McpServerConfig[]\n skills?: AgentOptions['skills']\n /**\n * Base {@link Preset} for the agent — spread in place of the default `basic`\n * preset (use it to swap the system prompt / tool set wholesale). The\n * top-level shortcuts above (`system`, `behavior`, `tools`, `mcpServers`,\n * `skills`) still override matching preset fields.\n */\n preset?: Preset\n /**\n * Pre-built extension registry folded into the agent via `createAgent`\n * (build it with `buildExtensionRegistry(defs.map(inlineLoadedExtension))`).\n * Contributes the registry's tools / hooks / mcpServers / skills /\n * system-fragments / subagents, with the explicit options above winning on\n * collision. Because hooks fold through `createAgent`, a headless run with\n * `extensions` also gets extension hooks (e.g. a `tool:transform` that\n * rewrites results), not just tools.\n */\n extensions?: ExtensionRegistry\n /** Execution context. Defaults to a process context rooted at `cwd`. */\n execution?: ExecutionContext\n /** Working directory for the default process context (ignored if `execution` is set). */\n cwd?: string\n /** Reuse / resume an existing session. */\n session?: Session\n /** Session store for a fresh session (defaults to an in-memory store). */\n store?: SessionStore\n /** Keep `thinking` blocks in `result.transcript` (default true). */\n includeThinking?: boolean\n /** Live event callback — the in-process stream-json equivalent. */\n onEvent?: (event: HeadlessEvent) => void\n}\n\n// ---------------------------------------------------------------------------\n// runHeadless\n// ---------------------------------------------------------------------------\n\n/**\n * Run a prompt to completion, headless, and return a single serializable\n * {@link HeadlessResult}. Safe to call concurrently for parallel rollouts —\n * each call builds its own agent + session and tears them down in `finally`.\n */\nexport async function runHeadless(opts: HeadlessOptions): Promise<HeadlessResult> {\n const startedAt = Date.now()\n const execution = opts.execution ?? createProcessContext({ cwd: opts.cwd })\n const session = opts.session ?? await createSession({ store: opts.store ?? createMemoryStore() })\n\n // Layer behavior on top of the base preset's: the `behavior` key is spread\n // last into `createAgent`, so without seeding from `basePreset.behavior` a\n // custom `preset` carrying behavior defaults would be silently wiped (the\n // top-level shortcuts are meant to OVERRIDE preset fields, not replace them).\n const basePreset = opts.preset ?? basic\n const behavior: NonNullable<AgentOptions['behavior']> = { ...basePreset.behavior, ...(opts.behavior ?? {}) }\n if (opts.maxTurns !== undefined)\n behavior.maxTurns = opts.maxTurns\n if (opts.maxTokens !== undefined)\n behavior.maxTokens = opts.maxTokens\n if (opts.schema !== undefined)\n behavior.schema = opts.schema\n\n const agent = createAgent({\n ...basePreset,\n provider: opts.provider,\n execution,\n session,\n behavior,\n ...(opts.tools !== undefined ? { tools: opts.tools } : {}),\n ...(opts.mcpServers !== undefined ? { mcpServers: opts.mcpServers } : {}),\n ...(opts.skills !== undefined ? { skills: opts.skills } : {}),\n ...(opts.extensions !== undefined ? { extensions: opts.extensions } : {}),\n })\n\n const collector = createRunSummaryCollector()\n const uninstallSummary = collector.install(agent.hooks)\n const uninstallEvents = opts.onEvent ? installHeadlessEventAdapter(agent.hooks, opts.onEvent) : noop\n\n // Resumed sessions carry turns from prior runs — remember where this run\n // starts so transcript/finalText/numToolCalls stay per-run, matching the\n // per-run usage/turns/durationMs stats.\n const runStartIndex = session.turns.length\n\n // Internal controller drives the wall-clock timeout and chains any external\n // signal so a host cancel and a timeout both abort the same run. The\n // listener is removed in `finally` — a long-lived host signal must not\n // accumulate one listener per rollout.\n const controller = new AbortController()\n const onExternalAbort = (): void => controller.abort(opts.signal!.reason)\n if (opts.signal) {\n if (opts.signal.aborted)\n controller.abort(opts.signal.reason)\n else\n opts.signal.addEventListener('abort', onExternalAbort, { once: true })\n }\n let timedOut = false\n const timer = opts.timeoutMs && opts.timeoutMs > 0\n ? setTimeout(() => {\n timedOut = true\n controller.abort(new Error(`Headless run timed out after ${opts.timeoutMs}ms`))\n }, opts.timeoutMs)\n : undefined\n\n let stats: AgentStats | undefined\n let error: HeadlessErrorInfo | undefined\n\n try {\n stats = await agent.run({\n prompt: opts.prompt,\n signal: controller.signal,\n ...(opts.model !== undefined ? { model: opts.model } : {}),\n ...(opts.system !== undefined ? { system: opts.system } : {}),\n ...(opts.thinking !== undefined ? { thinking: opts.thinking } : {}),\n })\n }\n catch (err) {\n // The agent loop throws typed errors (AgentAbortedError,\n // AgentContextExceededError, AgentProviderError, …) — their `name` already\n // classifies the failure, so surface it directly.\n const e = err instanceof Error ? err : new Error(String(err))\n error = { message: e.message, type: e.name }\n }\n finally {\n if (timer)\n clearTimeout(timer)\n opts.signal?.removeEventListener('abort', onExternalAbort)\n uninstallEvents()\n uninstallSummary()\n await agent.destroy()\n }\n\n // Status: a thrown error wins, but an abort/timeout can also surface as a\n // clean resolve (the loop returns partial stats), so check the signal too.\n let status: HeadlessStatus\n if (error)\n status = timedOut ? 'timeout' : controller.signal.aborted ? 'aborted' : 'error'\n else if (controller.signal.aborted)\n status = timedOut ? 'timeout' : 'aborted'\n else\n status = 'completed'\n\n const rawTranscript = session.turns.slice(runStartIndex)\n const transcript = opts.includeThinking === false ? stripThinking(rawTranscript) : rawTranscript\n const summary = collector.latest()\n\n const result: HeadlessResult = {\n status,\n finalText: extractFinalText(rawTranscript),\n ...(stats?.output ? { output: stats.output } : {}),\n usage: {\n input: stats?.totalIn ?? 0,\n output: stats?.totalOut ?? 0,\n cacheRead: stats?.totalCacheRead ?? 0,\n cacheCreation: stats?.totalCacheCreation ?? 0,\n ...(typeof stats?.cost === 'number' ? { cost: stats.cost } : {}),\n },\n turns: stats?.turns ?? 0,\n durationMs: stats?.elapsed ?? (Date.now() - startedAt),\n numToolCalls: countToolCalls(rawTranscript),\n // Suppress `finishReason` on abort/timeout: the last persisted turn can\n // carry `finishReason: 'stop'` (e.g. the model finished a turn, a follow-up\n // continued, then the run was cancelled), which would make a consumer\n // keyed on `finishReason === 'stop'` misread a cancel as \"model finished\".\n // `status` is authoritative for those exits; let it speak alone. The\n // `'pause'` exhaustion exit keeps `status: 'completed'` so it still\n // surfaces its `finishReason: 'pause'` here.\n ...(status !== 'aborted' && status !== 'timeout' && lastFinishReason(stats)\n ? { finishReason: lastFinishReason(stats) }\n : {}),\n ...(error ? { error } : {}),\n sessionId: session.id,\n ...(summary ? { summary } : {}),\n transcript,\n }\n\n opts.onEvent?.({ type: 'result', result })\n return result\n}\n\n// ---------------------------------------------------------------------------\n// Transcript → OpenAI chat messages (SFT-ready)\n// ---------------------------------------------------------------------------\n\nexport interface OpenAIChatMessage {\n role: 'system' | 'user' | 'assistant' | 'tool'\n content: string | null | OpenAIChatContentPart[]\n tool_calls?: Array<{ id: string, type: 'function', function: { name: string, arguments: string } }>\n tool_call_id?: string\n}\n\nexport type OpenAIChatContentPart\n = | { type: 'text', text: string }\n | { type: 'image_url', image_url: { url: string } }\n | { type: 'input_audio', input_audio: { data: string, format: string } }\n | { type: 'video_url', video_url: { url: string } }\n\n/**\n * Convert raw `session.turns` into standard OpenAI chat-completion messages:\n * assistant turns carry `tool_calls`, and each `tool_result` becomes its own\n * `role: 'tool'` message. This is the drop-in shape for an SFT renderer —\n * unlike `toOpenAI` (session/messages.ts), which emits an internal `_tag`\n * envelope meant for re-sending to a provider, not for training data.\n *\n * Fails closed on corrupt raw turns instead of fabricating tool results; silent\n * placeholders would create structurally-valid but semantically-poisoned SFT\n * examples.\n */\nexport function transcriptToOpenAIMessages(\n turns: SessionTurn[],\n options: { strictToolPairing?: boolean } = {},\n): OpenAIChatMessage[] {\n const { strictToolPairing = true } = options\n const messages: OpenAIChatMessage[] = []\n let chunk: Array<{ role: 'user' | 'assistant', content: SessionContentBlock[] }> = []\n const flushChunk = () => {\n if (chunk.length === 0)\n return\n let paired = chunk\n if (strictToolPairing) {\n const repairs: PairingRepair[] = []\n paired = ensureToolResultPairing(chunk, { onRepair: repair => repairs.push(repair) })\n if (repairs.length > 0) {\n throw new Error(\n `Cannot convert transcript to OpenAI messages: tool pairing repair required (${repairs.map(r => r.mode).join(', ')})`,\n )\n }\n }\n for (const msg of paired)\n pushOpenAIChatMessage(messages, msg)\n chunk = []\n }\n\n for (const turn of turns) {\n if (turn.role === 'system') {\n flushChunk()\n messages.push({ role: 'system', content: textOf(turn.content) })\n continue\n }\n // Non-wire turns (display-only `command`, and any future non-wire role)\n // never reach the model — shared, fail-safe guard.\n if (!isWireTurn(turn))\n continue\n chunk.push({ role: turn.role, content: turn.content })\n }\n flushChunk()\n\n return messages\n}\n\nfunction pushOpenAIChatMessage(messages: OpenAIChatMessage[], msg: { role: 'user' | 'assistant', content: SessionContentBlock[] }): void {\n const text = textOf(msg.content)\n\n if (msg.role === 'assistant') {\n const toolCalls = msg.content.filter((b): b is ToolCallBlock => b.type === 'tool_call')\n const out: OpenAIChatMessage = { role: 'assistant', content: text || null }\n if (toolCalls.length > 0) {\n out.tool_calls = toolCalls.map(b => ({\n id: b.id,\n type: 'function' as const,\n function: { name: b.name, arguments: JSON.stringify(b.input) },\n }))\n }\n messages.push(out)\n return\n }\n\n // user turn — may carry prompt text/images and/or tool_result blocks\n const userParts = contentPartsFromBlocks(msg.content)\n if (userParts.length > 0)\n messages.push({ role: 'user', content: simplifyOpenAIContent(userParts) })\n\n for (const tr of msg.content.filter((b): b is ToolResultBlock => b.type === 'tool_result')) {\n const { text, images } = summarizeToolResultForOpenAI(tr.output)\n if (images.length === 0) {\n messages.push({ role: 'tool', tool_call_id: tr.callId, content: text })\n continue\n }\n\n const noun = images.length === 1 ? 'image' : 'images'\n const marker = `[${images.length} ${noun} attached — see next user message]`\n messages.push({\n role: 'tool',\n tool_call_id: tr.callId,\n content: text.length > 0 ? `${text}\\n\\n${marker}` : marker,\n })\n messages.push({\n role: 'user',\n content: [\n ...images.map(toOpenAIImagePart),\n { type: 'text', text: `(${noun} returned by tool call ${tr.callId})` },\n ],\n })\n }\n}\n\n// ---------------------------------------------------------------------------\n// Internals\n// ---------------------------------------------------------------------------\n\ntype TextBlock = Extract<SessionContentBlock, { type: 'text' }>\ntype ToolCallBlock = Extract<SessionContentBlock, { type: 'tool_call' }>\ntype ToolResultBlock = Extract<SessionContentBlock, { type: 'tool_result' }>\n\nfunction noop(): void {}\n\nfunction textOf(content: SessionContentBlock[]): string {\n return content.filter((b): b is TextBlock => b.type === 'text').map(b => b.text).join('')\n}\n\nfunction contentPartsFromBlocks(content: SessionContentBlock[]): OpenAIChatContentPart[] {\n const parts: OpenAIChatContentPart[] = []\n for (const block of content) {\n if (block.type === 'image') {\n assertResolvedMediaBlock(block, 'OpenAI transcript messages')\n parts.push(toOpenAIImagePart(block))\n }\n else if (block.type === 'audio') {\n parts.push({ type: 'input_audio', input_audio: { data: block.data, format: audioFormatFromMediaType(block.mediaType) } })\n }\n else if (block.type === 'video') {\n parts.push({ type: 'video_url', video_url: { url: `data:${block.mediaType};base64,${block.data}` } })\n }\n else if (block.type === 'document') {\n assertResolvedMediaBlock(block, 'OpenAI transcript messages')\n parts.push({ type: 'text', text: documentMarker(block) })\n }\n else if (block.type === 'text' && block.text.length > 0) {\n parts.push({ type: 'text', text: block.text })\n }\n }\n return parts\n}\n\nfunction simplifyOpenAIContent(parts: OpenAIChatContentPart[]): string | OpenAIChatContentPart[] {\n if (parts.length === 1 && parts[0].type === 'text')\n return parts[0].text\n return parts\n}\n\nfunction toOpenAIImagePart(image: { mediaType: string, data: string }): OpenAIChatContentPart {\n return {\n type: 'image_url',\n image_url: { url: `data:${image.mediaType};base64,${image.data}` },\n }\n}\n\nfunction summarizeToolResultForOpenAI(output: string | ToolResultContent[]): {\n text: string\n images: Array<{ mediaType: string, data: string }>\n} {\n if (typeof output === 'string')\n return { text: output, images: [] }\n\n const texts: string[] = []\n const images: Array<{ mediaType: string, data: string }> = []\n for (const block of output) {\n if (block.type === 'text') {\n texts.push(block.text)\n }\n else if (block.type === 'image') {\n assertResolvedMediaBlock(block, 'OpenAI transcript messages')\n images.push({ mediaType: block.mediaType, data: block.data })\n }\n else if (block.type === 'audio') {\n texts.push(`[audio: ${block.mediaType}]`)\n }\n else if (block.type === 'video') {\n texts.push(`[video: ${block.mediaType}]`)\n }\n else {\n assertResolvedMediaBlock(block, 'OpenAI transcript messages')\n texts.push(documentMarker(block))\n }\n }\n return { text: texts.join('\\n'), images }\n}\n\nfunction documentMarker(doc: ToolResultDocumentContent): string {\n return documentBlockMarker(doc, 'document omitted')\n}\n\nfunction extractFinalText(turns: SessionTurn[]): string {\n for (let i = turns.length - 1; i >= 0; i--) {\n const turn = turns[i]\n if (turn.role !== 'assistant')\n continue\n const text = textOf(turn.content)\n if (text)\n return text\n }\n return ''\n}\n\nfunction countToolCalls(turns: SessionTurn[]): number {\n let n = 0\n for (const turn of turns) {\n for (const block of turn.content) {\n if (block.type === 'tool_call')\n n++\n }\n }\n return n\n}\n\nfunction lastFinishReason(stats?: AgentStats): TurnFinishReason | undefined {\n const usages = stats?.turnUsage\n if (!usages)\n return undefined\n for (let i = usages.length - 1; i >= 0; i--) {\n if (usages[i].finishReason)\n return usages[i].finishReason\n }\n return undefined\n}\n\nfunction stripThinking(turns: SessionTurn[]): SessionTurn[] {\n return turns.map(turn => ({\n ...turn,\n content: turn.content.filter(b => b.type !== 'thinking' && b.type !== 'redacted_thinking'),\n }))\n}\n\nexport function installHeadlessEventAdapter(\n hooks: Hookable<AgentHooks>,\n onEvent: (event: HeadlessEvent) => void,\n): () => void {\n const unregs: Array<() => void> = []\n const emittedTurnIds = new Set<string>()\n const emit = (event: HeadlessEvent): void => {\n try {\n onEvent(event)\n }\n catch {\n // A consumer's sink throwing is not the adapter's concern.\n }\n }\n\n unregs.push(hooks.hook('agent:start', ctx => emit({\n type: 'start',\n runId: ctx.runId,\n ...(ctx.providerName ? { provider: ctx.providerName } : {}),\n })))\n unregs.push(hooks.hook('stream:text', ctx => emit({ type: 'text', delta: ctx.delta })))\n unregs.push(hooks.hook('stream:thinking', ctx => emit({ type: 'thinking', delta: ctx.delta })))\n unregs.push(hooks.hook('tool:before', ctx => emit({\n type: 'tool_call',\n callId: ctx.callId,\n name: ctx.name,\n input: ctx.input,\n })))\n unregs.push(hooks.hook('tool:after', ctx => emit({\n type: 'tool_result',\n callId: ctx.callId,\n name: ctx.name,\n output: toolResultToText(ctx.result),\n isError: false,\n })))\n unregs.push(hooks.hook('tool:error', ctx => emit({\n type: 'tool_result',\n callId: ctx.callId,\n name: ctx.name,\n output: ctx.error.message,\n isError: true,\n })))\n unregs.push(hooks.hook('session:turns', (ctx) => {\n const startIndex = ctx.count - ctx.turns.length\n ctx.turns.forEach((turn, i) => {\n if (emittedTurnIds.has(turn.id))\n return\n emittedTurnIds.add(turn.id)\n emit({ type: 'turn', index: startIndex + i, turn })\n })\n }))\n unregs.push(hooks.hook('spawn:before', ctx => emit({ type: 'spawn', event: 'before', id: ctx.id })))\n unregs.push(hooks.hook('spawn:complete', ctx => emit({\n type: 'spawn',\n event: 'complete',\n id: ctx.id,\n info: { status: ctx.status ?? 'completed' },\n })))\n unregs.push(hooks.hook('spawn:error', ctx => emit({\n type: 'spawn',\n event: 'error',\n id: ctx.id,\n info: { message: ctx.error.message },\n })))\n unregs.push(hooks.hook('stream:error', ctx => emit({\n type: 'error',\n message: ctx.err instanceof Error ? ctx.err.message : String(ctx.err),\n ...(ctx.err instanceof Error ? { errorType: ctx.err.name } : {}),\n })))\n\n return () => {\n for (const un of unregs) {\n try {\n un()\n }\n catch {\n // ignore\n }\n }\n }\n}\n"],"mappings":"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"}