zidane 7.2.5 → 8.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +34 -6
- package/dist/{acp-D-tVyUjw.js → acp-DQDhi2dj.js} +230 -77
- package/dist/acp-DQDhi2dj.js.map +1 -0
- package/dist/acp-cli.d.ts +1 -1
- package/dist/acp-cli.js +9 -66
- package/dist/acp-cli.js.map +1 -1
- package/dist/acp.d.ts +10 -590
- package/dist/acp.d.ts.map +1 -1
- package/dist/acp.js +3 -3
- package/dist/{agent-D0zZnGbt.js → agent-DSLNmBp0.js} +14401 -13214
- package/dist/agent-DSLNmBp0.js.map +1 -0
- package/dist/agent.d.ts +1 -1
- package/dist/agent.js +3 -2
- package/dist/aliasing-lVFbm81n.js +217 -0
- package/dist/aliasing-lVFbm81n.js.map +1 -0
- package/dist/{anthropic-C2aole0G.js → anthropic-CD00LhUP.js} +1442 -1264
- package/dist/anthropic-CD00LhUP.js.map +1 -0
- package/dist/artifacts-CV2hUKnL.js.map +1 -1
- package/dist/{atomic-write-B7zr1ddF.js → atomic-write-Ijgf2Mhc.js} +13 -3
- package/dist/atomic-write-Ijgf2Mhc.js.map +1 -0
- package/dist/call-tool-dHlbGOIY.js +70 -0
- package/dist/call-tool-dHlbGOIY.js.map +1 -0
- package/dist/chat/pure.d.ts +372 -6
- package/dist/chat/pure.d.ts.map +1 -1
- package/dist/chat/pure.js +35 -244
- package/dist/chat/pure.js.map +1 -1
- package/dist/{approvals-DKaJZYlm.js → chat-JPJJ8uu5.js} +15879 -14631
- package/dist/chat-JPJJ8uu5.js.map +1 -0
- package/dist/chat.d.ts +4 -6
- package/dist/chat.js +23 -12
- package/dist/cli-shared-C-YCaglL.js +159 -0
- package/dist/cli-shared-C-YCaglL.js.map +1 -0
- package/dist/client-core-BQSyDALT.d.ts +2115 -0
- package/dist/client-core-BQSyDALT.d.ts.map +1 -0
- package/dist/codemode-worker.d.ts +1 -0
- package/dist/codemode-worker.js +155 -0
- package/dist/codemode-worker.js.map +1 -0
- package/dist/codemode.d.ts +352 -0
- package/dist/codemode.d.ts.map +1 -0
- package/dist/codemode.js +5 -0
- package/dist/connection-Dr-Js4yZ.d.ts +28 -0
- package/dist/connection-Dr-Js4yZ.d.ts.map +1 -0
- package/dist/connection-loop-gdh22LTI.js +112 -0
- package/dist/connection-loop-gdh22LTI.js.map +1 -0
- package/dist/context-segments-BHKlagL6.js +1016 -0
- package/dist/context-segments-BHKlagL6.js.map +1 -0
- package/dist/{context-transport-T_6AYIvy.js → context-transport-DSMTUsK1.js} +3 -3
- package/dist/{context-transport-T_6AYIvy.js.map → context-transport-DSMTUsK1.js.map} +1 -1
- package/dist/contexts/daytona.d.ts +19 -8
- package/dist/contexts/daytona.d.ts.map +1 -1
- package/dist/contexts/daytona.js +1 -440
- package/dist/contexts/docker.d.ts +36 -7
- package/dist/contexts/docker.d.ts.map +1 -1
- package/dist/contexts/docker.js +1 -456
- package/dist/contexts/e2b.d.ts +68 -13
- package/dist/contexts/e2b.d.ts.map +1 -1
- package/dist/contexts/e2b.js +1 -382
- package/dist/contexts/sandbox.d.ts +1 -1
- package/dist/contexts/sandbox.js +5 -0
- package/dist/contexts/sandbox.js.map +1 -1
- package/dist/{contexts-CRE9pw07.js → contexts-d7UolYot.js} +1059 -524
- package/dist/contexts-d7UolYot.js.map +1 -0
- package/dist/contexts.d.ts +3 -3
- package/dist/contexts.js +1 -1
- package/dist/cred-keys-GpBg71cP.js +105 -0
- package/dist/cred-keys-GpBg71cP.js.map +1 -0
- package/dist/{auth-BG2rVKSt.js → credentials-JttEuRON.js} +55 -206
- package/dist/credentials-JttEuRON.js.map +1 -0
- package/dist/{cursor-iojRXHF9.js → cursor-CdjaQTBW.js} +3 -3
- package/dist/{cursor-iojRXHF9.js.map → cursor-CdjaQTBW.js.map} +1 -1
- package/dist/daemon-cli.d.ts +1 -1
- package/dist/daemon-cli.js +3 -2
- package/dist/daemon-cli.js.map +1 -1
- package/dist/daytona-DG3omipZ.js +513 -0
- package/dist/daytona-DG3omipZ.js.map +1 -0
- package/dist/defaults-Cx3zvDOV.js +23 -0
- package/dist/defaults-Cx3zvDOV.js.map +1 -0
- package/dist/dispatcher-BMlu2BmZ.js +4941 -0
- package/dist/dispatcher-BMlu2BmZ.js.map +1 -0
- package/dist/docker-BZhMMJUp.js +727 -0
- package/dist/docker-BZhMMJUp.js.map +1 -0
- package/dist/e2b-CEVOdRib.js +480 -0
- package/dist/e2b-CEVOdRib.js.map +1 -0
- package/dist/edit-utils-EGosADZq.js +234 -0
- package/dist/edit-utils-EGosADZq.js.map +1 -0
- package/dist/environment-8wsKE2Ln.js +214 -0
- package/dist/environment-8wsKE2Ln.js.map +1 -0
- package/dist/eval-BNcvle_J.js +1595 -0
- package/dist/eval-BNcvle_J.js.map +1 -0
- package/dist/eval.d.ts +2 -2
- package/dist/eval.js +1 -1489
- package/dist/executor-Cx5-8yqi.js +621 -0
- package/dist/executor-Cx5-8yqi.js.map +1 -0
- package/dist/extension-authoring-DyGGmq9V.js +385 -0
- package/dist/extension-authoring-DyGGmq9V.js.map +1 -0
- package/dist/extensions.d.ts +2 -2
- package/dist/extensions.js +3 -3
- package/dist/{fetch-url-DX75gpL0.js → fetch-url-Ct2TjDWt.js} +4 -4
- package/dist/{fetch-url-DX75gpL0.js.map → fetch-url-Ct2TjDWt.js.map} +1 -1
- package/dist/{format-BF745pLL.js → format-C2NQEVUH.js} +39 -2
- package/dist/format-C2NQEVUH.js.map +1 -0
- package/dist/format-bytes-C7tfc3Zm.js +55 -0
- package/dist/format-bytes-C7tfc3Zm.js.map +1 -0
- package/dist/headless-C_rNUuYC.js +960 -0
- package/dist/headless-C_rNUuYC.js.map +1 -0
- package/dist/headless.d.ts +1 -1
- package/dist/headless.js +1 -413
- package/dist/{history-search-C4bk1Wz_.js → history-search-CcYzF8-0.js} +7 -3
- package/dist/history-search-CcYzF8-0.js.map +1 -0
- package/dist/history-search-worker.d.ts +1 -1
- package/dist/history-search-worker.js +1 -1
- package/dist/host-D7NrI03V.js +378 -0
- package/dist/host-D7NrI03V.js.map +1 -0
- package/dist/host-signals-BcP5QKUD.js +118 -0
- package/dist/host-signals-BcP5QKUD.js.map +1 -0
- package/dist/identity-CwfO8K-t.js +26 -0
- package/dist/identity-CwfO8K-t.js.map +1 -0
- package/dist/{index-BgN1T3lk.d.ts → index-BGe1fQT7.d.ts} +10987 -9320
- package/dist/index-BGe1fQT7.d.ts.map +1 -0
- package/dist/index-BVQsIKGn.d.ts +448 -0
- package/dist/index-BVQsIKGn.d.ts.map +1 -0
- package/dist/{index-C6NEd5y_.d.ts → index-CHABJd-L.d.ts} +3386 -502
- package/dist/index-CHABJd-L.d.ts.map +1 -0
- package/dist/{index-C37_ppWv.d.ts → index-D6a7qXpg.d.ts} +2 -3
- package/dist/index-D6a7qXpg.d.ts.map +1 -0
- package/dist/index.d.ts +6 -6
- package/dist/index.js +27 -23
- package/dist/{completion-core-BRo86R_L.js → inline-ghost-BVRQeGoL.js} +50 -2
- package/dist/inline-ghost-BVRQeGoL.js.map +1 -0
- package/dist/ipc/remote.d.ts +313 -0
- package/dist/ipc/remote.d.ts.map +1 -0
- package/dist/ipc/remote.js +4 -0
- package/dist/ipc.d.ts +6 -964
- package/dist/ipc.js +403 -4
- package/dist/ipc.js.map +1 -0
- package/dist/{isolation-Kfoof0MM.d.ts → isolation-D9L650W5.d.ts} +100 -15
- package/dist/isolation-D9L650W5.d.ts.map +1 -0
- package/dist/json-rpc--HXQti1E.js +350 -0
- package/dist/json-rpc--HXQti1E.js.map +1 -0
- package/dist/links-j8rED1sR.js +603 -0
- package/dist/links-j8rED1sR.js.map +1 -0
- package/dist/local-terminal-D8QThwo_.js +252 -0
- package/dist/local-terminal-D8QThwo_.js.map +1 -0
- package/dist/{logger--C1VQjwJ.js → logger-Gtqlayx8.js} +199 -173
- package/dist/logger-Gtqlayx8.js.map +1 -0
- package/dist/logs-view-CWG8aUAG.js.map +1 -1
- package/dist/{mcp-CgNd-f3F.js → mcp-_wecH9Qe.js} +608 -562
- package/dist/mcp-_wecH9Qe.js.map +1 -0
- package/dist/mcp.d.ts +2 -2
- package/dist/mcp.js +2 -2
- package/dist/media-sniff-UKijEaiQ.js.map +1 -1
- package/dist/{messages-2jcOA_5R.js → messages-BqiwcD2Q.js} +1017 -1014
- package/dist/messages-BqiwcD2Q.js.map +1 -0
- package/dist/{oauth-DxHO17JE.js → oauth-Px_pBB9W.js} +5 -5
- package/dist/{oauth-DxHO17JE.js.map → oauth-Px_pBB9W.js.map} +1 -1
- package/dist/{openai-compat-Dy56weK8.js → openai-compat-CFrpH7uq.js} +432 -589
- package/dist/openai-compat-CFrpH7uq.js.map +1 -0
- package/dist/orchestration-BCGmB8Ps.js +511 -0
- package/dist/orchestration-BCGmB8Ps.js.map +1 -0
- package/dist/output/stream-json.d.ts +1 -2
- package/dist/output/stream-json.d.ts.map +1 -1
- package/dist/output/stream-json.js +1 -1
- package/dist/output/terminal.d.ts +1 -2
- package/dist/output/terminal.d.ts.map +1 -1
- package/dist/output/terminal.js +13 -7
- package/dist/output/terminal.js.map +1 -1
- package/dist/{plugins-gbI7SBA6.js → plugins-DS7mahzZ.js} +20 -101
- package/dist/plugins-DS7mahzZ.js.map +1 -0
- package/dist/plugins.d.ts +1 -1
- package/dist/plugins.js +1 -2
- package/dist/prelude-Cxo4t74B.js +517 -0
- package/dist/prelude-Cxo4t74B.js.map +1 -0
- package/dist/presets.d.ts +1 -1
- package/dist/presets.js +1 -2
- package/dist/project-root-B8zADr4o.js +167 -0
- package/dist/project-root-B8zADr4o.js.map +1 -0
- package/dist/project-user-paths-BSgtrRxl.js +58 -0
- package/dist/project-user-paths-BSgtrRxl.js.map +1 -0
- package/dist/{prompts-Pqc3JdW_.d.ts → prompts-DYcvqShf.d.ts} +14 -11
- package/dist/prompts-DYcvqShf.d.ts.map +1 -0
- package/dist/protocol-DnhqqSmE.js +13 -0
- package/dist/protocol-DnhqqSmE.js.map +1 -0
- package/dist/providers/anthropic.d.ts +2 -2
- package/dist/providers/anthropic.js +1 -2
- package/dist/providers/arcee.d.ts +1 -1
- package/dist/providers/arcee.js +1 -1
- package/dist/providers/baseten.d.ts +1 -1
- package/dist/providers/baseten.js +1 -1
- package/dist/providers/cerebras.d.ts +1 -1
- package/dist/providers/cerebras.js +3 -2
- package/dist/providers/cerebras.js.map +1 -1
- package/dist/providers/local.d.ts +1 -1
- package/dist/providers/local.js +1 -1
- package/dist/providers/openai-compat.d.ts +1 -1
- package/dist/providers/openai-compat.js +1 -2
- package/dist/providers/openai.d.ts +1 -1
- package/dist/providers/openai.js +15 -12
- package/dist/providers/openai.js.map +1 -1
- package/dist/providers/openrouter.d.ts +1 -1
- package/dist/providers/openrouter.js +3 -2
- package/dist/providers/openrouter.js.map +1 -1
- package/dist/providers/xai.d.ts +1 -1
- package/dist/providers/xai.js +3 -3
- package/dist/{providers-BVhnFyiY.js → providers-XUR7F4Hi.js} +4 -4
- package/dist/{providers-BVhnFyiY.js.map → providers-XUR7F4Hi.js.map} +1 -1
- package/dist/providers.d.ts +1 -1
- package/dist/providers.js +4 -4
- package/dist/registry-D6ShBWJU.js +5234 -0
- package/dist/registry-D6ShBWJU.js.map +1 -0
- package/dist/remote-hosts-BtA_9ZGp.js +97 -0
- package/dist/remote-hosts-BtA_9ZGp.js.map +1 -0
- package/dist/restate.d.ts +2 -3
- package/dist/restate.d.ts.map +1 -1
- package/dist/restate.js +631 -572
- package/dist/restate.js.map +1 -1
- package/dist/run-summary-CklLiZ4y.js +288 -0
- package/dist/run-summary-CklLiZ4y.js.map +1 -0
- package/dist/{sandbox-BH0WQkXn.d.ts → sandbox-C5dR5DwQ.d.ts} +6 -3
- package/dist/sandbox-C5dR5DwQ.d.ts.map +1 -0
- package/dist/session/sqlite.d.ts +1 -2
- package/dist/session/sqlite.d.ts.map +1 -1
- package/dist/session/sqlite.js +1 -616
- package/dist/session-factory-BUGY5P40.js +1576 -0
- package/dist/session-factory-BUGY5P40.js.map +1 -0
- package/dist/{session-BqRP1hS7.js → session-xh9JXu6i.js} +94 -52
- package/dist/session-xh9JXu6i.js.map +1 -0
- package/dist/session.d.ts +1 -1
- package/dist/session.js +2 -2
- package/dist/settings-keys-Ckf29NeM.js +677 -0
- package/dist/settings-keys-Ckf29NeM.js.map +1 -0
- package/dist/shell-path-Dqaoow2J.js +412 -0
- package/dist/shell-path-Dqaoow2J.js.map +1 -0
- package/dist/{skills-BC3dodWp.js → skills-DKqZJm4X.js} +430 -470
- package/dist/skills-DKqZJm4X.js.map +1 -0
- package/dist/skills.d.ts +2 -2
- package/dist/skills.js +1 -2
- package/dist/source-mPExaUm8.js +381 -0
- package/dist/source-mPExaUm8.js.map +1 -0
- package/dist/sqlite-DV1DQzN2.js +698 -0
- package/dist/sqlite-DV1DQzN2.js.map +1 -0
- package/dist/{src-CkNQKFKr.js → src-BRMYRJib.js} +903 -1121
- package/dist/src-BRMYRJib.js.map +1 -0
- package/dist/{stdio-DPpBDPx5.js → stdio-C6YyoW3I.js} +4 -4
- package/dist/{stdio-DPpBDPx5.js.map → stdio-C6YyoW3I.js.map} +1 -1
- package/dist/{stdio-loader-Bbx19dMZ.js → stdio-loader-C830Vg-Z.js} +4 -4
- package/dist/{stdio-loader-Bbx19dMZ.js.map → stdio-loader-C830Vg-Z.js.map} +1 -1
- package/dist/system-prompt-MNVHatSD.d.ts.map +1 -1
- package/dist/timeout-DEaqslLO.d.ts.map +1 -1
- package/dist/todo-edits-Dn251YUP.js +1790 -0
- package/dist/todo-edits-Dn251YUP.js.map +1 -0
- package/dist/{turn-operations-DrbJlpq9.js → tool-formatters-IQFDrdrs.js} +1456 -2120
- package/dist/tool-formatters-IQFDrdrs.js.map +1 -0
- package/dist/tool-state-Dku6YqAB.js +989 -0
- package/dist/tool-state-Dku6YqAB.js.map +1 -0
- package/dist/tools/fetch-url.d.ts +1 -2
- package/dist/tools/fetch-url.d.ts.map +1 -1
- package/dist/tools/fetch-url.js +1 -2
- package/dist/tools/prompts.d.ts +1 -1
- package/dist/tools/prompts.js +7 -7
- package/dist/tools/prompts.js.map +1 -1
- package/dist/tools/web-search.d.ts +1 -2
- package/dist/tools/web-search.d.ts.map +1 -1
- package/dist/tools/web-search.js +2 -2
- package/dist/tools/web-search.js.map +1 -1
- package/dist/tools-_DnT3AGM.js +578 -0
- package/dist/tools-_DnT3AGM.js.map +1 -0
- package/dist/tools.d.ts +3 -3
- package/dist/tools.js +4 -2
- package/dist/tui.d.ts +534 -517
- package/dist/tui.d.ts.map +1 -1
- package/dist/tui.js +34933 -27243
- package/dist/tui.js.map +1 -1
- package/dist/turn-operations-B8sokwi5.js +333 -0
- package/dist/turn-operations-B8sokwi5.js.map +1 -0
- package/dist/turn-operations-DQX5ZZni.d.ts +3089 -0
- package/dist/turn-operations-DQX5ZZni.d.ts.map +1 -0
- package/dist/types-C7ZFOztE.d.ts +132 -0
- package/dist/types-C7ZFOztE.d.ts.map +1 -0
- package/dist/types-CH5XpIHw.js +114 -0
- package/dist/types-CH5XpIHw.js.map +1 -0
- package/dist/{types-CWgENVLY.js → types-Cu0ZGDu9.js} +10 -6
- package/dist/types-Cu0ZGDu9.js.map +1 -0
- package/dist/types-IqegbJEE.d.ts +624 -0
- package/dist/types-IqegbJEE.d.ts.map +1 -0
- package/dist/types.d.ts +4 -4
- package/dist/types.js +1 -1
- package/dist/url-D8HCl65b.js +1259 -0
- package/dist/url-D8HCl65b.js.map +1 -0
- package/dist/wasm-BVT-j5cl.js +33 -0
- package/dist/wasm-BVT-j5cl.js.map +1 -0
- package/dist/workspace-exec-stream-SV2R9d5S.js +355 -0
- package/dist/workspace-exec-stream-SV2R9d5S.js.map +1 -0
- package/dist/ws-CIHMvlSh.js +952 -0
- package/dist/ws-CIHMvlSh.js.map +1 -0
- package/dist/ws-client-N7NxzvQp.js +230 -0
- package/dist/ws-client-N7NxzvQp.js.map +1 -0
- package/dist/{xai-CazjStOK.js → xai-CvJTeLrI.js} +165 -5
- package/dist/xai-CvJTeLrI.js.map +1 -0
- package/dist/xdg-zweed0-t.js +117 -0
- package/dist/xdg-zweed0-t.js.map +1 -0
- package/docs/ACP.md +52 -0
- package/docs/ARCHITECTURE.md +103 -6
- package/docs/ARTIFACTS.md +8 -4
- package/docs/CHAT.md +165 -14
- package/docs/EXECUTION_CONTEXT.md +8 -0
- package/docs/EXTENSIONS.md +123 -2
- package/docs/HEADLESS.md +2 -0
- package/docs/IPC.md +775 -64
- package/docs/MACHINES.md +456 -0
- package/docs/PANELS.md +3 -0
- package/docs/README.md +4 -0
- package/docs/RESTATE.md +3 -2
- package/docs/RUN_IN_BACKGROUND.md +10 -2
- package/docs/SERVER.md +1085 -0
- package/docs/SKILL.md +6 -1
- package/docs/TERMINAL.md +75 -0
- package/docs/TUI.md +65 -14
- package/package.json +58 -26
- package/scripts/eval.ts +4 -0
- package/dist/acp-D-tVyUjw.js.map +0 -1
- package/dist/agent-D0zZnGbt.js.map +0 -1
- package/dist/anthropic-C2aole0G.js.map +0 -1
- package/dist/approvals-DKaJZYlm.js.map +0 -1
- package/dist/atomic-write-B7zr1ddF.js.map +0 -1
- package/dist/auth-BG2rVKSt.js.map +0 -1
- package/dist/completion-core-BRo86R_L.js.map +0 -1
- package/dist/contexts/daytona.js.map +0 -1
- package/dist/contexts/docker.js.map +0 -1
- package/dist/contexts/e2b.js.map +0 -1
- package/dist/contexts-CRE9pw07.js.map +0 -1
- package/dist/eval.js.map +0 -1
- package/dist/format-BF745pLL.js.map +0 -1
- package/dist/glob-DluQFSw1.js +0 -270
- package/dist/glob-DluQFSw1.js.map +0 -1
- package/dist/headless.js.map +0 -1
- package/dist/history-search-C4bk1Wz_.js.map +0 -1
- package/dist/index-BgN1T3lk.d.ts.map +0 -1
- package/dist/index-C37_ppWv.d.ts.map +0 -1
- package/dist/index-C6NEd5y_.d.ts.map +0 -1
- package/dist/ipc-BKVIIOqH.js +0 -331
- package/dist/ipc-BKVIIOqH.js.map +0 -1
- package/dist/ipc.d.ts.map +0 -1
- package/dist/isolation-Kfoof0MM.d.ts.map +0 -1
- package/dist/json-rpc-rSWMUh9b.js +0 -192
- package/dist/json-rpc-rSWMUh9b.js.map +0 -1
- package/dist/logger--C1VQjwJ.js.map +0 -1
- package/dist/mcp-CgNd-f3F.js.map +0 -1
- package/dist/messages-2jcOA_5R.js.map +0 -1
- package/dist/openai-compat-Dy56weK8.js.map +0 -1
- package/dist/output-cap-C9zukcCj.js +0 -100
- package/dist/output-cap-C9zukcCj.js.map +0 -1
- package/dist/panels-B6gRk4bf.js +0 -789
- package/dist/panels-B6gRk4bf.js.map +0 -1
- package/dist/plugins-gbI7SBA6.js.map +0 -1
- package/dist/prompts-Pqc3JdW_.d.ts.map +0 -1
- package/dist/run-summary-BU_NgwUT.js +0 -269
- package/dist/run-summary-BU_NgwUT.js.map +0 -1
- package/dist/sandbox-BH0WQkXn.d.ts.map +0 -1
- package/dist/session/sqlite.js.map +0 -1
- package/dist/session-BqRP1hS7.js.map +0 -1
- package/dist/shell-path-DfdXrGg9.js +0 -1549
- package/dist/shell-path-DfdXrGg9.js.map +0 -1
- package/dist/skills-BC3dodWp.js.map +0 -1
- package/dist/src-CkNQKFKr.js.map +0 -1
- package/dist/todo-edits-UOwgxGKu.js +0 -528
- package/dist/todo-edits-UOwgxGKu.js.map +0 -1
- package/dist/tool-formatters-DoRLnfuD.d.ts +0 -759
- package/dist/tool-formatters-DoRLnfuD.d.ts.map +0 -1
- package/dist/transcript-anchors-BeudMbXx.d.ts +0 -1762
- package/dist/transcript-anchors-BeudMbXx.d.ts.map +0 -1
- package/dist/turn-operations-C8bMBDl_.d.ts +0 -1258
- package/dist/turn-operations-C8bMBDl_.d.ts.map +0 -1
- package/dist/turn-operations-DrbJlpq9.js.map +0 -1
- package/dist/types-CWgENVLY.js.map +0 -1
- package/dist/xai-CazjStOK.js.map +0 -1
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
//#region src/chat/model-chain.ts
|
|
2
|
+
/** Identity of a chain entry — the pair, not object identity. */
|
|
3
|
+
function chainEntryKey(entry) {
|
|
4
|
+
return `${entry.provider}\u0000${entry.model}`;
|
|
5
|
+
}
|
|
6
|
+
/** Toggle `entry`: absent → appended, present → removed. Pure. */
|
|
7
|
+
function toggleKeyed(chain, entry, keyOf) {
|
|
8
|
+
const key = keyOf(entry);
|
|
9
|
+
const idx = chain.findIndex((e) => keyOf(e) === key);
|
|
10
|
+
if (idx === -1) return [...chain, entry];
|
|
11
|
+
return [...chain.slice(0, idx), ...chain.slice(idx + 1)];
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Make `entry` the primary (position 0), keeping the rest in order. Inserts
|
|
15
|
+
* when absent, promotes when present; no-op when it already leads.
|
|
16
|
+
*
|
|
17
|
+
* This is `↵` in the picker. It exists because toggling APPENDS: with a chain
|
|
18
|
+
* of `[current]`, toggling a new model produced `[current, new]` — the pick
|
|
19
|
+
* became a fallback and the active model never changed. "Highlight and ↵"
|
|
20
|
+
* means "use this one", so that gesture promotes; building a fallback list is
|
|
21
|
+
* the secondary gesture (`⇥`) and keeps toggle semantics.
|
|
22
|
+
*/
|
|
23
|
+
function pickPrimaryKeyed(chain, entry, keyOf) {
|
|
24
|
+
const key = keyOf(entry);
|
|
25
|
+
return [entry, ...chain.filter((e) => keyOf(e) !== key)];
|
|
26
|
+
}
|
|
27
|
+
/** 1-based position of `key` in the chain, or `null` when absent. */
|
|
28
|
+
function positionKeyed(chain, key, keyOf) {
|
|
29
|
+
const idx = chain.findIndex((e) => keyOf(e) === key);
|
|
30
|
+
return idx === -1 ? null : idx + 1;
|
|
31
|
+
}
|
|
32
|
+
/** Same entries in the same order. */
|
|
33
|
+
function chainsEqualKeyed(a, b, keyOf) {
|
|
34
|
+
return a.length === b.length && a.every((e, i) => keyOf(e) === keyOf(b[i]));
|
|
35
|
+
}
|
|
36
|
+
/** Move the entry with `key` by one priority slot; boundary or missing = identity. */
|
|
37
|
+
function reorderKeyed(chain, key, delta, keyOf) {
|
|
38
|
+
const from = chain.findIndex((e) => keyOf(e) === key);
|
|
39
|
+
const to = from + delta;
|
|
40
|
+
if (from < 0 || to < 0 || to >= chain.length) return chain;
|
|
41
|
+
const next = [...chain];
|
|
42
|
+
const [entry] = next.splice(from, 1);
|
|
43
|
+
next.splice(to, 0, entry);
|
|
44
|
+
return next;
|
|
45
|
+
}
|
|
46
|
+
function toggleChainEntry(chain, entry) {
|
|
47
|
+
return toggleKeyed(chain, entry, chainEntryKey);
|
|
48
|
+
}
|
|
49
|
+
function pickChainPrimary(chain, entry) {
|
|
50
|
+
return pickPrimaryKeyed(chain, entry, chainEntryKey);
|
|
51
|
+
}
|
|
52
|
+
/** 1-based chain position of a provider+model pair, or `null` when not in the chain. */
|
|
53
|
+
function chainPositionOf(chain, provider, model) {
|
|
54
|
+
return positionKeyed(chain, chainEntryKey({
|
|
55
|
+
provider,
|
|
56
|
+
model
|
|
57
|
+
}), chainEntryKey);
|
|
58
|
+
}
|
|
59
|
+
function chainsEqual(a, b) {
|
|
60
|
+
return chainsEqualKeyed(a, b, chainEntryKey);
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Did the SET of provider keys change between two chains? The agent is
|
|
64
|
+
* built with one provider instance per distinct chain key, so a set
|
|
65
|
+
* change requires a session re-activation (rebuild); a pure model /
|
|
66
|
+
* order change within the same providers does not.
|
|
67
|
+
*/
|
|
68
|
+
function providerKeySetChanged(prev, next) {
|
|
69
|
+
const prevKeys = new Set(prev.map((e) => e.provider));
|
|
70
|
+
const nextKeys = new Set(next.map((e) => e.provider));
|
|
71
|
+
if (prevKeys.size !== nextKeys.size) return true;
|
|
72
|
+
for (const k of nextKeys) if (!prevKeys.has(k)) return true;
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Assemble the `agent.run` `model` option from a chain.
|
|
77
|
+
*
|
|
78
|
+
* - Single-entry chain → the bare model id string (byte-identical to the
|
|
79
|
+
* pre-chain behavior).
|
|
80
|
+
* - Multi-entry chain → pinned `{ provider, model }` targets, where
|
|
81
|
+
* `provider` is the runtime `Provider.name` resolved via
|
|
82
|
+
* `providerNameFor` (chain entries carry chat-level `ProviderKey`s,
|
|
83
|
+
* which need not equal the instance names the agent loop matches on).
|
|
84
|
+
*
|
|
85
|
+
* Throws only on an empty chain — a programmer error, since chains
|
|
86
|
+
* always carry a primary. Stale or unresolvable entries degrade
|
|
87
|
+
* defensively instead (never throw, never produce an entry the agent
|
|
88
|
+
* would reject):
|
|
89
|
+
* - Entries whose key has no resolvable name (provider not constructed
|
|
90
|
+
* into the current agent) are dropped.
|
|
91
|
+
* - If the PRIMARY itself doesn't resolve, or fewer than two entries
|
|
92
|
+
* survive, fall back to the bare primary model string.
|
|
93
|
+
*
|
|
94
|
+
* `contextWindowFor` (optional) stamps each target with its model's
|
|
95
|
+
* context window from the host catalog, so the loop re-bases the
|
|
96
|
+
* auto-compact trigger when a fallback advances onto it (the host's
|
|
97
|
+
* explicit window is sized for the PRIMARY otherwise).
|
|
98
|
+
*/
|
|
99
|
+
function buildRunModel(chain, providerNameFor, contextWindowFor) {
|
|
100
|
+
const primary = chain[0];
|
|
101
|
+
if (!primary) throw new Error("buildRunModel: chain must not be empty");
|
|
102
|
+
if (chain.length === 1 || providerNameFor(primary.provider) === void 0) return primary.model;
|
|
103
|
+
const resolved = [];
|
|
104
|
+
for (const entry of chain) {
|
|
105
|
+
const name = providerNameFor(entry.provider);
|
|
106
|
+
if (name === void 0) continue;
|
|
107
|
+
const contextWindow = contextWindowFor?.(entry);
|
|
108
|
+
resolved.push({
|
|
109
|
+
provider: name,
|
|
110
|
+
model: entry.model,
|
|
111
|
+
...typeof contextWindow === "number" && contextWindow > 0 ? { contextWindow } : {}
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
return resolved.length > 1 ? resolved : primary.model;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Validate a persisted chain read back from `state.json`. The state file
|
|
118
|
+
* is user-editable JSON, so the value can be arbitrarily malformed —
|
|
119
|
+
* return only the well-shaped `{ provider, model }` entries (both
|
|
120
|
+
* non-empty strings), or `[]` for anything else. Never throws.
|
|
121
|
+
*/
|
|
122
|
+
function sanitizeModelChain(value) {
|
|
123
|
+
if (!Array.isArray(value)) return [];
|
|
124
|
+
const entries = [];
|
|
125
|
+
for (const item of value) {
|
|
126
|
+
if (typeof item !== "object" || item === null || !("provider" in item) || !("model" in item)) continue;
|
|
127
|
+
const { provider, model } = item;
|
|
128
|
+
if (typeof provider === "string" && provider.length > 0 && typeof model === "string" && model.length > 0) entries.push({
|
|
129
|
+
provider,
|
|
130
|
+
model
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
return entries;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Restore the fallback tail of a persisted chain for a resolved primary
|
|
137
|
+
* pair. Returns entries 1+ only when the persisted chain's entry 0
|
|
138
|
+
* matches `primary` — a divergent chain belongs to a different selection
|
|
139
|
+
* (e.g. a `--model` launch override) and silently attaching it would
|
|
140
|
+
* surprise. Entries whose provider isn't registered, entries equal to
|
|
141
|
+
* the primary, and exact duplicates drop. Accepts the raw persisted
|
|
142
|
+
* value (`state.json` is user-editable) — shape validation included.
|
|
143
|
+
*/
|
|
144
|
+
function restoreChainFallbacks(saved, primary, isRegistered) {
|
|
145
|
+
const chain = sanitizeModelChain(saved);
|
|
146
|
+
const head = chain[0];
|
|
147
|
+
if (chain.length < 2 || !head || head.provider !== primary.provider || head.model !== primary.model) return [];
|
|
148
|
+
return filterChainFallbacks(chain.slice(1), primary, isRegistered);
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Filter candidate fallback entries against a primary pair, preserving
|
|
152
|
+
* picked order: entries whose provider `isAvailable` rejects, entries
|
|
153
|
+
* equal to the primary, and exact duplicates drop. Shared by the
|
|
154
|
+
* picker's apply path (live-auth availability) and persisted-chain
|
|
155
|
+
* restore (registry availability).
|
|
156
|
+
*/
|
|
157
|
+
function filterChainFallbacks(entries, primary, isAvailable) {
|
|
158
|
+
const fallbacks = [];
|
|
159
|
+
for (const entry of entries) {
|
|
160
|
+
if (!isAvailable(entry.provider)) continue;
|
|
161
|
+
if (entry.provider === primary.provider && entry.model === primary.model) continue;
|
|
162
|
+
if (fallbacks.some((f) => f.provider === entry.provider && f.model === entry.model)) continue;
|
|
163
|
+
fallbacks.push({
|
|
164
|
+
provider: entry.provider,
|
|
165
|
+
model: entry.model
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
return fallbacks;
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* What of a model pick a window remembers as its default (`lastModelChain`:
|
|
172
|
+
* the next new session's model, the next launch's). One rule for the TUI and
|
|
173
|
+
* the GUI. A session on a server runs with the server's credentials, so its
|
|
174
|
+
* pickers list the server's providers: a pick there is remembered only when
|
|
175
|
+
* this computer can run its primary too (a provider only the server has
|
|
176
|
+
* would leave the next local session without a usable model), and the
|
|
177
|
+
* fallbacks this computer can't run are dropped. A pick on This computer is
|
|
178
|
+
* remembered as made. `null`: nothing to remember.
|
|
179
|
+
*/
|
|
180
|
+
function rememberableChain(chain, providerOf, scope) {
|
|
181
|
+
const primary = chain[0];
|
|
182
|
+
if (primary === void 0) return null;
|
|
183
|
+
if (!scope.onServer) return [...chain];
|
|
184
|
+
if (!scope.canRunHere(providerOf(primary))) return null;
|
|
185
|
+
return chain.filter((entry) => scope.canRunHere(providerOf(entry)));
|
|
186
|
+
}
|
|
187
|
+
//#endregion
|
|
188
|
+
//#region src/chat/turn-operations.ts
|
|
189
|
+
/**
|
|
190
|
+
* Fork — keep every turn up to and including `turnId`, then strip any
|
|
191
|
+
* `tool_call` blocks left without a matching `tool_result` in the slice.
|
|
192
|
+
*
|
|
193
|
+
* Semantics:
|
|
194
|
+
* - Include the selected turn ("branch from HERE" mental model — the
|
|
195
|
+
* user wants the selected message to be the latest in the fork).
|
|
196
|
+
* - If the selected turn is an assistant turn with unresolved
|
|
197
|
+
* `tool_call` blocks (their `tool_result`s live in turns AFTER the
|
|
198
|
+
* slice), strip those calls. Otherwise the fork would post an
|
|
199
|
+
* assistant turn with no matching tool results, breaking the next
|
|
200
|
+
* provider call.
|
|
201
|
+
* - Drop turns that become empty (all blocks stripped).
|
|
202
|
+
*
|
|
203
|
+
* Returns `null` when `turnId` doesn't exist in `turns` — caller should
|
|
204
|
+
* surface a "turn not found" error rather than silently no-op.
|
|
205
|
+
*/
|
|
206
|
+
function truncateTurnsAt(turns, turnId) {
|
|
207
|
+
const idx = turns.findIndex((t) => t.id === turnId);
|
|
208
|
+
if (idx === -1) return null;
|
|
209
|
+
return stripOrphanToolBlocks(turns.slice(0, idx + 1));
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Delete — remove the turn with `turnId` and any tool blocks left
|
|
213
|
+
* orphaned by the removal. Returns `null` when `turnId` doesn't exist.
|
|
214
|
+
*
|
|
215
|
+
* Strategy:
|
|
216
|
+
* 1. Drop the target turn.
|
|
217
|
+
* 2. Scan the remaining turns for `tool_call`s without a matching
|
|
218
|
+
* `tool_result` (orphaned by removing the user turn that carried
|
|
219
|
+
* the result), and `tool_result`s without a matching `tool_call`
|
|
220
|
+
* (orphaned by removing the assistant turn that issued the call).
|
|
221
|
+
* Strip both sides.
|
|
222
|
+
* 3. Drop turns whose content is now empty.
|
|
223
|
+
*
|
|
224
|
+
* This guarantees the resulting history is protocol-clean — a follow-up
|
|
225
|
+
* `agent.run()` against the modified session can post turns without the
|
|
226
|
+
* provider rejecting the history.
|
|
227
|
+
*/
|
|
228
|
+
function deleteTurnSafely(turns, turnId) {
|
|
229
|
+
const idx = turns.findIndex((t) => t.id === turnId);
|
|
230
|
+
if (idx === -1) return null;
|
|
231
|
+
return stripOrphanToolBlocks([...turns.slice(0, idx), ...turns.slice(idx + 1)]);
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Walk a turn list and remove any tool blocks whose counterpart is
|
|
235
|
+
* missing. Drops turns left empty. Used by `truncateTurnsAt` (which can
|
|
236
|
+
* leave `tool_call`s orphaned when their results are past the cut) and
|
|
237
|
+
* `deleteTurnSafely` (which can orphan either side of a pair).
|
|
238
|
+
*
|
|
239
|
+
* Pure / total: returns a new array; never throws.
|
|
240
|
+
*/
|
|
241
|
+
function stripOrphanToolBlocks(turns) {
|
|
242
|
+
const callIds = /* @__PURE__ */ new Set();
|
|
243
|
+
const resultIds = /* @__PURE__ */ new Set();
|
|
244
|
+
for (const turn of turns) for (const block of turn.content) if (block.type === "tool_call") callIds.add(block.id);
|
|
245
|
+
else if (block.type === "tool_result") resultIds.add(block.callId);
|
|
246
|
+
const result = [];
|
|
247
|
+
for (const turn of turns) {
|
|
248
|
+
const filtered = [];
|
|
249
|
+
for (const block of turn.content) {
|
|
250
|
+
if (block.type === "tool_call") {
|
|
251
|
+
if (!resultIds.has(block.id)) continue;
|
|
252
|
+
} else if (block.type === "tool_result") {
|
|
253
|
+
if (!callIds.has(block.callId)) continue;
|
|
254
|
+
}
|
|
255
|
+
filtered.push(block);
|
|
256
|
+
}
|
|
257
|
+
if (filtered.length === 0) continue;
|
|
258
|
+
result.push(filtered.length === turn.content.length ? turn : {
|
|
259
|
+
...turn,
|
|
260
|
+
content: filtered
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
return result;
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Replace a turn's text with `newText`, keeping every non-text block (tool
|
|
267
|
+
* calls, tool results, thinking, images) where it was. All text blocks
|
|
268
|
+
* collapse into one, placed where the first text block was; an empty or
|
|
269
|
+
* whitespace-only `newText` removes the text and keeps the rest.
|
|
270
|
+
*
|
|
271
|
+
* Returns `null` when the turn is missing or has no text to edit, so callers
|
|
272
|
+
* can report it. Untouched turns keep their identity (a store can rewrite
|
|
273
|
+
* only the edited row).
|
|
274
|
+
*/
|
|
275
|
+
function replaceTurnTextBlocks(turns, turnId, newText) {
|
|
276
|
+
const idx = turns.findIndex((turn) => turn.id === turnId);
|
|
277
|
+
if (idx === -1) return null;
|
|
278
|
+
const turn = turns[idx];
|
|
279
|
+
const firstTextIdx = turn.content.findIndex((block) => block.type === "text");
|
|
280
|
+
if (firstTextIdx === -1) return null;
|
|
281
|
+
const content = turn.content.filter((block) => block.type !== "text");
|
|
282
|
+
if (newText.trim()) content.splice(Math.min(firstTextIdx, content.length), 0, {
|
|
283
|
+
type: "text",
|
|
284
|
+
text: newText
|
|
285
|
+
});
|
|
286
|
+
const next = turns.slice();
|
|
287
|
+
next[idx] = {
|
|
288
|
+
...turn,
|
|
289
|
+
content
|
|
290
|
+
};
|
|
291
|
+
return next;
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* Serialize a turn's content to a clean text representation suited for
|
|
295
|
+
* the clipboard. Joins text + thinking blocks verbatim; tool calls and
|
|
296
|
+
* tool results get bracketed labels so the user can paste a readable
|
|
297
|
+
* record of what happened without losing structure.
|
|
298
|
+
*
|
|
299
|
+
* Empty turns return `''`.
|
|
300
|
+
*/
|
|
301
|
+
function turnAsText(turn) {
|
|
302
|
+
const parts = [];
|
|
303
|
+
for (const block of turn.content) if (block.type === "text" && block.text.trim()) parts.push(block.text);
|
|
304
|
+
else if (block.type === "thinking" && block.text.trim()) parts.push(`[thinking]\n${block.text}`);
|
|
305
|
+
else if (block.type === "tool_call") parts.push(`[tool call · ${block.name}]\n${stringifyArgs(block.input)}`);
|
|
306
|
+
else if (block.type === "tool_result") parts.push(`[tool result]\n${typeof block.output === "string" ? block.output : JSON.stringify(block.output, null, 2)}`);
|
|
307
|
+
else if (block.type === "compact-summary") parts.push(`[compaction summary · ${block.replacesTurnIds.length} turn${block.replacesTurnIds.length === 1 ? "" : "s"}]\n${block.summary}`);
|
|
308
|
+
return parts.join("\n\n");
|
|
309
|
+
}
|
|
310
|
+
function stringifyArgs(input) {
|
|
311
|
+
try {
|
|
312
|
+
return JSON.stringify(input, null, 2);
|
|
313
|
+
} catch {
|
|
314
|
+
return String(input);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* Count turns before / after the one identified by `turnId` in the
|
|
319
|
+
* given list. Returns `null` when the id is missing. Used to label the
|
|
320
|
+
* turn-details modal with `N before · M after`.
|
|
321
|
+
*/
|
|
322
|
+
function countNeighbors(turnIds, turnId) {
|
|
323
|
+
const idx = turnIds.indexOf(turnId);
|
|
324
|
+
if (idx === -1) return null;
|
|
325
|
+
return {
|
|
326
|
+
before: idx,
|
|
327
|
+
after: turnIds.length - 1 - idx
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
//#endregion
|
|
331
|
+
export { reorderKeyed as _, turnAsText as a, toggleChainEntry as b, chainPositionOf as c, filterChainFallbacks as d, pickChainPrimary as f, rememberableChain as g, providerKeySetChanged as h, truncateTurnsAt as i, chainsEqual as l, positionKeyed as m, deleteTurnSafely as n, buildRunModel as o, pickPrimaryKeyed as p, replaceTurnTextBlocks as r, chainEntryKey as s, countNeighbors as t, chainsEqualKeyed as u, restoreChainFallbacks as v, toggleKeyed as x, sanitizeModelChain as y };
|
|
332
|
+
|
|
333
|
+
//# sourceMappingURL=turn-operations-B8sokwi5.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"turn-operations-B8sokwi5.js","names":[],"sources":["../src/chat/model-chain.ts","../src/chat/turn-operations.ts"],"sourcesContent":["/**\n * Model fallback chains — pure helpers for the ordered multi-model picker.\n *\n * A chain is an ordered list of provider+model pairs: entry 0 is the\n * PRIMARY (drives provider swap, effort, options, context-window display),\n * entries 1+ are run-level fallbacks forwarded to `agent.run` as pinned\n * `{ provider, model }` targets (see `AgentRunOptions.model`).\n *\n * Renderer-agnostic and side-effect free, mirroring `model-catalog.ts`:\n * the TUI picker drives toggling/numbering through these, and the chat\n * host uses them for persistence validation and run-option assembly.\n */\n\nimport type { ProviderKey } from './auth'\n\n/** One provider+model pair in a fallback chain. */\nexport interface ModelChainEntry {\n provider: ProviderKey\n model: string\n}\n\n/** Identity of a chain entry — the pair, not object identity. */\nexport function chainEntryKey(entry: ModelChainEntry): string {\n return `${entry.provider}\\u0000${entry.model}`\n}\n\n// ---------------------------------------------------------------------------\n// Keyed generics — the ONE implementation of each chain edit.\n//\n// Both clients hold chains, but in different shapes: the TUI in\n// `ModelChainEntry` (`provider`/`model`), the GUI in its wire\n// `ModelFallbackRef` (`providerKey`/`modelId`). Before this, the GUI carried\n// five hand-mirrored copies of these functions on its own shape, which is how\n// a picker gesture could diverge between surfaces. The generics take the key\n// function and know nothing about the shape; the `ModelChainEntry` wrappers\n// below keep the existing names for existing callers.\n// ---------------------------------------------------------------------------\n\n/** Toggle `entry`: absent → appended, present → removed. Pure. */\nexport function toggleKeyed<T>(chain: readonly T[], entry: T, keyOf: (e: T) => string): T[] {\n const key = keyOf(entry)\n const idx = chain.findIndex(e => keyOf(e) === key)\n if (idx === -1)\n return [...chain, entry]\n return [...chain.slice(0, idx), ...chain.slice(idx + 1)]\n}\n\n/**\n * Make `entry` the primary (position 0), keeping the rest in order. Inserts\n * when absent, promotes when present; no-op when it already leads.\n *\n * This is `↵` in the picker. It exists because toggling APPENDS: with a chain\n * of `[current]`, toggling a new model produced `[current, new]` — the pick\n * became a fallback and the active model never changed. \"Highlight and ↵\"\n * means \"use this one\", so that gesture promotes; building a fallback list is\n * the secondary gesture (`⇥`) and keeps toggle semantics.\n */\nexport function pickPrimaryKeyed<T>(chain: readonly T[], entry: T, keyOf: (e: T) => string): T[] {\n const key = keyOf(entry)\n return [entry, ...chain.filter(e => keyOf(e) !== key)]\n}\n\n/** 1-based position of `key` in the chain, or `null` when absent. */\nexport function positionKeyed<T>(chain: readonly T[], key: string, keyOf: (e: T) => string): number | null {\n const idx = chain.findIndex(e => keyOf(e) === key)\n return idx === -1 ? null : idx + 1\n}\n\n/** Same entries in the same order. */\nexport function chainsEqualKeyed<T>(a: readonly T[], b: readonly T[], keyOf: (e: T) => string): boolean {\n return a.length === b.length && a.every((e, i) => keyOf(e) === keyOf(b[i]!))\n}\n\n/** Move the entry with `key` by one priority slot; boundary or missing = identity. */\nexport function reorderKeyed<T>(chain: readonly T[], key: string, delta: -1 | 1, keyOf: (e: T) => string): readonly T[] {\n const from = chain.findIndex(e => keyOf(e) === key)\n const to = from + delta\n if (from < 0 || to < 0 || to >= chain.length)\n return chain\n const next = [...chain]\n const [entry] = next.splice(from, 1)\n next.splice(to, 0, entry as T)\n return next\n}\n\n// ---------------------------------------------------------------------------\n// `ModelChainEntry` wrappers — existing public names, unchanged contracts.\n// ---------------------------------------------------------------------------\n\nexport function toggleChainEntry(chain: readonly ModelChainEntry[], entry: ModelChainEntry): ModelChainEntry[] {\n return toggleKeyed(chain, entry, chainEntryKey)\n}\n\nexport function pickChainPrimary(chain: readonly ModelChainEntry[], entry: ModelChainEntry): ModelChainEntry[] {\n return pickPrimaryKeyed(chain, entry, chainEntryKey)\n}\n\n/** 1-based chain position of a provider+model pair, or `null` when not in the chain. */\nexport function chainPositionOf(chain: readonly ModelChainEntry[], provider: ProviderKey, model: string): number | null {\n return positionKeyed(chain, chainEntryKey({ provider, model }), chainEntryKey)\n}\n\nexport function chainsEqual(a: readonly ModelChainEntry[], b: readonly ModelChainEntry[]): boolean {\n return chainsEqualKeyed(a, b, chainEntryKey)\n}\n\n/**\n * Did the SET of provider keys change between two chains? The agent is\n * built with one provider instance per distinct chain key, so a set\n * change requires a session re-activation (rebuild); a pure model /\n * order change within the same providers does not.\n */\nexport function providerKeySetChanged(\n prev: readonly ModelChainEntry[],\n next: readonly ModelChainEntry[],\n): boolean {\n const prevKeys = new Set(prev.map(e => e.provider))\n const nextKeys = new Set(next.map(e => e.provider))\n if (prevKeys.size !== nextKeys.size)\n return true\n for (const k of nextKeys) {\n if (!prevKeys.has(k))\n return true\n }\n return false\n}\n\n/**\n * Assemble the `agent.run` `model` option from a chain.\n *\n * - Single-entry chain → the bare model id string (byte-identical to the\n * pre-chain behavior).\n * - Multi-entry chain → pinned `{ provider, model }` targets, where\n * `provider` is the runtime `Provider.name` resolved via\n * `providerNameFor` (chain entries carry chat-level `ProviderKey`s,\n * which need not equal the instance names the agent loop matches on).\n *\n * Throws only on an empty chain — a programmer error, since chains\n * always carry a primary. Stale or unresolvable entries degrade\n * defensively instead (never throw, never produce an entry the agent\n * would reject):\n * - Entries whose key has no resolvable name (provider not constructed\n * into the current agent) are dropped.\n * - If the PRIMARY itself doesn't resolve, or fewer than two entries\n * survive, fall back to the bare primary model string.\n *\n * `contextWindowFor` (optional) stamps each target with its model's\n * context window from the host catalog, so the loop re-bases the\n * auto-compact trigger when a fallback advances onto it (the host's\n * explicit window is sized for the PRIMARY otherwise).\n */\nexport function buildRunModel(\n chain: readonly ModelChainEntry[],\n providerNameFor: (key: ProviderKey) => string | undefined,\n contextWindowFor?: (entry: ModelChainEntry) => number | undefined,\n): string | Array<{ provider: string, model: string, contextWindow?: number }> {\n const primary = chain[0]\n if (!primary)\n throw new Error('buildRunModel: chain must not be empty')\n if (chain.length === 1 || providerNameFor(primary.provider) === undefined)\n return primary.model\n const resolved: Array<{ provider: string, model: string, contextWindow?: number }> = []\n for (const entry of chain) {\n const name = providerNameFor(entry.provider)\n if (name === undefined)\n continue\n const contextWindow = contextWindowFor?.(entry)\n resolved.push({\n provider: name,\n model: entry.model,\n ...(typeof contextWindow === 'number' && contextWindow > 0 ? { contextWindow } : {}),\n })\n }\n return resolved.length > 1 ? resolved : primary.model\n}\n\n/**\n * Validate a persisted chain read back from `state.json`. The state file\n * is user-editable JSON, so the value can be arbitrarily malformed —\n * return only the well-shaped `{ provider, model }` entries (both\n * non-empty strings), or `[]` for anything else. Never throws.\n */\nexport function sanitizeModelChain(value: unknown): ModelChainEntry[] {\n if (!Array.isArray(value))\n return []\n const entries: ModelChainEntry[] = []\n for (const item of value) {\n if (typeof item !== 'object' || item === null || !('provider' in item) || !('model' in item))\n continue\n const { provider, model } = item\n if (typeof provider === 'string' && provider.length > 0 && typeof model === 'string' && model.length > 0)\n entries.push({ provider, model })\n }\n return entries\n}\n\n/**\n * Restore the fallback tail of a persisted chain for a resolved primary\n * pair. Returns entries 1+ only when the persisted chain's entry 0\n * matches `primary` — a divergent chain belongs to a different selection\n * (e.g. a `--model` launch override) and silently attaching it would\n * surprise. Entries whose provider isn't registered, entries equal to\n * the primary, and exact duplicates drop. Accepts the raw persisted\n * value (`state.json` is user-editable) — shape validation included.\n */\nexport function restoreChainFallbacks(\n saved: unknown,\n primary: ModelChainEntry,\n isRegistered: (key: ProviderKey) => boolean,\n): ModelChainEntry[] {\n const chain = sanitizeModelChain(saved)\n const head = chain[0]\n if (chain.length < 2 || !head || head.provider !== primary.provider || head.model !== primary.model)\n return []\n return filterChainFallbacks(chain.slice(1), primary, isRegistered)\n}\n\n/**\n * Filter candidate fallback entries against a primary pair, preserving\n * picked order: entries whose provider `isAvailable` rejects, entries\n * equal to the primary, and exact duplicates drop. Shared by the\n * picker's apply path (live-auth availability) and persisted-chain\n * restore (registry availability).\n */\nexport function filterChainFallbacks(\n entries: readonly ModelChainEntry[],\n primary: ModelChainEntry,\n isAvailable: (key: ProviderKey) => boolean,\n): ModelChainEntry[] {\n const fallbacks: ModelChainEntry[] = []\n for (const entry of entries) {\n if (!isAvailable(entry.provider))\n continue\n if (entry.provider === primary.provider && entry.model === primary.model)\n continue\n if (fallbacks.some(f => f.provider === entry.provider && f.model === entry.model))\n continue\n fallbacks.push({ provider: entry.provider, model: entry.model })\n }\n return fallbacks\n}\n\n/**\n * What of a model pick a window remembers as its default (`lastModelChain`:\n * the next new session's model, the next launch's). One rule for the TUI and\n * the GUI. A session on a server runs with the server's credentials, so its\n * pickers list the server's providers: a pick there is remembered only when\n * this computer can run its primary too (a provider only the server has\n * would leave the next local session without a usable model), and the\n * fallbacks this computer can't run are dropped. A pick on This computer is\n * remembered as made. `null`: nothing to remember.\n */\nexport function rememberableChain<T>(\n chain: readonly T[],\n providerOf: (entry: T) => string,\n scope: { onServer: boolean, canRunHere: (providerKey: string) => boolean },\n): T[] | null {\n const primary = chain[0]\n if (primary === undefined)\n return null\n if (!scope.onServer)\n return [...chain]\n if (!scope.canRunHere(providerOf(primary)))\n return null\n return chain.filter(entry => scope.canRunHere(providerOf(entry)))\n}\n","/**\n * Pure transforms on `SessionTurn[]` used by the TUI's turn-selection\n * modal actions (fork / delete / copy). Each helper is renderer- and\n * store-agnostic so it composes the same in TUI, SDK, or test code.\n *\n * Tool-call protocol invariant the helpers preserve:\n *\n * Every `tool_call` block emitted by an assistant turn MUST be matched\n * by a `tool_result` block (same `callId`) in a later turn before the\n * next assistant turn. Providers reject histories that violate this —\n * so any operation that mutates the turn list must either keep pairs\n * intact or strip both sides.\n */\n\nimport type { SessionContentBlock, SessionTurn } from '../types'\n\n/**\n * Fork — keep every turn up to and including `turnId`, then strip any\n * `tool_call` blocks left without a matching `tool_result` in the slice.\n *\n * Semantics:\n * - Include the selected turn (\"branch from HERE\" mental model — the\n * user wants the selected message to be the latest in the fork).\n * - If the selected turn is an assistant turn with unresolved\n * `tool_call` blocks (their `tool_result`s live in turns AFTER the\n * slice), strip those calls. Otherwise the fork would post an\n * assistant turn with no matching tool results, breaking the next\n * provider call.\n * - Drop turns that become empty (all blocks stripped).\n *\n * Returns `null` when `turnId` doesn't exist in `turns` — caller should\n * surface a \"turn not found\" error rather than silently no-op.\n */\nexport function truncateTurnsAt(turns: readonly SessionTurn[], turnId: string): SessionTurn[] | null {\n const idx = turns.findIndex(t => t.id === turnId)\n if (idx === -1)\n return null\n const slice = turns.slice(0, idx + 1)\n return stripOrphanToolBlocks(slice)\n}\n\n/**\n * Delete — remove the turn with `turnId` and any tool blocks left\n * orphaned by the removal. Returns `null` when `turnId` doesn't exist.\n *\n * Strategy:\n * 1. Drop the target turn.\n * 2. Scan the remaining turns for `tool_call`s without a matching\n * `tool_result` (orphaned by removing the user turn that carried\n * the result), and `tool_result`s without a matching `tool_call`\n * (orphaned by removing the assistant turn that issued the call).\n * Strip both sides.\n * 3. Drop turns whose content is now empty.\n *\n * This guarantees the resulting history is protocol-clean — a follow-up\n * `agent.run()` against the modified session can post turns without the\n * provider rejecting the history.\n */\nexport function deleteTurnSafely(turns: readonly SessionTurn[], turnId: string): SessionTurn[] | null {\n const idx = turns.findIndex(t => t.id === turnId)\n if (idx === -1)\n return null\n const without = [...turns.slice(0, idx), ...turns.slice(idx + 1)]\n return stripOrphanToolBlocks(without)\n}\n\n/**\n * Walk a turn list and remove any tool blocks whose counterpart is\n * missing. Drops turns left empty. Used by `truncateTurnsAt` (which can\n * leave `tool_call`s orphaned when their results are past the cut) and\n * `deleteTurnSafely` (which can orphan either side of a pair).\n *\n * Pure / total: returns a new array; never throws.\n */\nfunction stripOrphanToolBlocks(turns: readonly SessionTurn[]): SessionTurn[] {\n const callIds = new Set<string>()\n const resultIds = new Set<string>()\n for (const turn of turns) {\n for (const block of turn.content) {\n if (block.type === 'tool_call')\n callIds.add(block.id)\n else if (block.type === 'tool_result')\n resultIds.add(block.callId)\n }\n }\n const result: SessionTurn[] = []\n for (const turn of turns) {\n const filtered: SessionContentBlock[] = []\n for (const block of turn.content) {\n if (block.type === 'tool_call') {\n if (!resultIds.has(block.id))\n continue // call lost its result\n }\n else if (block.type === 'tool_result') {\n if (!callIds.has(block.callId))\n continue // result lost its call\n }\n filtered.push(block)\n }\n if (filtered.length === 0)\n continue // turn is now empty — drop it\n result.push(filtered.length === turn.content.length ? turn : { ...turn, content: filtered })\n }\n return result\n}\n\n/**\n * Replace a turn's text with `newText`, keeping every non-text block (tool\n * calls, tool results, thinking, images) where it was. All text blocks\n * collapse into one, placed where the first text block was; an empty or\n * whitespace-only `newText` removes the text and keeps the rest.\n *\n * Returns `null` when the turn is missing or has no text to edit, so callers\n * can report it. Untouched turns keep their identity (a store can rewrite\n * only the edited row).\n */\nexport function replaceTurnTextBlocks(turns: readonly SessionTurn[], turnId: string, newText: string): SessionTurn[] | null {\n const idx = turns.findIndex(turn => turn.id === turnId)\n if (idx === -1)\n return null\n const turn = turns[idx]!\n const firstTextIdx = turn.content.findIndex(block => block.type === 'text')\n if (firstTextIdx === -1)\n return null\n const content: SessionContentBlock[] = turn.content.filter(block => block.type !== 'text')\n if (newText.trim())\n content.splice(Math.min(firstTextIdx, content.length), 0, { type: 'text', text: newText })\n const next = turns.slice()\n next[idx] = { ...turn, content }\n return next\n}\n\n/**\n * Serialize a turn's content to a clean text representation suited for\n * the clipboard. Joins text + thinking blocks verbatim; tool calls and\n * tool results get bracketed labels so the user can paste a readable\n * record of what happened without losing structure.\n *\n * Empty turns return `''`.\n */\nexport function turnAsText(turn: SessionTurn): string {\n const parts: string[] = []\n for (const block of turn.content) {\n if (block.type === 'text' && block.text.trim())\n parts.push(block.text)\n else if (block.type === 'thinking' && block.text.trim())\n parts.push(`[thinking]\\n${block.text}`)\n else if (block.type === 'tool_call')\n parts.push(`[tool call · ${block.name}]\\n${stringifyArgs(block.input)}`)\n else if (block.type === 'tool_result')\n parts.push(`[tool result]\\n${typeof block.output === 'string' ? block.output : JSON.stringify(block.output, null, 2)}`)\n else if (block.type === 'compact-summary')\n parts.push(`[compaction summary · ${block.replacesTurnIds.length} turn${block.replacesTurnIds.length === 1 ? '' : 's'}]\\n${block.summary}`)\n }\n return parts.join('\\n\\n')\n}\n\nfunction stringifyArgs(input: Record<string, unknown>): string {\n try {\n return JSON.stringify(input, null, 2)\n }\n catch {\n return String(input)\n }\n}\n\n/**\n * Count turns before / after the one identified by `turnId` in the\n * given list. Returns `null` when the id is missing. Used to label the\n * turn-details modal with `N before · M after`.\n */\nexport function countNeighbors(\n turnIds: readonly string[],\n turnId: string,\n): { before: number, after: number } | null {\n const idx = turnIds.indexOf(turnId)\n if (idx === -1)\n return null\n return { before: idx, after: turnIds.length - 1 - idx }\n}\n"],"mappings":"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"}
|