zidane 7.2.4 → 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 -27242
- 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-zVSyo6K1.js +0 -331
- package/dist/ipc-zVSyo6K1.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-h5czzllR.js +0 -1549
- package/dist/shell-path-h5czzllR.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
package/dist/panels-B6gRk4bf.js
DELETED
|
@@ -1,789 +0,0 @@
|
|
|
1
|
-
import { n as estimateTokens } from "./utils-ngQzYzZD.js";
|
|
2
|
-
//#region src/tools/edit-utils.ts
|
|
3
|
-
/**
|
|
4
|
-
* Internal helpers shared between the `edit` and `multi_edit` tools.
|
|
5
|
-
*
|
|
6
|
-
* Not part of the public API — intentionally not re-exported from `tools/index.ts`
|
|
7
|
-
* or the package barrel.
|
|
8
|
-
*/
|
|
9
|
-
/**
|
|
10
|
-
* Count exact (non-overlapping) occurrences of `needle` in `haystack`.
|
|
11
|
-
* Returns 0 for an empty needle — both edit tools reject empty `old_string`
|
|
12
|
-
* up front, so this branch is defensive rather than semantic.
|
|
13
|
-
*/
|
|
14
|
-
function countExactMatches(haystack, needle) {
|
|
15
|
-
if (needle.length === 0) return 0;
|
|
16
|
-
let count = 0;
|
|
17
|
-
let idx = 0;
|
|
18
|
-
while (true) {
|
|
19
|
-
const next = haystack.indexOf(needle, idx);
|
|
20
|
-
if (next === -1) break;
|
|
21
|
-
count++;
|
|
22
|
-
idx = next + needle.length;
|
|
23
|
-
}
|
|
24
|
-
return count;
|
|
25
|
-
}
|
|
26
|
-
/** Map curly quotes (any of the four) to their straight ASCII equivalents. */
|
|
27
|
-
function normalizeQuotes(str) {
|
|
28
|
-
return str.replaceAll("‘", "'").replaceAll("’", "'").replaceAll("“", "\"").replaceAll("”", "\"");
|
|
29
|
-
}
|
|
30
|
-
/**
|
|
31
|
-
* Substitutions Anthropic's API applies to assistant output before the model
|
|
32
|
-
* sees it. The model emits the sanitized form; the file on disk contains the
|
|
33
|
-
* unsanitized form. We undo the substitutions on `old_string` so the search
|
|
34
|
-
* lands on the actual file contents.
|
|
35
|
-
*
|
|
36
|
-
* Verbatim from `claude-code/tools/FileEditTool/utils.ts`.
|
|
37
|
-
*/
|
|
38
|
-
const DESANITIZATIONS = [
|
|
39
|
-
["<fnr>", "<function_results>"],
|
|
40
|
-
["<n>", "<name>"],
|
|
41
|
-
["</n>", "</name>"],
|
|
42
|
-
["<o>", "<output>"],
|
|
43
|
-
["</o>", "</output>"],
|
|
44
|
-
["<e>", "<error>"],
|
|
45
|
-
["</e>", "</error>"],
|
|
46
|
-
["<s>", "<system>"],
|
|
47
|
-
["</s>", "</system>"],
|
|
48
|
-
["<r>", "<result>"],
|
|
49
|
-
["</r>", "</result>"],
|
|
50
|
-
["< META_START >", "<META_START>"],
|
|
51
|
-
["< META_END >", "<META_END>"],
|
|
52
|
-
["< EOT >", "<EOT>"],
|
|
53
|
-
["< META >", "<META>"],
|
|
54
|
-
["< SOS >", "<SOS>"],
|
|
55
|
-
["\n\nH:", "\n\nHuman:"],
|
|
56
|
-
["\n\nA:", "\n\nAssistant:"]
|
|
57
|
-
];
|
|
58
|
-
/**
|
|
59
|
-
* Apply the SDK desanitization table to a string. Exported so the edit tools
|
|
60
|
-
* can apply it to `new_string` whenever `old_string` matched via a
|
|
61
|
-
* desanitize-class fallback — keeps the file's unsanitized form on disk
|
|
62
|
-
* instead of writing the model's abbreviated form back.
|
|
63
|
-
*/
|
|
64
|
-
function desanitize(s) {
|
|
65
|
-
let out = s;
|
|
66
|
-
for (const [from, to] of DESANITIZATIONS) out = out.replaceAll(from, to);
|
|
67
|
-
return out;
|
|
68
|
-
}
|
|
69
|
-
/**
|
|
70
|
-
* Strip line-number prefixes from each line of a needle, used as a recovery
|
|
71
|
-
* fallback when the model pastes a `read_file` chunk verbatim into
|
|
72
|
-
* `old_string` — the on-disk file doesn't carry the metadata prefix.
|
|
73
|
-
*
|
|
74
|
-
* Accepts three separator characters so a model that learned on a different
|
|
75
|
-
* agent stack still works here: `\t` (Claude Code compact, our default),
|
|
76
|
-
* `|`, and `→`. Pattern: optional leading whitespace, 1-9 digits, then one
|
|
77
|
-
* of `\t | →`. The 9-digit ceiling covers files up to ~1B lines without
|
|
78
|
-
* overshooting into legitimate `\d{N}<sep>` content like Markdown table
|
|
79
|
-
* cells with long numeric IDs.
|
|
80
|
-
*/
|
|
81
|
-
const LINE_NUMBER_PREFIX_RE = /^[ \t]*\d{1,9}[\t|\u2192]/gm;
|
|
82
|
-
function stripLineNumberPrefixes(s) {
|
|
83
|
-
return s.replace(LINE_NUMBER_PREFIX_RE, "");
|
|
84
|
-
}
|
|
85
|
-
/**
|
|
86
|
-
* Search `target` in `normFile` and slice the matching span out of the
|
|
87
|
-
* original `haystack`, counting all non-overlapping occurrences. `normFile`
|
|
88
|
-
* is the haystack with whatever transform (quotes / desanitize / combined)
|
|
89
|
-
* was applied to make the indices align — slicing the original haystack
|
|
90
|
-
* preserves the file's actual typography so `replace_all` writes back the
|
|
91
|
-
* file's form, not the model's.
|
|
92
|
-
*
|
|
93
|
-
* Pre-condition: `normFile.length === haystack.length` (every transform
|
|
94
|
-
* we use is one-to-one). Returns null on miss.
|
|
95
|
-
*/
|
|
96
|
-
function locateAndCount(haystack, normFile, target, via) {
|
|
97
|
-
const idx = normFile.indexOf(target);
|
|
98
|
-
if (idx === -1) return null;
|
|
99
|
-
const actual = haystack.slice(idx, idx + target.length);
|
|
100
|
-
let occ = 0;
|
|
101
|
-
let cursor = 0;
|
|
102
|
-
while (true) {
|
|
103
|
-
const next = normFile.indexOf(target, cursor);
|
|
104
|
-
if (next === -1) break;
|
|
105
|
-
occ++;
|
|
106
|
-
cursor = next + target.length;
|
|
107
|
-
}
|
|
108
|
-
return {
|
|
109
|
-
actual,
|
|
110
|
-
occurrences: occ,
|
|
111
|
-
via
|
|
112
|
-
};
|
|
113
|
-
}
|
|
114
|
-
function resolveOldString(haystack, needle) {
|
|
115
|
-
const exact = countExactMatches(haystack, needle);
|
|
116
|
-
if (exact > 0) return {
|
|
117
|
-
actual: needle,
|
|
118
|
-
occurrences: exact,
|
|
119
|
-
via: "exact"
|
|
120
|
-
};
|
|
121
|
-
const normNeedle = normalizeQuotes(needle);
|
|
122
|
-
const normFile = normalizeQuotes(haystack);
|
|
123
|
-
if (normNeedle !== needle || normFile !== haystack) {
|
|
124
|
-
const m = locateAndCount(haystack, normFile, normNeedle, "quotes");
|
|
125
|
-
if (m) return m;
|
|
126
|
-
}
|
|
127
|
-
const desan = desanitize(needle);
|
|
128
|
-
if (desan !== needle) {
|
|
129
|
-
const desanCount = countExactMatches(haystack, desan);
|
|
130
|
-
if (desanCount === 1) return {
|
|
131
|
-
actual: desan,
|
|
132
|
-
occurrences: desanCount,
|
|
133
|
-
via: "desanitize"
|
|
134
|
-
};
|
|
135
|
-
}
|
|
136
|
-
const combo = desanitize(normNeedle);
|
|
137
|
-
if (combo !== needle) {
|
|
138
|
-
const m = locateAndCount(haystack, normFile, combo, "quotes+desanitize");
|
|
139
|
-
if (m && m.occurrences === 1) return m;
|
|
140
|
-
}
|
|
141
|
-
const stripped = stripLineNumberPrefixes(needle);
|
|
142
|
-
if (stripped !== needle && stripped.trim().length > 0) {
|
|
143
|
-
const count = countExactMatches(haystack, stripped);
|
|
144
|
-
if (count > 0) return {
|
|
145
|
-
actual: stripped,
|
|
146
|
-
occurrences: count,
|
|
147
|
-
via: "line-numbers"
|
|
148
|
-
};
|
|
149
|
-
const strippedNorm = normalizeQuotes(stripped);
|
|
150
|
-
if (strippedNorm !== stripped || normFile !== haystack) {
|
|
151
|
-
const m = locateAndCount(haystack, normFile, strippedNorm, "quotes+line-numbers");
|
|
152
|
-
if (m) return m;
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
return null;
|
|
156
|
-
}
|
|
157
|
-
/**
|
|
158
|
-
* Short human-readable label for a recovery path, used by `edit` /
|
|
159
|
-
* `multi_edit` to flag non-exact matches in their result messages — when a
|
|
160
|
-
* fallback mistargets, the model (and the user reading the transcript) can
|
|
161
|
-
* see WHICH transform fired instead of silently trusting the edit.
|
|
162
|
-
*/
|
|
163
|
-
function describeVia(via) {
|
|
164
|
-
switch (via) {
|
|
165
|
-
case "exact": return "exact match";
|
|
166
|
-
case "quotes": return "curly-quote normalization";
|
|
167
|
-
case "desanitize": return "sanitization recovery (e.g. <n> → <name>)";
|
|
168
|
-
case "quotes+desanitize": return "sanitization recovery + curly-quote normalization";
|
|
169
|
-
case "line-numbers": return "line-number-prefix stripping";
|
|
170
|
-
case "quotes+line-numbers": return "line-number-prefix stripping + curly-quote normalization";
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
/**
|
|
174
|
-
* Apply the same recovery transforms used to find `old_string` to
|
|
175
|
-
* `new_string`, so the file gets back its native form: desanitize when
|
|
176
|
-
* the model emitted `<n>` for `<name>`, strip line-number prefixes when
|
|
177
|
-
* the match required them, then re-curlify when the match required
|
|
178
|
-
* quote normalization. Shared between `edit` and `multi_edit`.
|
|
179
|
-
*/
|
|
180
|
-
function styleReplacementForVia(replacement, via, actual) {
|
|
181
|
-
let out = replacement;
|
|
182
|
-
if (via === "desanitize" || via === "quotes+desanitize") out = desanitize(out);
|
|
183
|
-
if (via === "line-numbers" || via === "quotes+line-numbers") out = stripLineNumberPrefixes(out);
|
|
184
|
-
if (via === "quotes" || via === "quotes+desanitize" || via === "quotes+line-numbers") out = preserveQuoteStyle(actual, out);
|
|
185
|
-
return out;
|
|
186
|
-
}
|
|
187
|
-
/**
|
|
188
|
-
* When `old_string` matched via curly-quote normalization, re-style
|
|
189
|
-
* `new_string` so the file's typography is preserved across the edit.
|
|
190
|
-
* Detects whether the matched file region had curly singles, doubles, or
|
|
191
|
-
* both, and applies the matching curlification to the replacement.
|
|
192
|
-
*
|
|
193
|
-
* Apostrophes in contractions (`don't`, `it's`) get the right-single curly
|
|
194
|
-
* quote regardless of opening context — that's the canonical typographer's
|
|
195
|
-
* convention for English. Other quotes use a simple
|
|
196
|
-
* preceded-by-whitespace-or-opening-punctuation heuristic.
|
|
197
|
-
*/
|
|
198
|
-
function preserveQuoteStyle(actual, replacement) {
|
|
199
|
-
const hasDouble = actual.includes("“") || actual.includes("”");
|
|
200
|
-
const hasSingle = actual.includes("‘") || actual.includes("’");
|
|
201
|
-
if (!hasDouble && !hasSingle) return replacement;
|
|
202
|
-
let out = replacement;
|
|
203
|
-
if (hasDouble) out = applyCurly(out, "\"", "“", "”", false);
|
|
204
|
-
if (hasSingle) out = applyCurly(out, "'", "‘", "’", true);
|
|
205
|
-
return out;
|
|
206
|
-
}
|
|
207
|
-
function applyCurly(s, straight, left, right, contractionAware) {
|
|
208
|
-
const chars = [...s];
|
|
209
|
-
const result = [];
|
|
210
|
-
for (let i = 0; i < chars.length; i++) {
|
|
211
|
-
if (chars[i] !== straight) {
|
|
212
|
-
result.push(chars[i]);
|
|
213
|
-
continue;
|
|
214
|
-
}
|
|
215
|
-
if (contractionAware) {
|
|
216
|
-
const prev = i > 0 ? chars[i - 1] : "";
|
|
217
|
-
const next = i < chars.length - 1 ? chars[i + 1] : "";
|
|
218
|
-
if (/\p{L}/u.test(prev) && /\p{L}/u.test(next)) {
|
|
219
|
-
result.push(right);
|
|
220
|
-
continue;
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
result.push(isOpeningContext(chars, i) ? left : right);
|
|
224
|
-
}
|
|
225
|
-
return result.join("");
|
|
226
|
-
}
|
|
227
|
-
function isOpeningContext(chars, i) {
|
|
228
|
-
if (i === 0) return true;
|
|
229
|
-
const prev = chars[i - 1];
|
|
230
|
-
return prev === " " || prev === " " || prev === "\n" || prev === "\r" || prev === "(" || prev === "[" || prev === "{" || prev === "—" || prev === "–";
|
|
231
|
-
}
|
|
232
|
-
//#endregion
|
|
233
|
-
//#region src/chat/context-breakdown.ts
|
|
234
|
-
const LABELS = {
|
|
235
|
-
systemPrompt: "System prompt",
|
|
236
|
-
rules: "Rules (AGENTS.md)",
|
|
237
|
-
tools: "Tool definitions",
|
|
238
|
-
mcpTools: "MCP tools",
|
|
239
|
-
mcpInstructions: "MCP instructions",
|
|
240
|
-
skills: "Skills",
|
|
241
|
-
subagentDefs: "Subagent definitions",
|
|
242
|
-
conversation: "Conversation",
|
|
243
|
-
mcpToolsDeferred: "MCP tools (deferred)",
|
|
244
|
-
toolsDeferred: "System tools (deferred)",
|
|
245
|
-
autocompactBuffer: "Autocompact buffer",
|
|
246
|
-
freeSpace: "Free space"
|
|
247
|
-
};
|
|
248
|
-
/** Sum the heuristic token sizes of a list of strings. */
|
|
249
|
-
function sumEstimate(parts) {
|
|
250
|
-
let total = 0;
|
|
251
|
-
for (const p of parts) total += estimateTokens(p);
|
|
252
|
-
return total;
|
|
253
|
-
}
|
|
254
|
-
function mcpGroupTokens(group) {
|
|
255
|
-
const items = group.tools.map((t) => ({
|
|
256
|
-
id: `${group.server}:${t.name}`,
|
|
257
|
-
label: t.name,
|
|
258
|
-
tokens: estimateTokens(t.json),
|
|
259
|
-
estimated: true,
|
|
260
|
-
...t.description ? { description: t.description } : {},
|
|
261
|
-
group: group.server
|
|
262
|
-
}));
|
|
263
|
-
let total = 0;
|
|
264
|
-
for (const it of items) total += it.tokens;
|
|
265
|
-
return {
|
|
266
|
-
total,
|
|
267
|
-
items
|
|
268
|
-
};
|
|
269
|
-
}
|
|
270
|
-
/**
|
|
271
|
-
* Shape a {@link ContextSnapshot} into a render-ready {@link ContextBreakdown}.
|
|
272
|
-
*
|
|
273
|
-
* Live categories (system prompt, tools, MCP tools/instructions, skills,
|
|
274
|
-
* memory, subagent defs, conversation) sum to `snapshot.used` — `conversation`
|
|
275
|
-
* absorbs the remainder so the bar matches the provider-reported total exactly.
|
|
276
|
-
* Deferred + autocompact + free-space buckets follow.
|
|
277
|
-
*
|
|
278
|
-
* When `snapshot.exact` carries provider counts, the matching categories use
|
|
279
|
-
* them (system, tools) and drop their `estimated` flag; everything else stays
|
|
280
|
-
* on the heuristic.
|
|
281
|
-
*/
|
|
282
|
-
function buildContextBreakdown(snapshot) {
|
|
283
|
-
const exact = snapshot.exact;
|
|
284
|
-
const systemExact = typeof exact?.system === "number";
|
|
285
|
-
const rulesTokens = snapshot.rulesBlock ? estimateTokens(snapshot.rulesBlock) : 0;
|
|
286
|
-
const rulesItems = (snapshot.rulesFiles ?? []).map((f) => ({
|
|
287
|
-
id: f.path,
|
|
288
|
-
label: f.path,
|
|
289
|
-
tokens: 0,
|
|
290
|
-
estimated: false
|
|
291
|
-
}));
|
|
292
|
-
const skillsTokens = snapshot.skillsCatalog ? estimateTokens(snapshot.skillsCatalog) : 0;
|
|
293
|
-
const mcpInstructionsTokens = snapshot.mcpInstructions ? estimateTokens(snapshot.mcpInstructions) : 0;
|
|
294
|
-
const subagentTokens = snapshot.subagentDefs ? estimateTokens(snapshot.subagentDefs) : 0;
|
|
295
|
-
const embeddedSubsections = rulesTokens + skillsTokens + mcpInstructionsTokens + subagentTokens;
|
|
296
|
-
const systemTotal = systemExact ? exact.system : estimateTokens(snapshot.system);
|
|
297
|
-
const baseSystemTokens = Math.max(0, systemTotal - embeddedSubsections);
|
|
298
|
-
const nativeToolsEst = sumEstimate(snapshot.toolsJson);
|
|
299
|
-
const mcpDisclosed = snapshot.mcpGroups.map(mcpGroupTokens);
|
|
300
|
-
const mcpToolsEst = mcpDisclosed.reduce((a, g) => a + g.total, 0);
|
|
301
|
-
let nativeToolsTokens = nativeToolsEst;
|
|
302
|
-
let mcpToolsTokens = mcpToolsEst;
|
|
303
|
-
let toolsEstimated = true;
|
|
304
|
-
if (systemExact && typeof exact?.systemAndTools === "number") {
|
|
305
|
-
const exactToolsTotal = Math.max(0, exact.systemAndTools - exact.system);
|
|
306
|
-
const estTotal = nativeToolsEst + mcpToolsEst;
|
|
307
|
-
if (estTotal > 0) {
|
|
308
|
-
nativeToolsTokens = Math.round(exactToolsTotal * (nativeToolsEst / estTotal));
|
|
309
|
-
mcpToolsTokens = exactToolsTotal - nativeToolsTokens;
|
|
310
|
-
} else {
|
|
311
|
-
nativeToolsTokens = exactToolsTotal;
|
|
312
|
-
mcpToolsTokens = 0;
|
|
313
|
-
}
|
|
314
|
-
toolsEstimated = false;
|
|
315
|
-
}
|
|
316
|
-
const live = [];
|
|
317
|
-
const push = (id, tokens, estimated, items) => {
|
|
318
|
-
if (tokens <= 0 && !items?.length) return;
|
|
319
|
-
live.push({
|
|
320
|
-
id,
|
|
321
|
-
label: LABELS[id],
|
|
322
|
-
tokens: Math.max(0, tokens),
|
|
323
|
-
estimated,
|
|
324
|
-
...items?.length ? { items } : {}
|
|
325
|
-
});
|
|
326
|
-
};
|
|
327
|
-
push("systemPrompt", baseSystemTokens, !systemExact);
|
|
328
|
-
push("rules", rulesTokens, true, rulesItems);
|
|
329
|
-
push("skills", skillsTokens, true);
|
|
330
|
-
push("mcpInstructions", mcpInstructionsTokens, true);
|
|
331
|
-
push("subagentDefs", subagentTokens, true);
|
|
332
|
-
push("tools", nativeToolsTokens, toolsEstimated, snapshot.toolItems?.map((t) => ({
|
|
333
|
-
id: t.name,
|
|
334
|
-
label: t.name,
|
|
335
|
-
tokens: estimateTokens(t.json),
|
|
336
|
-
estimated: true,
|
|
337
|
-
...t.description ? { description: t.description } : {}
|
|
338
|
-
})));
|
|
339
|
-
push("mcpTools", mcpToolsTokens, toolsEstimated, mcpDisclosed.flatMap((g) => g.items));
|
|
340
|
-
const accountedStatic = live.reduce((a, c) => a + c.tokens, 0);
|
|
341
|
-
push("conversation", Math.max(0, snapshot.used - accountedStatic), !(systemExact && !toolsEstimated));
|
|
342
|
-
const deferred = [];
|
|
343
|
-
const deferredNativeTools = sumEstimate(snapshot.deferredToolsJson);
|
|
344
|
-
if (deferredNativeTools > 0) deferred.push({
|
|
345
|
-
id: "toolsDeferred",
|
|
346
|
-
label: LABELS.toolsDeferred,
|
|
347
|
-
tokens: deferredNativeTools,
|
|
348
|
-
estimated: true,
|
|
349
|
-
deferred: true
|
|
350
|
-
});
|
|
351
|
-
const deferredMcp = snapshot.deferredMcpGroups.map(mcpGroupTokens);
|
|
352
|
-
const deferredMcpTotal = deferredMcp.reduce((a, g) => a + g.total, 0);
|
|
353
|
-
if (deferredMcpTotal > 0) deferred.push({
|
|
354
|
-
id: "mcpToolsDeferred",
|
|
355
|
-
label: LABELS.mcpToolsDeferred,
|
|
356
|
-
tokens: deferredMcpTotal,
|
|
357
|
-
estimated: true,
|
|
358
|
-
deferred: true,
|
|
359
|
-
items: deferredMcp.flatMap((g) => g.items)
|
|
360
|
-
});
|
|
361
|
-
if (snapshot.autocompactBuffer > 0) deferred.push({
|
|
362
|
-
id: "autocompactBuffer",
|
|
363
|
-
label: LABELS.autocompactBuffer,
|
|
364
|
-
tokens: snapshot.autocompactBuffer,
|
|
365
|
-
estimated: false,
|
|
366
|
-
deferred: true
|
|
367
|
-
});
|
|
368
|
-
const free = Math.max(0, snapshot.effectiveWindow - snapshot.used);
|
|
369
|
-
deferred.push({
|
|
370
|
-
id: "freeSpace",
|
|
371
|
-
label: LABELS.freeSpace,
|
|
372
|
-
tokens: free,
|
|
373
|
-
estimated: false,
|
|
374
|
-
deferred: true
|
|
375
|
-
});
|
|
376
|
-
const categories = [...live, ...deferred];
|
|
377
|
-
const hasEstimates = live.some((c) => c.estimated && c.tokens > 0);
|
|
378
|
-
const fraction = snapshot.effectiveWindow > 0 ? Math.max(0, Math.min(1, snapshot.used / snapshot.effectiveWindow)) : 0;
|
|
379
|
-
return {
|
|
380
|
-
modelId: snapshot.modelId,
|
|
381
|
-
used: snapshot.used,
|
|
382
|
-
effectiveWindow: snapshot.effectiveWindow,
|
|
383
|
-
fraction,
|
|
384
|
-
categories,
|
|
385
|
-
hasEstimates,
|
|
386
|
-
...snapshot.usage ? { usage: snapshot.usage } : {},
|
|
387
|
-
...snapshot.extensionSections?.length ? { extensionSections: snapshot.extensionSections } : {},
|
|
388
|
-
...snapshot.activeSkills?.length ? { activeSkills: snapshot.activeSkills } : {}
|
|
389
|
-
};
|
|
390
|
-
}
|
|
391
|
-
//#endregion
|
|
392
|
-
//#region src/chat/context-segments.ts
|
|
393
|
-
/**
|
|
394
|
-
* Context segments — pure transforms.
|
|
395
|
-
*
|
|
396
|
-
* Sibling to `context-breakdown.ts`: where that module answers "how many
|
|
397
|
-
* tokens is each part of my context", this one answers "what IS each part,
|
|
398
|
-
* and where did it come from". It turns the same assembled-prompt pieces into
|
|
399
|
-
* a flat list of {@link ContextSegment}s carrying the actual TEXT plus its
|
|
400
|
-
* provenance, so a UI can list every chunk loaded by default in a session,
|
|
401
|
-
* let the user read it, and open the file behind it when there is one.
|
|
402
|
-
*
|
|
403
|
-
* No React, no node — a browser-context renderer imports these via
|
|
404
|
-
* `zidane/chat/pure`.
|
|
405
|
-
*
|
|
406
|
-
* Provenance is honest about what can and can't be opened:
|
|
407
|
-
* - `'file'` — a real path on disk (AGENTS.md / CLAUDE.md / ruler md).
|
|
408
|
-
* The only origin that carries `path`, hence the only one
|
|
409
|
-
* a host can hand to `$EDITOR`.
|
|
410
|
-
* - `'built-in'` — compiled into the binary (base doctrine, subagent defs).
|
|
411
|
-
* - `'generated'` — assembled at prompt time from discovered state (the
|
|
412
|
-
* skills catalog is rendered from the skill manifests).
|
|
413
|
-
* - `'mcp'` — served by a remote MCP server at connect time.
|
|
414
|
-
*/
|
|
415
|
-
/**
|
|
416
|
-
* Remove the first occurrence of `part` from `whole`, collapsing the blank-line
|
|
417
|
-
* run left AT THE JOIN.
|
|
418
|
-
*
|
|
419
|
-
* Used to carve the rules block out of the base system so the "System prompt"
|
|
420
|
-
* segment reports only doctrine + env. Substring-based because that's the
|
|
421
|
-
* contract the assembly documents (`rulesBlock` IS a substring of
|
|
422
|
-
* `baseSystem`); a miss leaves `whole` untouched, which degrades to
|
|
423
|
-
* over-reporting the base row rather than dropping text on the floor.
|
|
424
|
-
*
|
|
425
|
-
* The collapse is deliberately scoped to the seam. An earlier version ran
|
|
426
|
-
* `/\n{3,}/g` over the whole result, which rewrote blank-line runs ANYWHERE in
|
|
427
|
-
* the doctrine — and this tab exists precisely so the user can read what is in
|
|
428
|
-
* context, not a reflowed approximation of it. Interior bytes now survive
|
|
429
|
-
* verbatim; only the newlines that met when `part` was excised are normalized,
|
|
430
|
-
* plus a `trim()` so a segment can't open or close on blank lines.
|
|
431
|
-
*/
|
|
432
|
-
function removeFirst(whole, part) {
|
|
433
|
-
if (!part) return whole;
|
|
434
|
-
const at = whole.indexOf(part);
|
|
435
|
-
if (at < 0) return whole;
|
|
436
|
-
const before = whole.slice(0, at);
|
|
437
|
-
const after = whole.slice(at + part.length);
|
|
438
|
-
const trailing = /\n*$/.exec(before)?.[0] ?? "";
|
|
439
|
-
const leading = /^\n*/.exec(after)?.[0] ?? "";
|
|
440
|
-
const seam = trailing.length + leading.length >= 2 ? "\n\n" : `${trailing}${leading}`;
|
|
441
|
-
return `${before.slice(0, before.length - trailing.length)}${seam}${after.slice(leading.length)}`.trim();
|
|
442
|
-
}
|
|
443
|
-
/**
|
|
444
|
-
* Best-effort display name for an instruction file: its basename, with the
|
|
445
|
-
* parent directory prefixed when the basename alone would be ambiguous
|
|
446
|
-
* (`AGENTS.md` appears at up to four paths per scope). Path-separator handling
|
|
447
|
-
* covers both POSIX and Windows so this stays node-free.
|
|
448
|
-
*/
|
|
449
|
-
function fileLabel(path) {
|
|
450
|
-
const parts = path.split(/[/\\]/).filter(Boolean);
|
|
451
|
-
const base = parts.at(-1) ?? path;
|
|
452
|
-
const parent = parts.at(-2);
|
|
453
|
-
return parent?.startsWith(".") ? `${parent}/${base}` : base;
|
|
454
|
-
}
|
|
455
|
-
/**
|
|
456
|
-
* Shape assembled-prompt pieces into a flat, render-ready segment list.
|
|
457
|
-
*
|
|
458
|
-
* Order is prompt order — base doctrine, then instruction files (broadest
|
|
459
|
-
* scope first, as `discoverAgentsMd` returns them), then the appended
|
|
460
|
-
* catalogs. Empty / whitespace-only pieces are dropped so the list never
|
|
461
|
-
* shows a zero-byte row.
|
|
462
|
-
*/
|
|
463
|
-
function buildContextSegments(input) {
|
|
464
|
-
const segments = [];
|
|
465
|
-
const push = (seg) => {
|
|
466
|
-
if (!seg.text.trim()) return;
|
|
467
|
-
segments.push({
|
|
468
|
-
...seg,
|
|
469
|
-
tokens: estimateTokens(seg.text)
|
|
470
|
-
});
|
|
471
|
-
};
|
|
472
|
-
const base = input.baseSystem ?? input.system ?? "";
|
|
473
|
-
const overridden = input.systemPath !== void 0;
|
|
474
|
-
push({
|
|
475
|
-
id: "system",
|
|
476
|
-
label: "System prompt",
|
|
477
|
-
origin: overridden ? "file" : "built-in",
|
|
478
|
-
detail: overridden ? "SYSTEM.md override + environment" : "doctrine + environment",
|
|
479
|
-
text: input.rulesBlock ? removeFirst(base, input.rulesBlock) : base,
|
|
480
|
-
...input.systemPath !== void 0 ? { path: input.systemPath } : {}
|
|
481
|
-
});
|
|
482
|
-
for (const file of input.rulesFiles ?? []) push({
|
|
483
|
-
id: `rules:${file.path}`,
|
|
484
|
-
label: fileLabel(file.path),
|
|
485
|
-
origin: "file",
|
|
486
|
-
...file.source ? { detail: file.source } : {},
|
|
487
|
-
text: file.contents,
|
|
488
|
-
path: file.path
|
|
489
|
-
});
|
|
490
|
-
push({
|
|
491
|
-
id: "skills",
|
|
492
|
-
label: "Skills catalog",
|
|
493
|
-
origin: "generated",
|
|
494
|
-
detail: "name + description per skill (bodies load on activation)",
|
|
495
|
-
text: input.skillsCatalog ?? ""
|
|
496
|
-
});
|
|
497
|
-
push({
|
|
498
|
-
id: "mcp-instructions",
|
|
499
|
-
label: "MCP instructions",
|
|
500
|
-
origin: "mcp",
|
|
501
|
-
detail: "served by the connected servers",
|
|
502
|
-
text: input.mcpInstructions ?? ""
|
|
503
|
-
});
|
|
504
|
-
push({
|
|
505
|
-
id: "subagent-defs",
|
|
506
|
-
label: "Subagent definitions",
|
|
507
|
-
origin: "built-in",
|
|
508
|
-
text: input.subagentDefs ?? ""
|
|
509
|
-
});
|
|
510
|
-
return segments;
|
|
511
|
-
}
|
|
512
|
-
//#endregion
|
|
513
|
-
//#region src/chat/cred-keys.ts
|
|
514
|
-
/**
|
|
515
|
-
* Credential-file key arithmetic, split from `./credentials` so the rules can
|
|
516
|
-
* be enforced where credentials themselves must not be pulled in.
|
|
517
|
-
*
|
|
518
|
-
* `./credentials` reaches the provider registry (and through it the pi-ai
|
|
519
|
-
* factories) for `credKeyOf`; the extension loader — an edge entrypoint that
|
|
520
|
-
* validates descriptor keys at registration time — must stay clear of that
|
|
521
|
-
* graph. This module is string arithmetic with no imports.
|
|
522
|
-
*/
|
|
523
|
-
/**
|
|
524
|
-
* Separator between a provider's canonical key and a slot qualifier. Every
|
|
525
|
-
* non-canonical slot (`#alt`, `#account:N`) starts with it, so the character is
|
|
526
|
-
* reserved in descriptor credential keys outright.
|
|
527
|
-
*/
|
|
528
|
-
const CRED_KEY_SLOT_SEPARATOR = "#";
|
|
529
|
-
/**
|
|
530
|
-
* Reserved suffix marking a provider's SECOND credential slot.
|
|
531
|
-
*
|
|
532
|
-
* Not usable as (or as the tail of) a descriptor's credential key: `foo#alt`
|
|
533
|
-
* holds `foo`'s alternate credential, so a provider claiming that name would
|
|
534
|
-
* share storage with it.
|
|
535
|
-
*/
|
|
536
|
-
const ALTERNATE_CRED_KEY_SUFFIX = "#alt";
|
|
537
|
-
/**
|
|
538
|
-
* Reserved infix marking one of a provider's ADDITIONAL OAuth accounts:
|
|
539
|
-
* `foo#account:1`, `foo#account:2`, …
|
|
540
|
-
*/
|
|
541
|
-
const ACCOUNT_CRED_KEY_INFIX = "#account:";
|
|
542
|
-
/**
|
|
543
|
-
* File key holding a provider's second credential, when it has one of each kind.
|
|
544
|
-
*
|
|
545
|
-
* The canonical key always holds the credential the user prefers; this sibling
|
|
546
|
-
* holds the other. That one invariant is what makes preference selection free:
|
|
547
|
-
* every existing reader (`applyApiKeyEnv`, the harness provider factories)
|
|
548
|
-
* already resolves the canonical key, so "switch priority" is just moving two
|
|
549
|
-
* objects between two keys — no precedence flag to interpret, no resolution
|
|
550
|
-
* order to keep in sync across layers.
|
|
551
|
-
*
|
|
552
|
-
* A sibling key rather than a nested field because the canonical entry gets
|
|
553
|
-
* REPLACED wholesale on token refresh; anything nested inside it would be
|
|
554
|
-
* dropped by the next rotation. And older zidane versions look credentials up
|
|
555
|
-
* by `credKeyOf`, so a suffixed key is simply invisible to them — they read the
|
|
556
|
-
* preferred credential and behave exactly as before, which is why this needs no
|
|
557
|
-
* migration or schema version.
|
|
558
|
-
*/
|
|
559
|
-
function alternateCredKey(fileKey) {
|
|
560
|
-
return `${fileKey}${ALTERNATE_CRED_KEY_SUFFIX}`;
|
|
561
|
-
}
|
|
562
|
-
/**
|
|
563
|
-
* File key holding one of a provider's non-active OAuth accounts.
|
|
564
|
-
*
|
|
565
|
-
* Same sibling-key reasoning as {@link alternateCredKey}: the canonical key is
|
|
566
|
-
* the active one, so a provider with three OAuth grants stores the active one
|
|
567
|
-
* canonically and the other two under `#account:N`. `#alt` stays dedicated to
|
|
568
|
-
* the other-kind (API key) alternate so files written by builds that predate
|
|
569
|
-
* multi-account keep meaning the same thing.
|
|
570
|
-
*/
|
|
571
|
-
function accountCredKey(fileKey, n) {
|
|
572
|
-
return `${fileKey}${ACCOUNT_CRED_KEY_INFIX}${n}`;
|
|
573
|
-
}
|
|
574
|
-
/** True when `key` is one of `fileKey`'s `#account:N` slots. */
|
|
575
|
-
function isAccountCredKey(fileKey, key) {
|
|
576
|
-
const prefix = `${fileKey}${ACCOUNT_CRED_KEY_INFIX}`;
|
|
577
|
-
return key.startsWith(prefix) && /^\d+$/.test(key.slice(prefix.length));
|
|
578
|
-
}
|
|
579
|
-
/**
|
|
580
|
-
* Smallest `#account:N` key of `fileKey` not present in `existing`.
|
|
581
|
-
*
|
|
582
|
-
* Deterministic rather than random so a file hand-edited or written by two
|
|
583
|
-
* processes in sequence stays readable; the write lock keeps it collision-free.
|
|
584
|
-
*/
|
|
585
|
-
function nextAccountCredKey(fileKey, existing) {
|
|
586
|
-
const taken = new Set(existing);
|
|
587
|
-
for (let n = 1;; n++) {
|
|
588
|
-
const key = accountCredKey(fileKey, n);
|
|
589
|
-
if (!taken.has(key)) return key;
|
|
590
|
-
}
|
|
591
|
-
}
|
|
592
|
-
/**
|
|
593
|
-
* Name shown for an OAuth account that was never given one.
|
|
594
|
-
*
|
|
595
|
-
* Also what a first OAuth login is stored under, so a second account has
|
|
596
|
-
* something to be told apart from. Pre-multi-account files hold unnamed
|
|
597
|
-
* grants; {@link oauthAccountLabel} makes them read the same.
|
|
598
|
-
*/
|
|
599
|
-
const DEFAULT_OAUTH_ACCOUNT_LABEL = "Default";
|
|
600
|
-
/** Trimmed user-given account name, or {@link DEFAULT_OAUTH_ACCOUNT_LABEL}. */
|
|
601
|
-
function oauthAccountLabel(credential) {
|
|
602
|
-
return (typeof credential.label === "string" ? credential.label.trim() : "") || "Default";
|
|
603
|
-
}
|
|
604
|
-
/**
|
|
605
|
-
* True when a key claims a reserved slot namespace.
|
|
606
|
-
*
|
|
607
|
-
* Built-in keys are plain identifiers (`anthropic`, `openai-codex`), but
|
|
608
|
-
* `ProviderDescriptor.key` / `credentialFileKey` are open strings — so the
|
|
609
|
-
* reservation is checked, not assumed.
|
|
610
|
-
*/
|
|
611
|
-
function isReservedCredKey(fileKey) {
|
|
612
|
-
return fileKey.includes("#");
|
|
613
|
-
}
|
|
614
|
-
//#endregion
|
|
615
|
-
//#region src/extensions/panels.ts
|
|
616
|
-
/** Caps applied before content crosses IPC or reaches a renderer. */
|
|
617
|
-
const PANEL_CONTENT_LIMITS = {
|
|
618
|
-
sections: 32,
|
|
619
|
-
itemsPerSection: 200,
|
|
620
|
-
actions: 8,
|
|
621
|
-
/** Per string field. */
|
|
622
|
-
textChars: 2e4,
|
|
623
|
-
/** Whole payload, JSON-serialised. */
|
|
624
|
-
bytes: 512 * 1024
|
|
625
|
-
};
|
|
626
|
-
function str(v, max = PANEL_CONTENT_LIMITS.textChars) {
|
|
627
|
-
return typeof v === "string" ? v.length > max ? `${v.slice(0, max - 1)}…` : v : void 0;
|
|
628
|
-
}
|
|
629
|
-
/**
|
|
630
|
-
* Coerce whatever `load()` returned into a well-formed `PanelContent`:
|
|
631
|
-
* unknown item kinds and malformed entries are dropped, strings are
|
|
632
|
-
* trimmed to the caps, and the whole thing is size-bounded. Never throws.
|
|
633
|
-
*/
|
|
634
|
-
function normalizePanelContent(input) {
|
|
635
|
-
const empty = { sections: [] };
|
|
636
|
-
if (!input || typeof input !== "object") return empty;
|
|
637
|
-
const o = input;
|
|
638
|
-
const sections = [];
|
|
639
|
-
if (Array.isArray(o.sections)) for (const raw of o.sections.slice(0, PANEL_CONTENT_LIMITS.sections)) {
|
|
640
|
-
const s = normalizeSection(raw, sections.length);
|
|
641
|
-
if (s) sections.push(s);
|
|
642
|
-
}
|
|
643
|
-
const actions = [];
|
|
644
|
-
if (Array.isArray(o.actions)) {
|
|
645
|
-
for (const raw of o.actions.slice(0, PANEL_CONTENT_LIMITS.actions)) if (raw && typeof raw === "object") {
|
|
646
|
-
const a = raw;
|
|
647
|
-
const id = str(a.id, 200);
|
|
648
|
-
const label = str(a.label, 200);
|
|
649
|
-
if (id && label) actions.push({
|
|
650
|
-
id,
|
|
651
|
-
label,
|
|
652
|
-
...a.tone === "danger" ? { tone: "danger" } : {}
|
|
653
|
-
});
|
|
654
|
-
}
|
|
655
|
-
}
|
|
656
|
-
const out = { sections };
|
|
657
|
-
const title = str(o.title, 200);
|
|
658
|
-
if (title) out.title = title;
|
|
659
|
-
if (typeof o.badge === "number" && Number.isFinite(o.badge)) out.badge = o.badge;
|
|
660
|
-
else if (typeof o.badge === "string" && o.badge) out.badge = o.badge.slice(0, 12);
|
|
661
|
-
if (actions.length > 0) out.actions = actions;
|
|
662
|
-
const emptyText = str(o.empty, 500);
|
|
663
|
-
if (emptyText) out.empty = emptyText;
|
|
664
|
-
return enforceBytes(out);
|
|
665
|
-
}
|
|
666
|
-
function normalizeSection(raw, index) {
|
|
667
|
-
if (!raw || typeof raw !== "object") return null;
|
|
668
|
-
const s = raw;
|
|
669
|
-
const items = [];
|
|
670
|
-
if (Array.isArray(s.items)) for (const item of s.items.slice(0, PANEL_CONTENT_LIMITS.itemsPerSection)) {
|
|
671
|
-
const n = normalizeItem(item);
|
|
672
|
-
if (n) items.push(n);
|
|
673
|
-
}
|
|
674
|
-
const out = {
|
|
675
|
-
id: str(s.id, 200) ?? `section-${index}`,
|
|
676
|
-
items
|
|
677
|
-
};
|
|
678
|
-
const title = str(s.title, 200);
|
|
679
|
-
if (title) out.title = title;
|
|
680
|
-
if (s.collapsed === true) out.collapsed = true;
|
|
681
|
-
return out;
|
|
682
|
-
}
|
|
683
|
-
function normalizeItem(raw) {
|
|
684
|
-
if (!raw || typeof raw !== "object") return null;
|
|
685
|
-
const i = raw;
|
|
686
|
-
switch (i.kind) {
|
|
687
|
-
case "row": {
|
|
688
|
-
const title = str(i.title, 500);
|
|
689
|
-
if (!title) return null;
|
|
690
|
-
const out = {
|
|
691
|
-
kind: "row",
|
|
692
|
-
title
|
|
693
|
-
};
|
|
694
|
-
const id = str(i.id, 200);
|
|
695
|
-
const subtitle = str(i.subtitle, 1e3);
|
|
696
|
-
const href = str(i.href, 2e3);
|
|
697
|
-
const status = str(i.status, 60);
|
|
698
|
-
const actionId = str(i.actionId, 200);
|
|
699
|
-
if (id) out.id = id;
|
|
700
|
-
if (subtitle) out.subtitle = subtitle;
|
|
701
|
-
if (href) out.href = href;
|
|
702
|
-
if (status) out.status = status;
|
|
703
|
-
if (actionId) out.actionId = actionId;
|
|
704
|
-
if (Array.isArray(i.badges)) out.badges = i.badges.filter(isBadge).slice(0, 8);
|
|
705
|
-
if (i.payload !== void 0 && isJsonValue(i.payload)) out.payload = i.payload;
|
|
706
|
-
return out;
|
|
707
|
-
}
|
|
708
|
-
case "markdown": {
|
|
709
|
-
const text = str(i.text);
|
|
710
|
-
return text === void 0 ? null : {
|
|
711
|
-
kind: "markdown",
|
|
712
|
-
text
|
|
713
|
-
};
|
|
714
|
-
}
|
|
715
|
-
case "kv":
|
|
716
|
-
if (!Array.isArray(i.rows)) return null;
|
|
717
|
-
return {
|
|
718
|
-
kind: "kv",
|
|
719
|
-
rows: i.rows.map((r) => {
|
|
720
|
-
if (!r || typeof r !== "object") return null;
|
|
721
|
-
const row = r;
|
|
722
|
-
const label = str(row.label, 200);
|
|
723
|
-
const value = str(row.value, 2e3);
|
|
724
|
-
return label !== void 0 && value !== void 0 ? {
|
|
725
|
-
label,
|
|
726
|
-
value
|
|
727
|
-
} : null;
|
|
728
|
-
}).filter((r) => r !== null).slice(0, PANEL_CONTENT_LIMITS.itemsPerSection)
|
|
729
|
-
};
|
|
730
|
-
case "custom": {
|
|
731
|
-
const renderer = str(i.renderer, 200);
|
|
732
|
-
const fallback = str(i.fallback);
|
|
733
|
-
if (!renderer || fallback === void 0) return null;
|
|
734
|
-
const out = {
|
|
735
|
-
kind: "custom",
|
|
736
|
-
renderer,
|
|
737
|
-
fallback
|
|
738
|
-
};
|
|
739
|
-
if (i.data !== void 0 && isJsonValue(i.data)) out.data = i.data;
|
|
740
|
-
return out;
|
|
741
|
-
}
|
|
742
|
-
default: return null;
|
|
743
|
-
}
|
|
744
|
-
}
|
|
745
|
-
function isBadge(v) {
|
|
746
|
-
return Boolean(v && typeof v === "object" && typeof v.text === "string");
|
|
747
|
-
}
|
|
748
|
-
function isJsonValue(v) {
|
|
749
|
-
try {
|
|
750
|
-
JSON.stringify(v);
|
|
751
|
-
return v !== void 0 && typeof v !== "function" && typeof v !== "symbol";
|
|
752
|
-
} catch {
|
|
753
|
-
return false;
|
|
754
|
-
}
|
|
755
|
-
}
|
|
756
|
-
/**
|
|
757
|
-
* Trim sections from the end until the payload fits the byte budget. A
|
|
758
|
-
* panel that overflows keeps its first sections and gets an `empty`-style
|
|
759
|
-
* note appended so the truncation is visible.
|
|
760
|
-
*/
|
|
761
|
-
function enforceBytes(content) {
|
|
762
|
-
const size = (c) => JSON.stringify(c).length;
|
|
763
|
-
if (size(content) <= PANEL_CONTENT_LIMITS.bytes) return content;
|
|
764
|
-
const sections = [...content.sections];
|
|
765
|
-
while (sections.length > 0 && size({
|
|
766
|
-
...content,
|
|
767
|
-
sections
|
|
768
|
-
}) > PANEL_CONTENT_LIMITS.bytes) sections.pop();
|
|
769
|
-
return {
|
|
770
|
-
...content,
|
|
771
|
-
sections: [...sections, {
|
|
772
|
-
id: "truncated",
|
|
773
|
-
items: [{
|
|
774
|
-
kind: "markdown",
|
|
775
|
-
text: "_Panel content truncated (too large)._"
|
|
776
|
-
}]
|
|
777
|
-
}]
|
|
778
|
-
};
|
|
779
|
-
}
|
|
780
|
-
/** Tab badge as shown next to the label; `undefined` when nothing to show. */
|
|
781
|
-
function panelBadgeText(badge) {
|
|
782
|
-
if (badge === void 0 || badge === 0 || badge === "") return void 0;
|
|
783
|
-
if (typeof badge === "number") return badge > 99 ? "99+" : String(badge);
|
|
784
|
-
return badge;
|
|
785
|
-
}
|
|
786
|
-
//#endregion
|
|
787
|
-
export { resolveOldString as _, ALTERNATE_CRED_KEY_SUFFIX as a, accountCredKey as c, isReservedCredKey as d, nextAccountCredKey as f, describeVia as g, buildContextBreakdown as h, ACCOUNT_CRED_KEY_INFIX as i, alternateCredKey as l, buildContextSegments as m, normalizePanelContent as n, CRED_KEY_SLOT_SEPARATOR as o, oauthAccountLabel as p, panelBadgeText as r, DEFAULT_OAUTH_ACCOUNT_LABEL as s, PANEL_CONTENT_LIMITS as t, isAccountCredKey as u, stripLineNumberPrefixes as v, styleReplacementForVia as y };
|
|
788
|
-
|
|
789
|
-
//# sourceMappingURL=panels-B6gRk4bf.js.map
|