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 +0,0 @@
1
- {"version":3,"file":"messages-YZQLKaz2.js","names":[],"sources":["../src/session/messages.ts"],"sourcesContent":["/**\n * Canonical SessionMessage format with converters from/to Anthropic and OpenAI-compat formats.\n */\n\nimport type { Provider } from '../providers'\nimport type { ResolveContentRef, SessionContentBlock, SessionMessage, ToolResultContent, ToolResultDocumentContent } from '../types'\nimport { fnv1aBase36 } from '../hash'\nimport { ASSISTANT_TOOL_CALLS_TAG, TOOL_RESULTS_TAG } from '../providers/openai-compat'\nimport { audioFormatFromMediaType, reconcileImageMediaType } from '../tools/media-sniff'\nimport { assertResolvedMediaBlock, documentBlockMarker } from '../types'\n\ntype ToolCallBlock = Extract<SessionContentBlock, { type: 'tool_call' }>\ninterface ContentRefBlock {\n type: 'image' | 'document'\n ref: string\n mediaType: string\n encoding?: 'base64' | 'text'\n name?: string\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Decode an Anthropic `tool_result.content` wire value back to zidane's canonical\n * `string | ToolResultContent[]` shape.\n *\n * Anthropic accepts three shapes in the wire: `string`, `Array<{type:'text',text}>`,\n * or `Array<{type:'text'|'image', ...}>`. We collapse to `string` only when every\n * block is text to keep simple cases readable.\n */\nfunction decodeAnthropicToolResultContent(content: unknown): string | ToolResultContent[] {\n if (typeof content === 'string')\n return content\n\n if (!Array.isArray(content))\n return JSON.stringify(content)\n\n const blocks: ToolResultContent[] = []\n for (const raw of content) {\n if (!raw || typeof raw !== 'object')\n continue\n const b = raw as Record<string, unknown>\n if (b.type === 'text' && typeof b.text === 'string') {\n blocks.push({ type: 'text', text: b.text })\n continue\n }\n if (b.type === 'image' && b.source && typeof b.source === 'object') {\n const src = b.source as Record<string, unknown>\n if (src.type === 'base64' && typeof src.data === 'string' && typeof src.media_type === 'string') {\n blocks.push({ type: 'image', mediaType: src.media_type, data: src.data })\n continue\n }\n }\n // Unknown block → stringify into text for visibility.\n blocks.push({ type: 'text', text: JSON.stringify(raw) })\n }\n\n if (blocks.length === 0)\n return ''\n\n const hasNonText = blocks.some(b => b.type !== 'text')\n if (!hasNonText)\n return blocks.map(b => (b as { type: 'text', text: string }).text).join('\\n')\n\n return blocks\n}\n\n/**\n * Build an Anthropic `image.source` block, reconciling the declared media\n * type against the actual magic bytes.\n *\n * Anthropic's API rejects the entire request when `media_type` disagrees\n * with the payload (`messages.N.content.K.image.source.base64: The image\n * was specified using the X media type, but the image appears to be a\n * Y image`). The upstream sources of `{type:'image'}` blocks each sniff\n * before producing the block (read_file / MCP / TUI paste), but this\n * wire-boundary reconciliation is a final safety net for any future code\n * path or host-supplied prompt part that slips through without sniffing.\n *\n * The reconciler is conservative: it overrides only when the magic bytes\n * positively identify a *different* known format. Unknown / too-short\n * payloads pass `mediaType` through unchanged.\n */\nfunction anthropicImageSource(mediaType: string, data: string): { type: 'base64', media_type: string, data: string } {\n return { type: 'base64' as const, media_type: reconcileImageMediaType(mediaType, data), data }\n}\n\nfunction anthropicDocumentBlocks(doc: Pick<ToolResultDocumentContent, 'mediaType' | 'data' | 'encoding' | 'name'>): AnthropicWireBlock[] {\n if (doc.encoding === 'base64' && doc.mediaType === 'application/pdf') {\n return [{\n type: 'document',\n source: { type: 'base64', media_type: 'application/pdf', data: doc.data },\n ...(doc.name ? { title: doc.name } : {}),\n }]\n }\n\n const header = doc.name\n ? `<attachment name=\"${doc.name}\" media_type=\"${doc.mediaType}\" encoding=\"${doc.encoding}\">`\n : `<attachment media_type=\"${doc.mediaType}\" encoding=\"${doc.encoding}\">`\n return [{ type: 'text', text: `${header}\\n${doc.data}\\n</attachment>` }]\n}\n\nfunction documentMarker(doc: ToolResultDocumentContent): string {\n return documentBlockMarker(doc, 'document attached')\n}\n\nfunction isContentRefBlock(block: SessionContentBlock | ToolResultContent): block is (SessionContentBlock | ToolResultContent) & ContentRefBlock {\n return (block.type === 'image' || block.type === 'document')\n && typeof (block as { ref?: unknown }).ref === 'string'\n}\n\nfunction unresolvedContentRefError(block: ContentRefBlock): Error {\n return new Error(`Cannot project content ref \"${block.ref}\" to provider wire messages without resolveContentRef.`)\n}\n\n/**\n * Coerce a tool-call id to Anthropic's wire constraint `^[a-zA-Z0-9_-]+$`.\n *\n * Sessions started under another provider (OpenAI-compat / OpenRouter /\n * Cerebras) or carrying MCP-namespaced calls can hold ids with `.`, `:`,\n * `/` or other characters that 400 the request the moment the user switches\n * to an Anthropic model (`messages.N.content.M.tool_use.id: String should\n * match pattern '^[a-zA-Z0-9_-]+$'`).\n *\n * The mapping is deterministic — every disallowed char becomes `_` — so a\n * `tool_use` and its paired `tool_result` (sanitized identically below) keep\n * matching ids and the pairing survives. When sanitization actually changed\n * the id, a short hash of the ORIGINAL id is appended so distinct inputs\n * that would collapse to the same replacement (`call.1` vs `call_1` vs\n * `call:1`) stay distinct on the wire. Empty ids get a stable placeholder\n * so the block stays well-formed.\n */\nconst ANTHROPIC_TOOL_ID_INVALID = /[^\\w-]/g\nfunction sanitizeAnthropicToolId(id: string): string {\n if (!id)\n return 'tool_0'\n // `replace` with a global regex is idempotent for already-valid ids and\n // avoids the stateful `lastIndex` pitfall of reusing a `/g` regex `.test()`.\n const sanitized = id.replace(ANTHROPIC_TOOL_ID_INVALID, '_')\n if (sanitized === id)\n return id\n // Append a short hash of the ORIGINAL id so distinct inputs that collapse to\n // the same replacement stay distinct, deterministically, so a `tool_use` and\n // its paired `tool_result` keep matching ids.\n return `${sanitized}_${fnv1aBase36(id)}`\n}\n\n/**\n * Encode zidane's canonical `string | ToolResultContent[]` shape to Anthropic's\n * wire format for `tool_result.content`.\n */\nfunction encodeAnthropicToolResultContent(\n output: string | ToolResultContent[],\n): string | Array<{ type: 'text', text: string } | { type: 'image', source: { type: 'base64', media_type: string, data: string } }> {\n if (typeof output === 'string')\n return output\n return output.map((b) => {\n if (b.type === 'text')\n return { type: 'text' as const, text: b.text }\n if (b.type === 'document') {\n assertResolvedMediaBlock(b, 'Anthropic wire messages')\n return { type: 'text' as const, text: documentMarker(b) }\n }\n if (b.type === 'audio')\n return { type: 'text' as const, text: `[audio omitted: ${b.mediaType}]` }\n if (b.type === 'video')\n return { type: 'text' as const, text: `[video omitted: ${b.mediaType}]` }\n assertResolvedMediaBlock(b, 'Anthropic wire messages')\n return {\n type: 'image' as const,\n source: anthropicImageSource(b.mediaType, b.data),\n }\n })\n}\n\n// ---------------------------------------------------------------------------\n// fromAnthropic\n// ---------------------------------------------------------------------------\n\nexport function fromAnthropic(msg: { role: string, content: unknown }): SessionMessage {\n const role = msg.role as 'user' | 'assistant'\n const content: SessionContentBlock[] = []\n\n if (typeof msg.content === 'string') {\n content.push({ type: 'text', text: msg.content })\n return { role, content }\n }\n\n if (Array.isArray(msg.content)) {\n for (const block of msg.content) {\n if (!block || typeof block !== 'object')\n continue\n const b = block as Record<string, unknown>\n\n if (b.type === 'text') {\n content.push({ type: 'text', text: b.text as string })\n }\n else if (b.type === 'image') {\n const source = b.source as Record<string, unknown>\n if (source?.type === 'base64') {\n content.push({ type: 'image', mediaType: source.media_type as string, data: source.data as string })\n }\n }\n else if (b.type === 'document') {\n const source = b.source as Record<string, unknown>\n if (source?.type === 'base64' && typeof source.media_type === 'string' && typeof source.data === 'string') {\n content.push({\n type: 'document',\n mediaType: source.media_type,\n data: source.data,\n encoding: 'base64',\n ...(typeof b.title === 'string' ? { name: b.title } : {}),\n })\n }\n else if (source?.type === 'text' && typeof source.media_type === 'string' && typeof source.data === 'string') {\n content.push({\n type: 'document',\n mediaType: source.media_type,\n data: source.data,\n encoding: 'text',\n ...(typeof b.title === 'string' ? { name: b.title } : {}),\n })\n }\n }\n else if (b.type === 'tool_use') {\n content.push({ type: 'tool_call', id: b.id as string, name: b.name as string, input: b.input as Record<string, unknown> })\n }\n else if (b.type === 'tool_result') {\n const output = decodeAnthropicToolResultContent(b.content)\n const block: Extract<SessionContentBlock, { type: 'tool_result' }> = {\n type: 'tool_result',\n callId: b.tool_use_id as string,\n output,\n }\n if (b.is_error === true)\n block.isError = true\n content.push(block)\n }\n else if (b.type === 'thinking') {\n const block: Extract<SessionContentBlock, { type: 'thinking' }> = {\n type: 'thinking',\n text: (b.thinking as string | undefined) ?? '',\n }\n if (typeof b.signature === 'string') {\n block.signature = b.signature\n // Tag the producer so cross-provider senders can drop foreign signatures.\n block.signatureProducer = 'anthropic'\n }\n content.push(block)\n }\n else if (b.type === 'redacted_thinking') {\n // Encrypted reasoning that must be echoed back unmodified to keep\n // interleaved-thinking + tool-use chains working on Sonnet 3.7+/Opus 4.x.\n content.push({ type: 'redacted_thinking', data: (b.data as string | undefined) ?? '' })\n }\n else if (b.type === 'server_tool_use') {\n // Anthropic server-tool invocation (e.g. `web_search_20250305`). Captured\n // so multi-turn citation context survives — Anthropic's docs require\n // these blocks to be echoed back on follow-up turns.\n content.push({\n type: 'server_tool_use',\n producer: 'anthropic',\n id: (b.id as string | undefined) ?? '',\n name: (b.name as string | undefined) ?? '',\n input: (b.input as Record<string, unknown> | undefined) ?? {},\n })\n }\n else if (b.type === 'web_search_tool_result') {\n // Pairs with `server_tool_use`. `content` is opaque (search hit array\n // with `encrypted_content` / `encrypted_index`) — store unchanged.\n content.push({\n type: 'server_tool_result',\n producer: 'anthropic',\n toolUseId: (b.tool_use_id as string | undefined) ?? '',\n toolName: 'web_search',\n content: b.content,\n })\n }\n // Unknown block types are silently skipped\n }\n }\n\n return { role, content }\n}\n\n// ---------------------------------------------------------------------------\n// fromOpenAI\n// ---------------------------------------------------------------------------\n\nexport function fromOpenAI(msg: { role: string, content: unknown }): SessionMessage {\n const role = msg.role as 'user' | 'assistant'\n const content: SessionContentBlock[] = []\n const c: unknown = msg.content\n\n if (c == null) {\n return { role, content }\n }\n\n if (typeof c === 'string') {\n content.push({ type: 'text', text: c })\n return { role, content }\n }\n\n if (typeof c === 'object' && !Array.isArray(c) && (c as { _tag?: unknown })._tag === ASSISTANT_TOOL_CALLS_TAG) {\n const tagged = c as { text?: unknown, tool_calls?: unknown }\n if (typeof tagged.text === 'string' && tagged.text) {\n content.push({ type: 'text', text: tagged.text })\n }\n if (Array.isArray(tagged.tool_calls)) {\n for (const raw of tagged.tool_calls) {\n if (!raw || typeof raw !== 'object')\n continue\n const tc = raw as { id?: string, function?: { name?: string, arguments?: unknown } }\n const rawArgs = tc.function?.arguments\n // Malformed argument JSON (truncated stream, hand-edited history)\n // must not kill the whole conversion — fall back to `{}`, same\n // degradation `consumeSSE` applies to truncated tool-call args.\n let input: Record<string, unknown> = {}\n if (typeof rawArgs === 'string') {\n try {\n input = JSON.parse(rawArgs) as Record<string, unknown>\n }\n catch {\n input = {}\n }\n }\n else if (rawArgs && typeof rawArgs === 'object') {\n input = rawArgs as Record<string, unknown>\n }\n content.push({ type: 'tool_call', id: tc.id ?? '', name: tc.function?.name ?? '', input })\n }\n }\n return { role, content }\n }\n\n if (typeof c === 'object' && !Array.isArray(c) && (c as { _tag?: unknown })._tag === TOOL_RESULTS_TAG) {\n const tagged = c as { results?: unknown, text?: unknown }\n if (Array.isArray(tagged.results)) {\n for (const raw of tagged.results) {\n if (!raw || typeof raw !== 'object')\n continue\n const r = raw as { tool_call_id?: string, content?: string | ToolResultContent[] }\n content.push({ type: 'tool_result', callId: r.tool_call_id ?? '', output: r.content ?? '' })\n }\n }\n // Sibling text preserved by `toOpenAI` alongside the results.\n if (typeof tagged.text === 'string' && tagged.text)\n content.push({ type: 'text', text: tagged.text })\n return { role, content }\n }\n\n if (Array.isArray(c)) {\n for (const block of c) {\n if (!block || typeof block !== 'object')\n continue\n const b = block as Record<string, unknown>\n\n if (b.type === 'text') {\n content.push({ type: 'text', text: b.text as string })\n }\n else if (b.type === 'image_url') {\n const imageUrl = (b.image_url as Record<string, unknown>)?.url as string\n if (imageUrl?.startsWith('data:')) {\n const [meta, data] = imageUrl.slice(5).split(',', 2)\n const mediaType = meta.replace(';base64', '')\n content.push({ type: 'image', mediaType, data })\n }\n }\n }\n return { role, content }\n }\n\n return { role, content }\n}\n\n// ---------------------------------------------------------------------------\n// toAnthropic\n// ---------------------------------------------------------------------------\n\ntype AnthropicWireBlock\n = | { type: 'text', text: string }\n | { type: 'image', source: { type: 'base64', media_type: string, data: string } }\n | { type: 'document', source: { type: 'base64' | 'text', media_type: string, data: string }, title?: string }\n | { type: 'tool_use', id: string, name: string, input: Record<string, unknown> }\n | { type: 'tool_result', tool_use_id: string, content: ReturnType<typeof encodeAnthropicToolResultContent>, is_error?: true }\n | { type: 'thinking', thinking: string, signature: string }\n | { type: 'redacted_thinking', data: string }\n | { type: 'server_tool_use', id: string, name: string, input: Record<string, unknown> }\n | { type: 'web_search_tool_result', tool_use_id: string, content: unknown }\n\nexport function toAnthropic(msg: SessionMessage): { role: string, content: unknown } {\n const blocks: AnthropicWireBlock[] = msg.content\n // Drop foreign reasoning state. Three independent rejection paths,\n // each driven by an Anthropic API constraint we've hit in production:\n //\n // 1. `signatureProducer === 'openai'` — OpenAI's `encrypted_content`\n // isn't a valid Anthropic HMAC; sending it 400s with an unhelpful\n // \"invalid signature\" error.\n // 2. `type === 'thinking' && !signature` — Anthropic's\n // `ThinkingBlockParam` requires a signature field. A non-Anthropic\n // producer that doesn't sign thinking (Cerebras, Gemini, OSS via\n // OpenAI-compat, etc.) leaves a block in the session that 400s\n // here with `messages.N.content.M.thinking.signature: Field\n // required` the next time the user picks an Anthropic model. Drop\n // them — the model can re-think on its own turn, no info loss\n // beyond the prior provider's chain-of-thought, which Anthropic\n // can't consume anyway.\n // 3. `type === 'provider_reasoning'` — opaque provider-bound reasoning\n // state; not an Anthropic block type at all.\n .filter((b) => {\n if (b.type === 'provider_reasoning')\n return false\n if (b.type !== 'thinking')\n return true\n if (b.signatureProducer === 'openai')\n return false\n if (!b.signature)\n return false\n return true\n })\n .flatMap((block): AnthropicWireBlock[] => {\n switch (block.type) {\n case 'text':\n return [{ type: 'text', text: block.text }]\n case 'image':\n assertResolvedMediaBlock(block, 'Anthropic wire messages')\n return [{ type: 'image', source: anthropicImageSource(block.mediaType, block.data) }]\n case 'audio':\n // Anthropic has no audio input block. The prompt path throws before a\n // top-level audio block can reach here; this is the defensive marker\n // for any other code path (e.g. a cross-provider session replay).\n return [{ type: 'text', text: `[audio omitted: ${block.mediaType}]` }]\n case 'video':\n return [{ type: 'text', text: `[video omitted: ${block.mediaType}]` }]\n case 'document':\n assertResolvedMediaBlock(block, 'Anthropic wire messages')\n return anthropicDocumentBlocks(block)\n case 'tool_call':\n return [{ type: 'tool_use', id: sanitizeAnthropicToolId(block.id), name: block.name, input: block.input }]\n case 'tool_result': {\n const out: AnthropicWireBlock = {\n type: 'tool_result',\n tool_use_id: sanitizeAnthropicToolId(block.callId),\n content: encodeAnthropicToolResultContent(block.output),\n }\n if (block.isError)\n out.is_error = true\n const docs = typeof block.output === 'string'\n ? []\n : block.output.filter((part): part is ToolResultDocumentContent => part.type === 'document' && typeof part.data === 'string')\n return [out, ...docs.flatMap(anthropicDocumentBlocks)]\n }\n case 'thinking':\n // Filter above guarantees `signature` is present and either\n // anthropic-produced or legacy (back-compat for pre-tagging\n // Anthropic sessions where producer was never recorded).\n return [{ type: 'thinking', thinking: block.text, signature: block.signature ?? '' }]\n case 'redacted_thinking':\n return [{ type: 'redacted_thinking', data: block.data }]\n case 'server_tool_use':\n // Anthropic-produced server-tool invocation echoed back so the\n // model can resume the citation chain. Producer is always\n // `anthropic` (other providers don't emit this variant).\n return [{ type: 'server_tool_use', id: sanitizeAnthropicToolId(block.id), name: block.name, input: block.input }]\n case 'server_tool_result':\n return [{ type: 'web_search_tool_result', tool_use_id: sanitizeAnthropicToolId(block.toolUseId), content: block.content }]\n default:\n return [{ type: 'text', text: '' }]\n }\n })\n\n // Simplify to plain string if only one text block\n const first = blocks[0]\n if (blocks.length === 1 && first.type === 'text')\n return { role: msg.role, content: first.text }\n\n return { role: msg.role, content: blocks }\n}\n\n// ---------------------------------------------------------------------------\n// toOpenAI\n// ---------------------------------------------------------------------------\n\nexport function toOpenAI(msg: SessionMessage): { role: string, content: unknown } {\n const toolCalls = msg.content.filter(b => b.type === 'tool_call')\n const toolResults = msg.content.filter(b => b.type === 'tool_result')\n const textBlocks = msg.content.filter(b => b.type === 'text')\n const imageBlocks = msg.content.filter(b => b.type === 'image')\n const audioBlocks = msg.content.filter(b => b.type === 'audio')\n const videoBlocks = msg.content.filter(b => b.type === 'video')\n const documentBlocks = msg.content.filter(b => b.type === 'document')\n\n // Tool results → tagged format. Sibling text blocks (a user follow-up\n // typed while tools ran) ride along on `text` — the early return here\n // used to silently drop them, breaking round-trip fidelity vs. the wire\n // shaper (`toOAIMessages`), which preserves them.\n if (toolResults.length > 0) {\n const siblingText = textBlocks.map(b => b.text).join('\\n')\n return {\n role: msg.role,\n content: {\n _tag: TOOL_RESULTS_TAG,\n results: toolResults.map(tr => ({ tool_call_id: tr.callId, content: tr.output })),\n ...(siblingText ? { text: siblingText } : {}),\n },\n }\n }\n\n // Tool calls → tagged format\n if (toolCalls.length > 0) {\n const textContent = textBlocks.length > 0 ? textBlocks[0].text : null\n return {\n role: msg.role,\n content: {\n _tag: ASSISTANT_TOOL_CALLS_TAG,\n text: textContent,\n tool_calls: toolCalls.map(tc => ({\n id: tc.id,\n type: 'function',\n function: { name: tc.name, arguments: JSON.stringify(tc.input) },\n })),\n },\n }\n }\n\n // Images/audio/video/documents → multimodal array. Documents have no portable\n // OpenAI Chat Completions block here, so preserve them as markers.\n if (imageBlocks.length > 0 || audioBlocks.length > 0 || videoBlocks.length > 0 || documentBlocks.length > 0) {\n const parts: unknown[] = []\n for (const img of imageBlocks) {\n assertResolvedMediaBlock(img, 'OpenAI-compatible wire messages')\n parts.push({\n type: 'image_url',\n image_url: { url: `data:${img.mediaType};base64,${img.data}` },\n })\n }\n for (const b of audioBlocks)\n parts.push({ type: 'input_audio', input_audio: { data: b.data, format: audioFormatFromMediaType(b.mediaType) } })\n for (const b of videoBlocks)\n parts.push({ type: 'video_url', video_url: { url: `data:${b.mediaType};base64,${b.data}` } })\n for (const b of documentBlocks) {\n assertResolvedMediaBlock(b, 'OpenAI-compatible wire messages')\n parts.push({ type: 'text', text: documentMarker(b) })\n }\n for (const b of textBlocks)\n parts.push({ type: 'text', text: b.text })\n return { role: msg.role, content: parts }\n }\n\n // Pure text → string\n if (textBlocks.length === 1)\n return { role: msg.role, content: textBlocks[0].text }\n\n // Multiple text blocks or empty\n if (textBlocks.length > 1)\n return { role: msg.role, content: textBlocks.map(b => ({ type: 'text', text: b.text })) }\n\n return { role: msg.role, content: null }\n}\n\n// ---------------------------------------------------------------------------\n// autoDetectAndConvert\n// ---------------------------------------------------------------------------\n\n// ---------------------------------------------------------------------------\n// ensureToolResultPairing\n// ---------------------------------------------------------------------------\n\n/**\n * Placeholder content inserted into a synthetic `tool_result` when the harness\n * has to repair an orphan `tool_use`. Exported so downstream consumers\n * (training-data collectors, HFI submission) can reject any payload containing\n * it — the marker satisfies the wire-level pairing contract structurally but\n * the content itself is fake and would poison fine-tuning data.\n */\nexport const SYNTHETIC_TOOL_RESULT_PLACEHOLDER = '[Tool result missing due to internal error]'\n\n/**\n * Replacement text for an assistant message whose every content block was\n * stripped during pairing repair (e.g. the only blocks were orphan\n * `tool_call`s). Providers reject empty `content` arrays — the marker keeps\n * the turn shape valid while signaling \"this assistant turn lost its\n * outputs\" to the model so it can recover.\n */\nexport const TOOL_USE_INTERRUPTED_MARKER = '[Tool use interrupted]'\n\n/**\n * Replacement text for a user message whose every content block was a\n * `tool_result` with no matching upstream `tool_call` (e.g. the assistant\n * pair was stripped by an earlier compaction). Same role as\n * {@link TOOL_USE_INTERRUPTED_MARKER} on the user side.\n */\nexport const ORPHANED_TOOL_RESULT_MARKER = '[Orphaned tool result removed due to conversation resume]'\n\n/**\n * Classification of a single repair the pairing pass performed. Surfaced via\n * {@link EnsureToolResultPairingOptions.onRepair} so consumers can wire\n * telemetry, debug logs, or strict-mode rejection without re-implementing the\n * walk.\n *\n * Each entry corresponds to one of the corruption modes documented on\n * {@link ensureToolResultPairing}.\n */\nexport type PairingRepairMode\n = | 'orphan-tool-use-prepend' // mode 1: tool_use with no matching tool_result; next msg is user → prepend synthetic\n | 'orphan-tool-use-append' // mode 2: tool_use is followed by nothing (or a non-user msg) → append synthetic user turn\n | 'orphan-tool-result-strip' // mode 3: tool_result with no preceding tool_call → strip block\n | 'duplicate-tool-use-strip' // mode 4: duplicate tool_use id across assistant msgs → strip later instance\n | 'duplicate-tool-result-strip' // mode 5: duplicate tool_result callId in one user msg → strip later instance\n | 'empty-assistant-marker' // mode 6: assistant msg emptied by mode-4 stripping → replace with marker text\n | 'duplicate-tool-use-remint' // persist-time: fresh turn reused an existing tool_call id → re-minted before persist (loop-side, not part of ensureToolResultPairing)\n\nexport interface PairingRepair {\n mode: PairingRepairMode\n /** Tool-use / tool-result id this repair concerns. Absent for empty-marker repairs. */\n callId?: string\n /** Zero-based index into the INPUT `messages` array where the corruption was found. */\n messageIndex: number\n}\n\nexport interface EnsureToolResultPairingOptions {\n /**\n * Fired once per repair the pass performed. Synchronous so the loop can\n * stay on its hot path. Throwing from the callback aborts the pass —\n * consumers wanting fail-fast (strict mode) can re-throw with their own\n * typed error.\n */\n onRepair?: (repair: PairingRepair) => void\n}\n\n/**\n * Defensive repair pass that rewrites a message list so it satisfies the\n * wire-level `tool_use` ↔ `tool_result` adjacency contract every modern\n * provider enforces.\n *\n * Anthropic 400s on orphans with `'tool_use' ids were found without\n * 'tool_result' blocks immediately after` (and its inverse, `tool_result\n * must be preceded by a tool_call with the same toolCallId`). OpenAI's\n * Chat Completions API rejects most mismatches with a 400 too.\n *\n * Six repair modes — modeled after Anthropic's Claude Code defenses:\n *\n * | # | Corruption | Repair |\n * |---|------------|--------|\n * | 1 | assistant `tool_use` whose next user msg lacks a matching `tool_result` | **Prepend** a synthetic `tool_result` block carrying {@link SYNTHETIC_TOOL_RESULT_PLACEHOLDER} with `isError: true` |\n * | 2 | assistant `tool_use` followed by nothing (or by a non-user msg) | **Insert** a new synthetic user message with the same placeholder |\n * | 3 | user `tool_result` with no preceding assistant `tool_call` | **Strip** the orphan block; if it empties the msg, replace with {@link ORPHANED_TOOL_RESULT_MARKER} text block |\n * | 4 | duplicate `tool_call.id` across assistant messages (CC-1212) | **Strip** later instances + their matching tool_results |\n * | 5 | duplicate `tool_result.callId` within a single user message | **Dedupe** by `callId`, keep first |\n * | 6 | assistant message emptied by mode-4 stripping | **Replace** content with {@link TOOL_USE_INTERRUPTED_MARKER} text block |\n *\n * **Repair, not drop.** Earlier versions of this pass simply dropped orphan\n * blocks, which (a) silently rewrote history the model had reasoned over and\n * (b) cascaded — dropping an assistant tool_call would orphan its\n * tool_result, which would then get dropped too, removing any trace of\n * \"what the model tried to do\" from the transcript. The repair-based pass\n * preserves the model's tool_use shape and patches the dangling result with\n * an `is_error` placeholder so the model sees \"I tried X, the result was\n * lost\" and can retry intelligently.\n *\n * Adjacency contract: `tool_result` blocks must live in the user message\n * IMMEDIATELY following the assistant message that emitted the matching\n * `tool_use`. The pass enforces strict adjacency — a tool_result two\n * messages downstream of its tool_call is still an orphan.\n *\n * Idempotent: returns the input reference unchanged when no repairs were\n * necessary. Re-running on already-repaired output is a no-op.\n *\n * Pure: does not mutate input messages or their content arrays — every\n * repair allocates a fresh array / object.\n */\nexport function ensureToolResultPairing(\n messages: SessionMessage[],\n options: EnsureToolResultPairingOptions = {},\n): SessionMessage[] {\n if (messages.length === 0)\n return messages\n\n const fireRepair = options.onRepair ?? (() => {})\n\n // Pre-pass: first-occurrence index of every assistant `tool_call.id`.\n // Mode 4 strips any block whose first occurrence wasn't in the current\n // message — the first instance wins so the original semantics stand.\n const firstSeenAt = new Map<string, number>()\n for (let i = 0; i < messages.length; i++) {\n const msg = messages[i]\n if (msg.role !== 'assistant')\n continue\n for (const block of msg.content) {\n if (block.type === 'tool_call' && !firstSeenAt.has(block.id))\n firstSeenAt.set(block.id, i)\n }\n }\n\n // Scoped to this call. Keyed by INPUT index of the user message that\n // should receive prepended synthetic results from the prior assistant\n // turn's mode-1 repair. Drained as the outer loop reaches each user msg.\n const pendingOrphansByUserIndex = new Map<number, string[]>()\n\n let changed = false\n const markChanged = () => { changed = true }\n const out: SessionMessage[] = []\n\n for (let i = 0; i < messages.length; i++) {\n const msg = messages[i]\n\n if (msg.role === 'assistant') {\n processAssistantMessage({\n index: i,\n msg,\n messages,\n firstSeenAt,\n pendingOrphansByUserIndex,\n out,\n fireRepair,\n markChanged,\n })\n }\n else {\n processUserMessage({\n index: i,\n msg,\n pendingOrphansByUserIndex,\n out,\n fireRepair,\n markChanged,\n })\n }\n }\n\n return changed ? out : messages\n}\n\ninterface ProcessAssistantArgs {\n index: number\n msg: SessionMessage\n messages: SessionMessage[]\n firstSeenAt: Map<string, number>\n pendingOrphansByUserIndex: Map<number, string[]>\n out: SessionMessage[]\n fireRepair: (repair: PairingRepair) => void\n markChanged: () => void\n}\n\n/**\n * Process one assistant message: strip mode-4 duplicates, queue mode-1 / 2\n * orphan-tool-use repairs for the next user message (or insert a synthetic\n * one), and emit a mode-6 marker when dedup empties the message.\n */\nfunction processAssistantMessage(args: ProcessAssistantArgs): void {\n const { index, msg, messages, firstSeenAt, pendingOrphansByUserIndex, out, fireRepair, markChanged } = args\n\n // Mode 4: drop tool_call blocks that are duplicates either:\n // - across messages (first occurrence was in an earlier assistant msg), or\n // - within this same message (same id appearing twice in one turn —\n // pathological but observed in the wild with retry-replay providers).\n //\n // The per-message `seenHere` set guards against the intra-message case:\n // `firstSeenAt` records only the first OCCURRENCE per id, so two blocks\n // sharing an id within the same message both pass the cross-message\n // check (`firstSeenAt.get(id) === index`). The local set tracks which\n // ids we've already kept this iteration and strips later repeats.\n const dedupedContent: SessionContentBlock[] = []\n const seenHere = new Set<string>()\n let dedupedChanged = false\n for (const block of msg.content) {\n if (block.type === 'tool_call') {\n const isCrossMsgDup = firstSeenAt.get(block.id) !== index\n const isIntraMsgDup = seenHere.has(block.id)\n if (isCrossMsgDup || isIntraMsgDup) {\n dedupedChanged = true\n fireRepair({ mode: 'duplicate-tool-use-strip', callId: block.id, messageIndex: index })\n continue\n }\n seenHere.add(block.id)\n }\n dedupedContent.push(block)\n }\n\n const surviving = collectIds<ToolCallBlock>(dedupedContent, 'tool_call', b => b.id)\n const next = messages[index + 1]\n const nextIsUser = next && next.role === 'user'\n const nextResultIds = nextIsUser ? collectResultIds(next.content) : new Set<string>()\n const orphans: string[] = []\n for (const id of surviving) {\n if (!nextResultIds.has(id))\n orphans.push(id)\n }\n\n // Emit the (possibly deduped) assistant message — modes 1 / 2 patch the\n // matching user side rather than touching tool_use blocks.\n emitAssistantAfterDedup({ index, msg, dedupedContent, dedupedChanged, out, fireRepair, markChanged })\n\n if (orphans.length === 0)\n return\n\n // Mode 1: stash for the next user msg processor to prepend.\n if (nextIsUser) {\n markChanged()\n pendingOrphansByUserIndex.set(index + 1, orphans)\n for (const callId of orphans)\n fireRepair({ mode: 'orphan-tool-use-prepend', callId, messageIndex: index })\n return\n }\n\n // Mode 2: synthesize a user message with placeholders for every orphan.\n markChanged()\n out.push({\n role: 'user',\n content: orphans.map(callId => syntheticResultBlock(callId)),\n })\n for (const callId of orphans)\n fireRepair({ mode: 'orphan-tool-use-append', callId, messageIndex: index })\n}\n\ninterface EmitAssistantArgs {\n index: number\n msg: SessionMessage\n dedupedContent: SessionContentBlock[]\n dedupedChanged: boolean\n out: SessionMessage[]\n fireRepair: (repair: PairingRepair) => void\n markChanged: () => void\n}\n\nfunction emitAssistantAfterDedup(args: EmitAssistantArgs): void {\n const { index, msg, dedupedContent, dedupedChanged, out, fireRepair, markChanged } = args\n if (!dedupedChanged) {\n out.push(msg)\n return\n }\n markChanged()\n if (dedupedContent.length === 0) {\n out.push({ ...msg, content: [{ type: 'text', text: TOOL_USE_INTERRUPTED_MARKER }] })\n fireRepair({ mode: 'empty-assistant-marker', messageIndex: index })\n return\n }\n out.push({ ...msg, content: dedupedContent })\n}\n\ninterface ProcessUserArgs {\n index: number\n msg: SessionMessage\n pendingOrphansByUserIndex: Map<number, string[]>\n out: SessionMessage[]\n fireRepair: (repair: PairingRepair) => void\n markChanged: () => void\n}\n\n/**\n * Process one user message: dedup mode-5 duplicate tool_results, strip\n * mode-3 orphans whose tool_call is missing from the previously-emitted\n * assistant message, and prepend any synthetic results queued by the prior\n * assistant's mode-1 repair.\n */\nfunction processUserMessage(args: ProcessUserArgs): void {\n const { index, msg, pendingOrphansByUserIndex, out, fireRepair, markChanged } = args\n const queuedOrphans = pendingOrphansByUserIndex.get(index)\n pendingOrphansByUserIndex.delete(index)\n\n const prev = out.length > 0 ? out[out.length - 1] : null\n const validIds = prev && prev.role === 'assistant'\n ? collectIds<ToolCallBlock>(prev.content, 'tool_call', b => b.id)\n : new Set<string>()\n\n // Pass 1 — mode 5: dedupe by callId within this msg.\n const seenCallIds = new Set<string>()\n let modifiedHere = false\n const afterDedup: SessionContentBlock[] = []\n for (const block of msg.content) {\n if (block.type !== 'tool_result') {\n afterDedup.push(block)\n continue\n }\n if (seenCallIds.has(block.callId)) {\n modifiedHere = true\n fireRepair({ mode: 'duplicate-tool-result-strip', callId: block.callId, messageIndex: index })\n continue\n }\n seenCallIds.add(block.callId)\n afterDedup.push(block)\n }\n\n // Pass 2 — mode 3: strip orphan tool_results.\n const afterStrip: SessionContentBlock[] = []\n for (const block of afterDedup) {\n if (block.type === 'tool_result' && !validIds.has(block.callId)) {\n modifiedHere = true\n fireRepair({ mode: 'orphan-tool-result-strip', callId: block.callId, messageIndex: index })\n continue\n }\n afterStrip.push(block)\n }\n\n // Pass 3: prepend queued mode-1 synthetic results.\n const finalContent: SessionContentBlock[] = queuedOrphans\n ? [...queuedOrphans.map(syntheticResultBlock), ...afterStrip]\n : afterStrip\n\n if (!modifiedHere && queuedOrphans === undefined) {\n out.push(msg)\n return\n }\n\n markChanged()\n if (finalContent.length === 0) {\n out.push({ ...msg, content: [{ type: 'text', text: ORPHANED_TOOL_RESULT_MARKER }] })\n return\n }\n out.push({ ...msg, content: finalContent })\n}\n\n// ---------------------------------------------------------------------------\n// remintDuplicateToolCallIds — persist-time duplicate-id healing\n// ---------------------------------------------------------------------------\n\nexport interface RemintResult {\n /** Tool calls with duplicate ids replaced. Same reference when unchanged. */\n toolCalls: Array<{ id: string, name: string, input: Record<string, unknown> }>\n /** Assistant content with matching `tool_call` block ids rewritten. Same reference when unchanged. */\n content: SessionContentBlock[]\n /** One entry per re-minted occurrence, in emission order. */\n reminted: Array<{ oldId: string, newId: string }>\n}\n\n/**\n * Re-mint tool-call ids that collide with ids already present in the\n * transcript (or with an earlier sibling in the same turn), BEFORE the turn\n * is persisted and its tools dispatched.\n *\n * Why this exists: some providers/serving stacks emit non-globally-unique\n * tool_use ids (per-turn counters like `call_0`, retry-replay duplicates,\n * Kimi-K2.6 on Fireworks). The wire-time pairing pass\n * ({@link ensureToolResultPairing}) can only STRIP such duplicates — which\n * erases the model's tool calls and results from the wire view, stalls\n * progress, and re-accumulates repairs quadratically because the persisted\n * session keeps the corrupted ids. Re-minting at persist time keeps the\n * pairing intact instead: the call, its execution, and its tool_result all\n * carry the fresh id, so the pairing pass has nothing to strip on any later\n * turn.\n *\n * Fresh ids are `${oldId}_r{n}` with `n` bumped until unique — deterministic\n * shape, Anthropic-wire-safe charset (given a safe input id), and visibly\n * traceable back to the original.\n *\n * Alignment contract: `toolCalls` and the `tool_call` blocks inside\n * `content` are two views of the same emission and MUST be in the same\n * order (true for every provider — both are built from one source array).\n * Occurrences are matched positionally per old id so intra-turn duplicates\n * map to distinct fresh ids on both views.\n *\n * Pure: returns the input references unchanged when no id collides.\n */\nexport function remintDuplicateToolCallIds(\n toolCalls: ReadonlyArray<{ id: string, name: string, input: Record<string, unknown> }>,\n content: readonly SessionContentBlock[],\n priorIds: ReadonlySet<string>,\n): RemintResult {\n const seen = new Set(priorIds)\n const reminted: Array<{ oldId: string, newId: string }> = []\n // Final id per occurrence, queued per old id so the content walk below\n // can re-associate positionally (handles intra-turn duplicates).\n const finalIdQueues = new Map<string, string[]>()\n\n let changed = false\n const outCalls = toolCalls.map((tc) => {\n let finalId = tc.id\n if (seen.has(tc.id)) {\n let n = 1\n while (seen.has(`${tc.id}_r${n}`))\n n++\n finalId = `${tc.id}_r${n}`\n reminted.push({ oldId: tc.id, newId: finalId })\n changed = true\n }\n seen.add(finalId)\n const queue = finalIdQueues.get(tc.id)\n if (queue)\n queue.push(finalId)\n else\n finalIdQueues.set(tc.id, [finalId])\n return finalId === tc.id ? tc : { ...tc, id: finalId }\n })\n\n if (!changed) {\n return {\n toolCalls: toolCalls as RemintResult['toolCalls'],\n content: content as SessionContentBlock[],\n reminted,\n }\n }\n\n const outContent = content.map((block) => {\n if (block.type !== 'tool_call')\n return block\n const queue = finalIdQueues.get(block.id)\n const finalId = queue?.shift()\n if (finalId === undefined || finalId === block.id)\n return block\n return { ...block, id: finalId }\n })\n\n return { toolCalls: outCalls as RemintResult['toolCalls'], content: outContent, reminted }\n}\n\nfunction syntheticResultBlock(callId: string): SessionContentBlock {\n return {\n type: 'tool_result',\n callId,\n output: SYNTHETIC_TOOL_RESULT_PLACEHOLDER,\n isError: true,\n }\n}\n\nfunction collectResultIds(content: SessionContentBlock[]): Set<string> {\n const ids = new Set<string>()\n for (const block of content) {\n if (block.type === 'tool_result')\n ids.add(block.callId)\n }\n return ids\n}\n\nfunction collectIds<B extends SessionContentBlock>(\n content: SessionContentBlock[],\n type: B['type'],\n getId: (block: B) => string,\n): Set<string> {\n const ids = new Set<string>()\n for (const block of content) {\n if (block.type === type)\n ids.add(getId(block as B))\n }\n return ids\n}\n\n// ---------------------------------------------------------------------------\n// Resume-time filters (L1)\n// ---------------------------------------------------------------------------\n\n/**\n * Drop ASSISTANT turns whose every `tool_call` block is unresolved\n * (no matching `tool_result` block anywhere later in the transcript).\n * Tool_call blocks with at least one matching tool_result are kept — modes\n * 1/3 of {@link ensureToolResultPairing} handle the partial-pair case at\n * wire-send time.\n *\n * Use case: session resume. A turn that emitted three `tool_use` blocks but\n * never persisted the matching `tool_result` turn (process death, crash,\n * `kill -9`) leaves the transcript with an orphan that Anthropic rejects on\n * the FIRST API call after reload. Dropping the whole assistant turn — not\n * just the orphan blocks — preserves text-only turns that legitimately\n * carry reasoning the model wants to see again.\n *\n * Does NOT mint fresh ids: re-id'ing on every resume would cause\n * exponential transcript growth across repeated resumes of an interrupted\n * session.\n *\n * Pure: returns the input reference unchanged when no turn was dropped.\n */\nexport function filterUnresolvedToolUses<T extends { role: string, content: SessionContentBlock[] }>(\n turns: T[],\n): T[] {\n if (turns.length === 0)\n return turns\n\n // Gather every resolved tool_result id (visible anywhere later in the\n // transcript). A tool_use is \"resolved\" iff its id appears in this set.\n const resolvedIds = new Set<string>()\n for (const turn of turns) {\n for (const block of turn.content) {\n if (block.type === 'tool_result')\n resolvedIds.add(block.callId)\n }\n }\n\n let changed = false\n const out: T[] = []\n for (const turn of turns) {\n if (turn.role !== 'assistant') {\n out.push(turn)\n continue\n }\n const toolCalls = turn.content.filter(b => b.type === 'tool_call')\n if (toolCalls.length === 0) {\n out.push(turn)\n continue\n }\n const allUnresolved = toolCalls.every(b => b.type === 'tool_call' && !resolvedIds.has(b.id))\n if (allUnresolved) {\n changed = true\n continue\n }\n out.push(turn)\n }\n return changed ? out : turns\n}\n\n/**\n * Classification of a session's tail state for resume purposes.\n *\n * - `'clean'` — the trailing turn is a user message (the model would respond\n * next), or the transcript is empty. Safe to resume by appending a fresh\n * user prompt.\n * - `'interrupted'` — the trailing turn is an assistant message that has at\n * least one `tool_call` block with no matching `tool_result` anywhere\n * later. The run was almost certainly killed between persisting the\n * assistant turn and persisting its tool-results turn. Hosts that want\n * Claude-Code-style auto-resume can detect this and inject a\n * `\"Continue from where you left off.\"` user message before the next run.\n * - `'completed'` — the trailing turn is an assistant message with no\n * orphan tool_calls. The model considers itself done. Hosts that want to\n * resume must supply a new prompt; auto-continuation here would be a\n * non-sequitur.\n */\nexport type TurnInterruptionState = 'clean' | 'interrupted' | 'completed'\n\n/**\n * Inspect a session's trailing turn to classify whether the run was\n * interrupted mid-tool-call. Pure / synchronous — does not modify the input.\n *\n * Pair with {@link filterUnresolvedToolUses} on the resume path: filter\n * first so the result reflects the post-cleanup state (a turn whose orphans\n * were stripped reads as 'completed', not 'interrupted').\n */\nexport function detectTurnInterruption<T extends { role: string, content: SessionContentBlock[] }>(\n turns: T[],\n): TurnInterruptionState {\n if (turns.length === 0)\n return 'clean'\n const last = turns[turns.length - 1]\n if (last.role === 'user')\n return 'clean'\n if (last.role !== 'assistant')\n return 'clean'\n // Walk all turns to find resolved tool_result ids — a tool_use anywhere\n // earlier in the run may still be answered by a later tool_result.\n const resolvedIds = new Set<string>()\n for (const turn of turns) {\n for (const block of turn.content) {\n if (block.type === 'tool_result')\n resolvedIds.add(block.callId)\n }\n }\n for (const block of last.content) {\n if (block.type === 'tool_call' && !resolvedIds.has(block.id))\n return 'interrupted'\n }\n return 'completed'\n}\n\n/**\n * Default directive injected by {@link ensureEndsWithUserMessage} when the\n * caller doesn't pass one. Neutral enough to read sensibly in any context —\n * compaction passes its own directive, the agent loop falls back to this.\n *\n * The trailing newline is omitted on purpose; provider `userMessage()`\n * helpers wrap the content in the right block shape and any trailing\n * whitespace would land in the wire payload as-is.\n */\nexport const DEFAULT_USER_TAIL_DIRECTIVE = 'Continue.'\n\n/**\n * Guarantee a message list ends with a `role: 'user'` message, appending a\n * synthetic directive when it doesn't.\n *\n * Why: Anthropic's API (and several OpenAI-compat reasoning models — opus\n * 4.7, the o-series translation layers on Bedrock/Vertex) rejects requests\n * whose final message is `role: 'assistant'` with\n * \"This model does not support assistant message prefill. The conversation\n * must end with a user message.\"\n *\n * Triggers in zidane:\n * - Compaction over a session whose last turn is the agent's response\n * (the common case — autocompact fires right after `agent.run()`).\n * - Schema enforcement after an assistant text turn (no `tool_use`, so\n * `ensureToolResultPairing` doesn't synthesize a user tail).\n * - `context:transform` hooks that strip the trailing user turn.\n *\n * The pair-repair pass {@link ensureToolResultPairing} already covers the\n * orphan-`tool_use` case via mode 2; this helper closes the plain-text\n * assistant-tail case. They compose: run pair-repair first, then this\n * pass, so an assistant turn with orphan tool_uses gets its synthetic\n * `tool_result` user turn AND this pass is a no-op (the synthetic turn\n * is already user-role).\n *\n * Empty input passes through unchanged — the caller's \"nothing to send\"\n * guard is responsible for that case; we don't materialize a conversation\n * out of an empty list.\n *\n * Idempotent: returns the input reference unchanged when the list is\n * already user-terminated (or empty).\n *\n * @param messages Wire-ready message list.\n * @param provider Provider whose `userMessage()` shape we use so the\n * synthetic turn matches the wire format the rest of\n * the list already follows.\n * @param directive Text to put in the synthetic user message. Defaults\n * to {@link DEFAULT_USER_TAIL_DIRECTIVE} (\"Continue.\").\n * Compaction overrides this with a summary-specific cue.\n */\nexport function ensureEndsWithUserMessage(\n messages: SessionMessage[],\n provider: Provider,\n directive: string = DEFAULT_USER_TAIL_DIRECTIVE,\n): SessionMessage[] {\n if (messages.length === 0)\n return messages\n if (messages[messages.length - 1].role === 'user')\n return messages\n return [...messages, provider.userMessage(directive)]\n}\n\n// ---------------------------------------------------------------------------\n// toWireMessages — canonical \"give me provider-ready messages\" projection\n// ---------------------------------------------------------------------------\n\nexport interface ToWireMessagesOptions {\n /**\n * Pairing-repair telemetry. Fires once per repair the underlying\n * {@link ensureToolResultPairing} pass performs. Mirrors the\n * `pairing:repair` hook surface so consumers can wire structured logging\n * without an agent instance.\n */\n onRepair?: (repair: PairingRepair) => void\n /**\n * When set, also runs {@link ensureEndsWithUserMessage} so the result is\n * safe for assistant-prefill-rejecting models (opus 4.7, o-series\n * translation layers). Omit to skip — pure pairing repair only.\n */\n provider?: Provider\n /**\n * Override for the synthetic user-tail directive. Only consulted when\n * `provider` is set. Defaults to {@link DEFAULT_USER_TAIL_DIRECTIVE}.\n */\n userTailDirective?: string\n /**\n * Resolve persisted content references into provider-native payload bytes.\n * The returned data is wire-only and must not be written back to turns.\n */\n resolveContentRef?: ResolveContentRef\n}\n\nasync function resolveRefContentBlock(\n block: SessionContentBlock,\n resolveContentRef: ResolveContentRef | undefined,\n): Promise<{ block: SessionContentBlock, changed: boolean }> {\n if (isContentRefBlock(block)) {\n if (!resolveContentRef)\n throw unresolvedContentRefError(block)\n const { data } = await resolveContentRef({\n type: block.type,\n ref: block.ref,\n mediaType: block.mediaType,\n ...(block.type === 'document' ? { encoding: block.encoding } : {}),\n ...(block.name ? { name: block.name } : {}),\n })\n if (block.type === 'image') {\n return {\n block: { type: 'image', mediaType: block.mediaType, data, ...(block.name ? { name: block.name } : {}) },\n changed: true,\n }\n }\n return {\n block: { type: 'document', mediaType: block.mediaType, encoding: block.encoding, data, ...(block.name ? { name: block.name } : {}) },\n changed: true,\n }\n }\n\n if (block.type !== 'tool_result' || typeof block.output === 'string')\n return { block, changed: false }\n\n const resolved = await resolveToolResultContent(block.output, resolveContentRef)\n if (!resolved.changed)\n return { block, changed: false }\n return { block: { ...block, output: resolved.output }, changed: true }\n}\n\nasync function resolveToolResultContent(\n output: ToolResultContent[],\n resolveContentRef: ResolveContentRef | undefined,\n): Promise<{ output: ToolResultContent[], changed: boolean }> {\n let changed = false\n const next: ToolResultContent[] = []\n for (const part of output) {\n if (!isContentRefBlock(part)) {\n next.push(part)\n continue\n }\n if (!resolveContentRef)\n throw unresolvedContentRefError(part)\n const { data } = await resolveContentRef({\n type: part.type,\n ref: part.ref,\n mediaType: part.mediaType,\n ...(part.type === 'document' ? { encoding: part.encoding } : {}),\n ...(part.name ? { name: part.name } : {}),\n })\n changed = true\n if (part.type === 'image') {\n next.push({ type: 'image', mediaType: part.mediaType, data, ...(part.name ? { name: part.name } : {}) })\n }\n else {\n next.push({ type: 'document', mediaType: part.mediaType, encoding: part.encoding, data, ...(part.name ? { name: part.name } : {}) })\n }\n }\n return { output: changed ? next : output, changed }\n}\n\n/**\n * Resolve image/document ref blocks into data blocks for provider wire use.\n * This is intentionally wire-only: callers must never persist the returned\n * messages back into `session.turns`.\n *\n * Returns the input array reference unchanged when no block carried a ref —\n * the common case (most turns hold no refs, and re-running on already-resolved\n * output is a no-op), so the multi-pass wire pipeline doesn't pay per-message\n * copies for nothing.\n */\nexport async function resolveContentRefsInMessages(\n messages: readonly SessionMessage[],\n options: { resolveContentRef?: ResolveContentRef } = {},\n): Promise<SessionMessage[]> {\n let anyChanged = false\n const out: SessionMessage[] = []\n for (const msg of messages) {\n let changed = false\n const content: SessionContentBlock[] = []\n for (const block of msg.content) {\n const resolved = await resolveRefContentBlock(block, options.resolveContentRef)\n if (resolved.changed)\n changed = true\n content.push(resolved.block)\n }\n if (changed)\n anyChanged = true\n out.push(changed ? { ...msg, content } : msg)\n }\n return anyChanged ? out : (messages as SessionMessage[])\n}\n\nfunction finalizeWireMessages(messages: SessionMessage[], options: ToWireMessagesOptions): SessionMessage[] {\n const paired = ensureToolResultPairing(messages, options.onRepair ? { onRepair: options.onRepair } : {})\n if (!options.provider)\n return paired\n return ensureEndsWithUserMessage(paired, options.provider, options.userTailDirective)\n}\n\n/**\n * Build a wire-ready `SessionMessage[]` from raw persisted `SessionTurn[]`.\n *\n * **The canonical \"I want to send these to a provider\" projection.** Use\n * this — not raw `session.turns` / `store.getTurns()` — when constructing a\n * provider request outside `agent.run()`. The agent's own wire pipeline\n * (`executeTurn` in `src/loop.ts`) applies the same repair just-in-time;\n * downstream consumers that bypass the loop hit `tool_result must be\n * preceded by a tool_call` 400s precisely because they shipped raw turns.\n *\n * Pipeline:\n * 1. Filter `system`-role turns (the wire only carries user/assistant).\n * 2. {@link ensureToolResultPairing} — repairs all six orphan / dup\n * corruption modes by inserting synthetic placeholders rather than\n * dropping (preserves the model's tool_use shape).\n * 3. {@link ensureEndsWithUserMessage} when `options.provider` is set —\n * guards against assistant-tail prefill rejection (opus 4.7, o-series).\n *\n * Pure + idempotent. Does not mutate the input turns. Re-running on the\n * output is a no-op.\n *\n * **Do not feed the result back into `session.setTurns` / `appendTurns`.**\n * The repair can insert `SYNTHETIC_TOOL_RESULT_PLACEHOLDER` / `[Orphaned\n * tool result removed …]` markers; round-tripping those into persisted\n * state contaminates the session's reasoning history and defeats the\n * \"don't rewrite the past\" invariant the wire-only repair was designed\n * around.\n */\nexport async function toWireMessages(\n turns: readonly { role: 'user' | 'assistant' | 'system', content: SessionContentBlock[] }[],\n options: ToWireMessagesOptions = {},\n): Promise<SessionMessage[]> {\n const messages: SessionMessage[] = []\n for (const t of turns) {\n if (t.role === 'system')\n continue\n messages.push({ role: t.role, content: t.content })\n }\n const resolved = await resolveContentRefsInMessages(messages, { resolveContentRef: options.resolveContentRef })\n return finalizeWireMessages(resolved, options)\n}\n\nexport function autoDetectAndConvert(msg: { role: string, content: unknown }): SessionMessage {\n const c: unknown = msg.content\n\n // OpenAI-compat tagged messages\n if (c && typeof c === 'object' && !Array.isArray(c)) {\n const tag = (c as { _tag?: unknown })._tag\n if (typeof tag === 'string' && tag.startsWith('__zidane_'))\n return fromOpenAI(msg)\n }\n\n // Array: inspect block types\n if (Array.isArray(c)) {\n for (const block of c) {\n if (!block || typeof block !== 'object')\n continue\n const b = block as Record<string, unknown>\n if (b.type === 'tool_use' || (b.type === 'tool_result' && 'tool_use_id' in b)) {\n return fromAnthropic(msg)\n }\n if (b.type === 'image_url') {\n return fromOpenAI(msg)\n }\n }\n // Default array → Anthropic\n return fromAnthropic(msg)\n }\n\n // String → either format is the same\n if (typeof c === 'string') {\n return fromAnthropic(msg)\n }\n\n // Default\n return fromAnthropic(msg)\n}\n"],"mappings":"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"}
@@ -1,129 +0,0 @@
1
- //#region src/compact/policy.d.ts
2
- /**
3
- * Auto-compaction trigger policy + effective-context-window math.
4
- *
5
- * Core module (no chat / loop / provider-catalog dependency) so BOTH the
6
- * agent loop's loop-native auto-compaction AND the chat hosts share one
7
- * decision function. Previously `shouldAutoCompact` lived in `src/chat/`
8
- * and `effectiveContextWindow` in `src/chat/providers.ts`; the loop can't
9
- * import from `src/chat/`, so the policy lives here and chat re-exports it
10
- * for back-compat.
11
- *
12
- * Pure functions, no I/O. Same inputs -> same answer.
13
- */
14
- /**
15
- * Reserved output budget subtracted from the raw context window when
16
- * computing the effective ceiling for compaction / warning thresholds.
17
- *
18
- * Aligned with Claude Code's `COMPACT_MAX_OUTPUT_TOKENS = 20_000` — covers
19
- * p99.99 of summary + response output. A turn that consumed N input tokens
20
- * leaves `effectiveWindow - N` headroom for the next prompt's response; once
21
- * headroom shrinks below the threshold, auto-compaction fires.
22
- */
23
- declare const OUTPUT_RESERVE_TOKENS = 20000;
24
- /**
25
- * Effective context window — what the next user turn can actually pack
26
- * before the provider reserves space for the assistant's reply. Equals
27
- * `rawWindow - OUTPUT_RESERVE_TOKENS`, clamped to `>= 1` so a tiny
28
- * (or absurd) window doesn't yield zero / negative thresholds.
29
- *
30
- * Pass `null` through unchanged so callers can pipe a raw window lookup
31
- * directly without an intermediate check.
32
- */
33
- declare function effectiveContextWindow(rawWindow: number | null): number | null;
34
- /**
35
- * Default hysteresis floor for {@link shouldAutoCompact}. After a successful
36
- * compaction lands, the next compaction is suppressed until input usage
37
- * grows by at least this fraction of the effective context window beyond
38
- * the post-compact baseline.
39
- *
40
- * `0.1` = 10% of the window. Picked so the immediate post-compact bounce
41
- * (summary turn + restored attachments + re-emitted system prefix) never
42
- * re-fires the trigger by itself, but a meaningful chunk of new work
43
- * (one or two large tool reads) does. Tune via the predicate's
44
- * `minGrowthFraction` input if a host needs different ergonomics.
45
- */
46
- declare const AUTO_COMPACT_MIN_GROWTH_FRACTION = 0.1;
47
- /**
48
- * Inputs to {@link shouldAutoCompact}.
49
- *
50
- * Kept as a struct so the call site reads as the predicate it is, and so
51
- * future inputs (per-session opt-out, recent-compaction cooldown, …) land
52
- * without re-threading every consumer.
53
- */
54
- interface AutoCompactInput {
55
- /** User's master toggle. `false` → trigger never fires. */
56
- enabled: boolean;
57
- /**
58
- * Threshold expressed as a fraction of the effective context window
59
- * (e.g. `0.8` = 80%). Values outside the open interval `(0, 1)` are
60
- * rejected with `'invalid-threshold'` — `<= 0` is meaningless, and
61
- * `>= 1` would schedule the trigger for "after we've already
62
- * overflowed" which is too late to be useful.
63
- */
64
- threshold: number;
65
- /**
66
- * Latest input-token count from the last `turn:after`. Must be a
67
- * non-negative finite number; `NaN` / `±Infinity` / negative values
68
- * are treated as "no usable signal" and the trigger skips
69
- * conservatively (we'd rather defer compaction than fire on garbage).
70
- */
71
- inputTokens: number;
72
- /**
73
- * Model's raw context window. `null` for unknown / custom models — the
74
- * trigger skips since we can't compute a ratio.
75
- */
76
- rawContextWindow: number | null;
77
- /**
78
- * Whether a compaction is already in flight for this session. Passing it
79
- * through the predicate lets tests assert "doesn't double-fire" without
80
- * spinning up the agent loop.
81
- */
82
- alreadyCompacting?: boolean;
83
- /**
84
- * Input-token count observed immediately AFTER the most recent successful
85
- * compaction landed. Used together with {@link minGrowthFraction} to
86
- * suppress thrashing — after compaction lowers the prefix from 85% → 35%,
87
- * the next few turns drift back up; without hysteresis the trigger fires
88
- * again the instant the threshold is re-crossed, often before the model
89
- * has done any new work. Tracking the post-compact baseline lets the
90
- * predicate require meaningful new growth before re-firing.
91
- *
92
- * `undefined` (no compaction yet this session) → hysteresis disabled,
93
- * predicate behaves as before.
94
- */
95
- lastCompactedInputTokens?: number;
96
- /**
97
- * Minimum fraction of the effective context window that must be CONSUMED
98
- * by new content (i.e. `inputTokens - lastCompactedInputTokens`) before
99
- * a follow-up compaction fires. Expressed in the same units as
100
- * {@link threshold}, e.g. `0.1` = 10% of the window. Defaults to `0`
101
- * (no hysteresis) when omitted; chat hosts pick a value like `0.1`.
102
- *
103
- * Only consulted when {@link lastCompactedInputTokens} is set — first
104
- * compaction in a session always fires off the absolute threshold.
105
- */
106
- minGrowthFraction?: number;
107
- }
108
- type AutoCompactDecision = {
109
- kind: 'fire';
110
- usedFraction: number;
111
- effectiveWindow: number;
112
- } | {
113
- kind: 'skip';
114
- reason: 'disabled' | 'unknown-window' | 'invalid-threshold' | 'invalid-input-tokens' | 'under-threshold' | 'already-compacting' | 'cooldown';
115
- };
116
- /**
117
- * Decide whether auto-compaction should fire for the latest turn.
118
- *
119
- * Order of checks is deliberate: cheapest / most common skips first
120
- * (`disabled` is one boolean read; `unknown-window` is the predictable
121
- * miss for custom models), invariant violations next, then the actual
122
- * threshold math. `already-compacting` runs last so the diagnostic
123
- * surfaces correctly when the predicate is called inside an existing
124
- * compaction window.
125
- */
126
- declare function shouldAutoCompact(input: AutoCompactInput): AutoCompactDecision;
127
- //#endregion
128
- export { effectiveContextWindow as a, OUTPUT_RESERVE_TOKENS as i, AutoCompactDecision as n, shouldAutoCompact as o, AutoCompactInput as r, AUTO_COMPACT_MIN_GROWTH_FRACTION as t };
129
- //# sourceMappingURL=policy-DcGlpaNs.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"policy-DcGlpaNs.d.ts","names":[],"sources":["../src/compact/policy.ts"],"mappings":";;AAsBA;;;;AAAkC;AAWlC;;;;AAA+D;AAkB/D;;;;AAA6C;AAS7C;;;;;cAtCa,qBAAA;;;;;;;AA0FM;AAGnB;;iBAlFgB,sBAAA,CAAuB,SAAwB;;;;;;;;AAoFnC;AAY5B;;;;cA9Ea,gCAAA;;;;AA8EkE;;;;UArE9D,gBAAA;;EAEf,OAAA;;;;;;;;EAQA,SAAA;;;;;;;EAOA,WAAA;;;;;EAKA,gBAAA;;;;;;EAMA,iBAAA;;;;;;;;;;;;;EAaA,wBAAA;;;;;;;;;;;EAWA,iBAAA;AAAA;AAAA,KAGU,mBAAA;EACJ,IAAA;EAAc,YAAA;EAAsB,eAAA;AAAA;EACpC,IAAA;EAAc,MAAA;AAAA;;;;;;;;;;;iBAYN,iBAAA,CAAkB,KAAA,EAAO,gBAAA,GAAmB,mBAAmB"}
@@ -1,114 +0,0 @@
1
- import { r as waitTask, u as shell } from "./agent-Cch2ayTt.js";
2
- import { a as multiEdit, i as readFile, n as createSpawnTool, o as listFiles, r as shellKill, t as writeFile, u as edit } from "./tools-CCd8e-HT.js";
3
- //#region src/presets/basic.ts
4
- /**
5
- * Core tools available in every basic preset (without spawn).
6
- *
7
- * `edit` and `multi_edit` ship in the basic set because surgical edits are the
8
- * default modality for production agents — `write_file` is for full overwrites.
9
- * `glob` and `grep` are exported but opt-in: not every agent needs codebase
10
- * search, and shipping them by default would force `tool:gate` work onto
11
- * consumers that prefer the model to use `shell` + classic Unix tools.
12
- */
13
- const basicTools = {
14
- shell,
15
- shellKill,
16
- waitTask,
17
- readFile,
18
- writeFile,
19
- listFiles,
20
- edit,
21
- multiEdit
22
- };
23
- var basic_default = definePreset({
24
- name: "basic",
25
- system: "You are a helpful assistant with access to shell, file reading, file writing, surgical and multi-edit tools, directory listing, and sub-agent spawning. Prefer `edit` / `multi_edit` for in-place changes and `write_file` for full file overwrites. Use them to accomplish tasks in the project directory.",
26
- get tools() {
27
- return {
28
- ...basicTools,
29
- spawn: createSpawnTool({ persist: true })
30
- };
31
- }
32
- });
33
- //#endregion
34
- //#region src/presets/index.ts
35
- /**
36
- * Identity helper for type inference when defining a preset.
37
- */
38
- function definePreset(config) {
39
- return config;
40
- }
41
- /**
42
- * Field-aware composition of presets. Right-most preset wins for scalar fields;
43
- * objects shallow-merge; arrays and hook handler lists concatenate. Designed so
44
- * stacking presets does the obvious thing without the spread-collision footgun:
45
- *
46
- * - `name`, `system`, `eager`, `skills` → last-defined wins
47
- * - `tools`, `toolAliases`, `behavior` → shallow-merge (later keys override)
48
- * - `behavior.dedupTools`, `behavior.toolBudgets` → **deep-merge** (per-tool-name; later wins on collision)
49
- * - `mcpServers` → concat with last-wins on `name` collision
50
- * - `hooks` → per-event concat; every handler fires
51
- *
52
- * `hooks` always emerges as `event → handler[]` so downstream registration
53
- * (in `createAgent`) sees a uniform shape. Order of handlers within an event
54
- * follows preset order: earlier presets register first.
55
- *
56
- * `mcpServers` is deduped by `name` because shipping two servers with the same
57
- * name would trip the connector at runtime — a later preset overriding an
58
- * earlier preset's `github` server is the practical intent.
59
- *
60
- * `behavior.dedupTools` and `behavior.toolBudgets` get the same per-key deep-merge
61
- * because they are tool-name-keyed records — a preset that ships a dedup hasher
62
- * for one tool should not erase a hasher another preset ships for a different
63
- * tool. Last-wins still applies on a per-tool collision so a downstream preset
64
- * can override an upstream preset's policy for one specific tool. Other
65
- * `behavior` fields keep last-wins semantics.
66
- */
67
- function composePresets(...presets) {
68
- const out = {};
69
- const hooksByEvent = {};
70
- const mcpByName = /* @__PURE__ */ new Map();
71
- for (const p of presets) {
72
- if (p.name !== void 0) out.name = p.name;
73
- if (p.system !== void 0) out.system = p.system;
74
- if (p.eager !== void 0) out.eager = p.eager;
75
- if (p.skills !== void 0) out.skills = p.skills;
76
- if (p.tools) out.tools = {
77
- ...out.tools,
78
- ...p.tools
79
- };
80
- if (p.toolAliases) out.toolAliases = {
81
- ...out.toolAliases,
82
- ...p.toolAliases
83
- };
84
- if (p.behavior) {
85
- const merged = {
86
- ...out.behavior,
87
- ...p.behavior
88
- };
89
- if (out.behavior?.dedupTools || p.behavior.dedupTools) merged.dedupTools = {
90
- ...out.behavior?.dedupTools,
91
- ...p.behavior.dedupTools
92
- };
93
- if (out.behavior?.toolBudgets || p.behavior.toolBudgets) merged.toolBudgets = {
94
- ...out.behavior?.toolBudgets,
95
- ...p.behavior.toolBudgets
96
- };
97
- out.behavior = merged;
98
- }
99
- if (p.mcpServers) for (const server of p.mcpServers) mcpByName.set(server.name, server);
100
- if (p.hooks) for (const [event, handler] of Object.entries(p.hooks)) {
101
- if (handler === void 0) continue;
102
- const list = Array.isArray(handler) ? handler : [handler];
103
- const key = event;
104
- (hooksByEvent[key] ??= []).push(...list);
105
- }
106
- }
107
- if (mcpByName.size > 0) out.mcpServers = [...mcpByName.values()];
108
- if (Object.keys(hooksByEvent).length > 0) out.hooks = hooksByEvent;
109
- return out;
110
- }
111
- //#endregion
112
- export { basic_default as i, definePreset as n, basicTools as r, composePresets as t };
113
-
114
- //# sourceMappingURL=presets-BQWYMHdd.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"presets-BQWYMHdd.js","names":[],"sources":["../src/presets/basic.ts","../src/presets/index.ts"],"sourcesContent":["import { definePreset } from '.'\nimport { edit, listFiles, multiEdit, readFile, shell, shellKill, waitTask, writeFile } from '../tools'\nimport { createSpawnTool } from '../tools/spawn'\n\n/**\n * Core tools available in every basic preset (without spawn).\n *\n * `edit` and `multi_edit` ship in the basic set because surgical edits are the\n * default modality for production agents — `write_file` is for full overwrites.\n * `glob` and `grep` are exported but opt-in: not every agent needs codebase\n * search, and shipping them by default would force `tool:gate` work onto\n * consumers that prefer the model to use `shell` + classic Unix tools.\n */\nexport const basicTools = { shell, shellKill, waitTask, readFile, writeFile, listFiles, edit, multiEdit }\n\nexport default definePreset({\n name: 'basic',\n system: 'You are a helpful assistant with access to shell, file reading, file writing, surgical and multi-edit tools, directory listing, and sub-agent spawning. Prefer `edit` / `multi_edit` for in-place changes and `write_file` for full file overwrites. Use them to accomplish tasks in the project directory.',\n // `tools` is a getter so each access (every `{ ...basic }` spread into\n // `createAgent`) mints a FRESH spawn tool. `createSpawnTool()` carries\n // per-instance state (running children, concurrency counter, child-stats\n // accumulator); a module-level singleton instance would be shared by every\n // agent in the process, breaking concurrent rollouts.\n //\n // `persist: true` shares the parent's session with every child agent — child\n // turns land in `session.turns` tagged with their own `runId`, and the run\n // itself is recorded in `session.runs` with `parentRunId` + `depth`. That's\n // what lets a reloaded TUI session reconstruct the full subagent tree (see\n // `eventsFromTurns` in `tui/store.ts`). Hosts that want children in-memory\n // only can construct their own preset with `createSpawnTool()`.\n get tools() {\n return { ...basicTools, spawn: createSpawnTool({ persist: true }) }\n },\n})\n","import type { AgentHooks, AgentOptions } from '../agent'\n\nexport type { AgentHookMap } from '../agent'\n\n/**\n * A preset is a reusable slice of `AgentOptions` — spread it into `createAgent()`\n * to configure tools, a default system prompt, aliases, behavior defaults, and\n * agent-lifetime hooks.\n *\n * `provider`, `execution`, `session`, and `mcpConnector` are excluded — they're\n * ambient / per-invocation runtime wiring (a custom `mcpConnector` is the MCP\n * connection seam, often closure-bound to a transport / auth provider), so\n * presets stay shareable and composable.\n *\n * ```ts\n * import { basic } from 'zidane/presets'\n * createAgent({ ...basic, provider })\n * ```\n *\n * ### Composing multiple presets\n *\n * Bare `...spread` is shallow — `{ ...a, ...b }` overwrites every key `b`\n * defines, including `hooks`. Use {@link composePresets} when you want\n * field-aware merging (per-event hook concat, tools shallow-merge, etc.):\n *\n * ```ts\n * createAgent({ ...composePresets(basic, telemetry, mine), provider })\n * ```\n */\nexport type Preset = Omit<Partial<AgentOptions>, 'provider' | 'execution' | 'session' | 'mcpConnector'>\n\n/**\n * Identity helper for type inference when defining a preset.\n */\nexport function definePreset(config: Preset): Preset {\n return config\n}\n\n/**\n * Field-aware composition of presets. Right-most preset wins for scalar fields;\n * objects shallow-merge; arrays and hook handler lists concatenate. Designed so\n * stacking presets does the obvious thing without the spread-collision footgun:\n *\n * - `name`, `system`, `eager`, `skills` → last-defined wins\n * - `tools`, `toolAliases`, `behavior` → shallow-merge (later keys override)\n * - `behavior.dedupTools`, `behavior.toolBudgets` → **deep-merge** (per-tool-name; later wins on collision)\n * - `mcpServers` → concat with last-wins on `name` collision\n * - `hooks` → per-event concat; every handler fires\n *\n * `hooks` always emerges as `event → handler[]` so downstream registration\n * (in `createAgent`) sees a uniform shape. Order of handlers within an event\n * follows preset order: earlier presets register first.\n *\n * `mcpServers` is deduped by `name` because shipping two servers with the same\n * name would trip the connector at runtime — a later preset overriding an\n * earlier preset's `github` server is the practical intent.\n *\n * `behavior.dedupTools` and `behavior.toolBudgets` get the same per-key deep-merge\n * because they are tool-name-keyed records — a preset that ships a dedup hasher\n * for one tool should not erase a hasher another preset ships for a different\n * tool. Last-wins still applies on a per-tool collision so a downstream preset\n * can override an upstream preset's policy for one specific tool. Other\n * `behavior` fields keep last-wins semantics.\n */\nexport function composePresets(...presets: Preset[]): Preset {\n const out: Preset = {}\n const hooksByEvent: { [K in keyof AgentHooks]?: AgentHooks[K][] } = {}\n // Keep mcpServers in source-order on first sight, but allow later\n // declarations to override earlier ones with the same `name`. A `Map`\n // keyed by name gives O(1) override + stable iteration.\n const mcpByName = new Map<string, NonNullable<Preset['mcpServers']>[number]>()\n\n for (const p of presets) {\n if (p.name !== undefined)\n out.name = p.name\n if (p.system !== undefined)\n out.system = p.system\n if (p.eager !== undefined)\n out.eager = p.eager\n if (p.skills !== undefined)\n out.skills = p.skills\n if (p.tools)\n out.tools = { ...out.tools, ...p.tools }\n if (p.toolAliases)\n out.toolAliases = { ...out.toolAliases, ...p.toolAliases }\n if (p.behavior) {\n // Top-level shallow-merge first; then deep-merge the two tool-name-keyed\n // sub-records so per-tool entries from earlier presets aren't clobbered.\n const merged: NonNullable<Preset['behavior']> = { ...out.behavior, ...p.behavior }\n if (out.behavior?.dedupTools || p.behavior.dedupTools) {\n merged.dedupTools = { ...out.behavior?.dedupTools, ...p.behavior.dedupTools }\n }\n if (out.behavior?.toolBudgets || p.behavior.toolBudgets) {\n merged.toolBudgets = { ...out.behavior?.toolBudgets, ...p.behavior.toolBudgets }\n }\n out.behavior = merged\n }\n if (p.mcpServers) {\n for (const server of p.mcpServers)\n mcpByName.set(server.name, server)\n }\n if (p.hooks) {\n for (const [event, handler] of Object.entries(p.hooks)) {\n if (handler === undefined)\n continue\n const list = Array.isArray(handler) ? handler : [handler]\n const key = event as keyof AgentHooks\n // Safe cast: we read the loose `AgentHookMap` shape (handler-or-array)\n // and re-emit only as arrays. Each `list` element matches the event's\n // handler signature by construction (the input was typed `AgentHookMap`).\n const bucket = (hooksByEvent[key] ??= []) as unknown[]\n bucket.push(...(list as unknown[]))\n }\n }\n }\n\n if (mcpByName.size > 0)\n out.mcpServers = [...mcpByName.values()]\n\n if (Object.keys(hooksByEvent).length > 0)\n out.hooks = hooksByEvent\n\n return out\n}\n\nexport { default as basic, basicTools } from './basic'\n"],"mappings":";;;;;;;;;;;;AAaA,MAAa,aAAa;CAAE;CAAO;CAAW;CAAU;CAAU;CAAW;CAAW;CAAM;AAAU;AAExG,IAAA,gBAAe,aAAa;CAC1B,MAAM;CACN,QAAQ;CAaR,IAAI,QAAQ;EACV,OAAO;GAAE,GAAG;GAAY,OAAO,gBAAgB,EAAE,SAAS,KAAK,CAAC;EAAE;CACpE;AACF,CAAC;;;;;;ACCD,SAAgB,aAAa,QAAwB;CACnD,OAAO;AACT;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4BA,SAAgB,eAAe,GAAG,SAA2B;CAC3D,MAAM,MAAc,CAAC;CACrB,MAAM,eAA8D,CAAC;CAIrE,MAAM,4BAAY,IAAI,IAAuD;CAE7E,KAAK,MAAM,KAAK,SAAS;EACvB,IAAI,EAAE,SAAS,KAAA,GACb,IAAI,OAAO,EAAE;EACf,IAAI,EAAE,WAAW,KAAA,GACf,IAAI,SAAS,EAAE;EACjB,IAAI,EAAE,UAAU,KAAA,GACd,IAAI,QAAQ,EAAE;EAChB,IAAI,EAAE,WAAW,KAAA,GACf,IAAI,SAAS,EAAE;EACjB,IAAI,EAAE,OACJ,IAAI,QAAQ;GAAE,GAAG,IAAI;GAAO,GAAG,EAAE;EAAM;EACzC,IAAI,EAAE,aACJ,IAAI,cAAc;GAAE,GAAG,IAAI;GAAa,GAAG,EAAE;EAAY;EAC3D,IAAI,EAAE,UAAU;GAGd,MAAM,SAA0C;IAAE,GAAG,IAAI;IAAU,GAAG,EAAE;GAAS;GACjF,IAAI,IAAI,UAAU,cAAc,EAAE,SAAS,YACzC,OAAO,aAAa;IAAE,GAAG,IAAI,UAAU;IAAY,GAAG,EAAE,SAAS;GAAW;GAE9E,IAAI,IAAI,UAAU,eAAe,EAAE,SAAS,aAC1C,OAAO,cAAc;IAAE,GAAG,IAAI,UAAU;IAAa,GAAG,EAAE,SAAS;GAAY;GAEjF,IAAI,WAAW;EACjB;EACA,IAAI,EAAE,YACJ,KAAK,MAAM,UAAU,EAAE,YACrB,UAAU,IAAI,OAAO,MAAM,MAAM;EAErC,IAAI,EAAE,OACJ,KAAK,MAAM,CAAC,OAAO,YAAY,OAAO,QAAQ,EAAE,KAAK,GAAG;GACtD,IAAI,YAAY,KAAA,GACd;GACF,MAAM,OAAO,MAAM,QAAQ,OAAO,IAAI,UAAU,CAAC,OAAO;GACxD,MAAM,MAAM;GAKZ,CADgB,aAAa,SAAS,CAAC,GAChC,KAAK,GAAI,IAAkB;EACpC;CAEJ;CAEA,IAAI,UAAU,OAAO,GACnB,IAAI,aAAa,CAAC,GAAG,UAAU,OAAO,CAAC;CAEzC,IAAI,OAAO,KAAK,YAAY,EAAE,SAAS,GACrC,IAAI,QAAQ;CAEd,OAAO;AACT"}