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
|
@@ -1,1762 +0,0 @@
|
|
|
1
|
-
import { Bv as SkillConfig, Dd as EditOutcome, Fd as SessionMeta, Hf as ModelInfo, Id as Settings, Jv as SessionData, Ld as StreamEvent, Lf as ProviderAuth, Nd as Picked, Qo as ExtensionRegistry, Rf as ProviderKey, Tc as SubagentRegistry, U_ as SessionTurn, Uc as LoadedPlugin, Wf as ProviderDescriptor, Wl as StorageMode, Xv as SessionRun, Z_ as ThinkingLevel, Zv as SessionStore, ac as StoredExtensionConfigItem, bf as ModelChainEntry, nv as ToolResultContent, qs as ExtensionConfigCategory, t as Preset, wc as SubagentOverride, y_ as McpServerConfig, ym as AgentRegistry, z_ as SessionContentBlock } from "./index-BgN1T3lk.js";
|
|
2
|
-
//#region src/chat/hints.d.ts
|
|
3
|
-
/**
|
|
4
|
-
* Single hint entry — `<key> <label>`, optionally followed by an inline
|
|
5
|
-
* secondary chord (`<key><extra.key> <label> <extra.label>`) for compound
|
|
6
|
-
* shortcuts like `ctrl+m/n model effort`.
|
|
7
|
-
*
|
|
8
|
-
* Colour fields are advisory hex strings (resolved against the active
|
|
9
|
-
* theme by the renderer); leaving them undefined lets the renderer pick
|
|
10
|
-
* its conventional fallback (e.g. `warn` for keys, `dim` for labels,
|
|
11
|
-
* `mute` for secondary).
|
|
12
|
-
*/
|
|
13
|
-
interface Hint {
|
|
14
|
-
key: string;
|
|
15
|
-
label: string;
|
|
16
|
-
/** Optional override for the key color. Renderer default: warn. */
|
|
17
|
-
keyColor?: string;
|
|
18
|
-
/** Optional override for the label color. Renderer default: dim. */
|
|
19
|
-
labelColor?: string;
|
|
20
|
-
/**
|
|
21
|
-
* Optional secondary chord + value rendered inline after the primary
|
|
22
|
-
* pair: `<key><extra.key> <label> <extra.label>`. Lets one hint advertise
|
|
23
|
-
* a compound shortcut (e.g. `ctrl+m/n model effort`) without forcing
|
|
24
|
-
* callers into a parallel struct or a custom renderer.
|
|
25
|
-
*/
|
|
26
|
-
extra?: {
|
|
27
|
-
key: string;
|
|
28
|
-
label: string;
|
|
29
|
-
/**
|
|
30
|
-
* Dispatchable binding spec behind `extra.key` when the displayed
|
|
31
|
-
* chord is an abbreviation (`/l` for `ctrl+l` — see `shortChord`).
|
|
32
|
-
* The abbreviation itself doesn't parse as a keypress, so a renderer
|
|
33
|
-
* that makes the secondary chord independently clickable needs the
|
|
34
|
-
* full spec. Defaults to `extra.key` when omitted.
|
|
35
|
-
*/
|
|
36
|
-
keySpec?: string; /** Defaults to mute on the renderer side. */
|
|
37
|
-
keyColor?: string; /** Defaults to dim on the renderer side. */
|
|
38
|
-
labelColor?: string;
|
|
39
|
-
};
|
|
40
|
-
}
|
|
41
|
-
/**
|
|
42
|
-
* Truncate `text` to at most `max` characters, replacing the trailing
|
|
43
|
-
* overflow with `…`. Edge cases:
|
|
44
|
-
* - `max <= 0` → empty string (no room to render at all).
|
|
45
|
-
* - `max === 1` → just the ellipsis glyph.
|
|
46
|
-
* - `text.length <= max` → unchanged.
|
|
47
|
-
*
|
|
48
|
-
* Trailing-style truncation matches the natural read order of titles:
|
|
49
|
-
* the prefix carries enough signal to identify the surface.
|
|
50
|
-
*/
|
|
51
|
-
declare function truncateTrailing(text: string, max: number): string;
|
|
52
|
-
/**
|
|
53
|
-
* Plain-text width estimate for a list of {@link Hint}s rendered as
|
|
54
|
-
* `<key> <label> · <key> <label> · …`. Exported so prompt-box overlays
|
|
55
|
-
* can run the same responsive math as the bottom-bar footer when
|
|
56
|
-
* deciding whether trigger hints fit. Pure / total.
|
|
57
|
-
*/
|
|
58
|
-
declare function hintsLength(hints: readonly Hint[]): number;
|
|
59
|
-
/**
|
|
60
|
-
* Stable empty list so callers can compare by reference. Exported so
|
|
61
|
-
* any consumer that needs to feed "no primary hints" into the same
|
|
62
|
-
* `clipHintsToWidth` / `renderHintSpans` pipeline (e.g. the TUI's
|
|
63
|
-
* minimal UI mode, where the prompt overlay shows only `@` / `/`
|
|
64
|
-
* triggers) reuses the same frozen array instead of allocating a new
|
|
65
|
-
* one each render.
|
|
66
|
-
*/
|
|
67
|
-
declare const EMPTY_HINTS: readonly Hint[];
|
|
68
|
-
/**
|
|
69
|
-
* Return the longest prefix of `hints` whose rendered width fits within
|
|
70
|
-
* `budget`. Used to degrade hint rows gracefully at narrow terminal
|
|
71
|
-
* widths instead of letting an absolutely-positioned hint row wrap
|
|
72
|
-
* mid-segment (which paints the overflow over surrounding borders and
|
|
73
|
-
* looks like garbled glyphs in a TUI).
|
|
74
|
-
*
|
|
75
|
-
* Prefix-only (no reordering, no last-hint priority) so the survivors
|
|
76
|
-
* keep their authored order — the user's muscle memory for "leftmost
|
|
77
|
-
* hint = primary action" stays intact as the terminal shrinks.
|
|
78
|
-
*/
|
|
79
|
-
declare function clipHintsToWidth(hints: readonly Hint[], budget: number): readonly Hint[];
|
|
80
|
-
//#endregion
|
|
81
|
-
//#region src/start/shared-options.d.ts
|
|
82
|
-
declare const startProviderNames: readonly ["anthropic", "openai", "openrouter", "cerebras", "xai", "arcee", "baseten", "local", "openai-compat"];
|
|
83
|
-
type StartProviderName = typeof startProviderNames[number];
|
|
84
|
-
declare const startPresetNames: readonly ["basic"];
|
|
85
|
-
type StartPresetName = typeof startPresetNames[number];
|
|
86
|
-
declare const startFormatNames: readonly ["zidane", "provider"];
|
|
87
|
-
type StartFormatName = typeof startFormatNames[number];
|
|
88
|
-
interface StartLocalOptions {
|
|
89
|
-
system?: string;
|
|
90
|
-
prompt: string;
|
|
91
|
-
model?: string;
|
|
92
|
-
baseURL?: string;
|
|
93
|
-
apiKeyEnv?: string;
|
|
94
|
-
headersEnv?: string;
|
|
95
|
-
extraHeaders?: Record<string, string>;
|
|
96
|
-
vision?: boolean;
|
|
97
|
-
imageInToolResult?: boolean;
|
|
98
|
-
temperature?: number;
|
|
99
|
-
seed?: number;
|
|
100
|
-
preset: StartPresetName;
|
|
101
|
-
thinking: ThinkingLevel;
|
|
102
|
-
provider: StartProviderName;
|
|
103
|
-
context: string;
|
|
104
|
-
image?: string;
|
|
105
|
-
cwd?: string;
|
|
106
|
-
env?: Record<string, string>;
|
|
107
|
-
pregame?: {
|
|
108
|
-
name: string;
|
|
109
|
-
content: string;
|
|
110
|
-
};
|
|
111
|
-
sandboxId?: string;
|
|
112
|
-
sandboxOnDestroy?: 'kill' | 'pause' | 'leave';
|
|
113
|
-
mcp?: McpServerConfig[];
|
|
114
|
-
sessionDb?: string;
|
|
115
|
-
sessionId?: string;
|
|
116
|
-
schema?: Record<string, unknown>;
|
|
117
|
-
json: boolean;
|
|
118
|
-
streamJson: boolean;
|
|
119
|
-
format: StartFormatName;
|
|
120
|
-
}
|
|
121
|
-
//#endregion
|
|
122
|
-
//#region src/chat/keybindings.d.ts
|
|
123
|
-
/**
|
|
124
|
-
* Keybindings — a single source of truth for the app's global shortcuts.
|
|
125
|
-
*
|
|
126
|
-
* Every customizable action is declared once in {@link KEYBINDING_DEFS}
|
|
127
|
-
* with its default trigger, label, and description. The TUI imports
|
|
128
|
-
* `DEFAULT_KEYBINDINGS` for the baked-in defaults; on launch we load
|
|
129
|
-
* `<userDir>/keybindings.json` (when present) and merge user overrides
|
|
130
|
-
* on top so the user can rebind any action without recompiling.
|
|
131
|
-
*
|
|
132
|
-
* Scope (deliberate):
|
|
133
|
-
*
|
|
134
|
-
* - We expose only the **global, action-opening** shortcuts here —
|
|
135
|
-
* "open the Settings modal", "cycle agent profile", "enter
|
|
136
|
-
* select-turn mode", etc. Modal-internal letter shortcuts (`f`
|
|
137
|
-
* fork, `d` delete, `c` copy on the turn-details modal) and
|
|
138
|
-
* universal navigation (`↑/↓/↵/⎋`) stay hardcoded — they live
|
|
139
|
-
* too close to a renderable's input contract to remap safely.
|
|
140
|
-
*
|
|
141
|
-
* - Storage lives at the **user level** (`<userDir>/keybindings.json`),
|
|
142
|
-
* never inside a project's `.{prefix}/`. Shortcut muscle memory is
|
|
143
|
-
* a per-user concern, not a per-repo one.
|
|
144
|
-
*
|
|
145
|
-
* Format on disk: JSON with `//` and `/* … *\/` comments allowed
|
|
146
|
-
* (parsed via a small JSONC stripper). Each entry maps an action id
|
|
147
|
-
* to a binding spec string. Specs are parsed by {@link parseBindingSpec};
|
|
148
|
-
* unknown / malformed entries fall back to the default for that action
|
|
149
|
-
* (with a debug log under `ZIDANE_DEBUG`) so a syntax slip never bricks
|
|
150
|
-
* the TUI.
|
|
151
|
-
*/
|
|
152
|
-
/**
|
|
153
|
-
* Every action the keybindings system can drive. Adding a new action
|
|
154
|
-
* here forces every consumer (TUI keyboard handler, hint rows, settings
|
|
155
|
-
* UI) to handle it, and ships a default that the user can override.
|
|
156
|
-
*/
|
|
157
|
-
type KeyAction = 'openSettings' | 'openSessionDetails' | 'newSession' | 'openModelPicker' | 'openEffortPicker' | 'openTodos' | 'openArtifacts' | 'panelNext' | 'panelPrev' | 'openContextPanel' | 'openMainSession' | 'openUsagePanel' | 'openKeybindings' | 'openPalette' | 'cycleAgent' | 'enterSelectTurnMode' | 'cancelToolCall' | 'abortRun' | 'changeCwd' | 'attachClipboardImage' | 'openExternalEditor' | 'enterQueueSelection' | 'pushQueuedMessage' | 'dropQueuedMessage' | 'turnFork' | 'turnDelete' | 'turnCopy' | 'turnEdit' | 'sessionDelete' | 'sessionCopyId' | 'sessionGenerateTitle' | 'sessionExportMarkdown' | 'sessionExportJson' | 'sessionCompact';
|
|
158
|
-
/** Resolved keybindings — every action has a current spec string. */
|
|
159
|
-
type KeyBindings = Record<KeyAction, string>;
|
|
160
|
-
/**
|
|
161
|
-
* Resolved spec string for one extension-contributed keybinding. Same
|
|
162
|
-
* shape as a built-in {@link KeyBindings} entry but the `id` is
|
|
163
|
-
* extension-owned (no `KeyAction` union member). The TUI dispatcher
|
|
164
|
-
* iterates these alongside the built-ins; user overrides flow through
|
|
165
|
-
* the same `keybindings.json` file by matching on `id`.
|
|
166
|
-
*/
|
|
167
|
-
interface ResolvedExtensionKeybinding {
|
|
168
|
-
/** Extension-owned id (matches `ExtensionKeybinding.id`). */
|
|
169
|
-
id: string;
|
|
170
|
-
/** Active spec string — user override when present, default otherwise. May be empty (= unbound). */
|
|
171
|
-
spec: string;
|
|
172
|
-
}
|
|
173
|
-
/**
|
|
174
|
-
* Logical grouping for one action — used by the keybindings panel to
|
|
175
|
-
* render section headers. Stable strings (not an enum) so future
|
|
176
|
-
* groups can be added without churning every existing entry.
|
|
177
|
-
*/
|
|
178
|
-
type KeyBindingGroup = 'Global' | 'Message queue' | 'Turn details' | 'Session details';
|
|
179
|
-
/** Static metadata for one action — used by the loader, hint rows, settings UI. */
|
|
180
|
-
interface KeyBindingDef {
|
|
181
|
-
/** Stable identifier — JSON key + TS union member. */
|
|
182
|
-
action: KeyAction;
|
|
183
|
-
/** Default trigger spec (e.g. `'ctrl+o'`). */
|
|
184
|
-
default: string;
|
|
185
|
-
/** Short label used in shortcut hint rows. */
|
|
186
|
-
label: string;
|
|
187
|
-
/** Longer description for the settings UI and the annotated JSON file. */
|
|
188
|
-
description: string;
|
|
189
|
-
/**
|
|
190
|
-
* Group label rendered as a section header in the keybindings panel.
|
|
191
|
-
* Items are listed in {@link KEYBINDING_DEFS} order; the panel just
|
|
192
|
-
* inserts a header whenever this field changes between adjacent
|
|
193
|
-
* entries — so groups stay contiguous and the order here is the
|
|
194
|
-
* order on screen.
|
|
195
|
-
*/
|
|
196
|
-
group: KeyBindingGroup;
|
|
197
|
-
}
|
|
198
|
-
/**
|
|
199
|
-
* The canonical action catalog. Order is the source of truth for the
|
|
200
|
-
* generated keybindings file and the settings UI.
|
|
201
|
-
*/
|
|
202
|
-
declare const KEYBINDING_DEFS: readonly KeyBindingDef[];
|
|
203
|
-
/** Index by action for O(1) lookup of label / description / default. */
|
|
204
|
-
declare const KEYBINDING_DEF_BY_ACTION: Readonly<Record<KeyAction, KeyBindingDef>>;
|
|
205
|
-
/** Defaults, derived from {@link KEYBINDING_DEFS} so the two never drift. */
|
|
206
|
-
declare const DEFAULT_KEYBINDINGS: KeyBindings;
|
|
207
|
-
/** Parsed shape of a `"ctrl+shift+o"` spec. */
|
|
208
|
-
interface ParsedBinding {
|
|
209
|
-
ctrl: boolean;
|
|
210
|
-
shift: boolean;
|
|
211
|
-
alt: boolean;
|
|
212
|
-
meta: boolean;
|
|
213
|
-
/** The key name (e.g. `'o'`, `'tab'`, `'escape'`). Always lowercase. */
|
|
214
|
-
name: string;
|
|
215
|
-
}
|
|
216
|
-
/**
|
|
217
|
-
* Parse a `'ctrl+shift+o'`-style spec into structured fields. Returns
|
|
218
|
-
* `null` for empty / malformed inputs; the caller falls back to the
|
|
219
|
-
* default for that action.
|
|
220
|
-
*
|
|
221
|
-
* Tolerant by design:
|
|
222
|
-
* - Case-insensitive (`Ctrl+O` → same as `ctrl+o`).
|
|
223
|
-
* - Modifier order doesn't matter (`shift+ctrl+o` works).
|
|
224
|
-
* - Mixed `+` and `-` separators allowed (`ctrl-o`, `ctrl+o`).
|
|
225
|
-
* - Trailing / leading whitespace is stripped.
|
|
226
|
-
* - Duplicate modifiers collapse silently.
|
|
227
|
-
*/
|
|
228
|
-
declare function parseBindingSpec(spec: string | undefined | null): ParsedBinding | null;
|
|
229
|
-
/**
|
|
230
|
-
* Test a KeyEvent against a parsed-or-string binding. Accepts either
|
|
231
|
-
* form so callers can pre-parse (hot path) or pass the raw spec for
|
|
232
|
-
* one-off checks.
|
|
233
|
-
*
|
|
234
|
-
* Modifier semantics: ALL declared modifiers must be pressed AND no
|
|
235
|
-
* extra modifiers may be pressed. So `'o'` does NOT match `ctrl+o`,
|
|
236
|
-
* and `'ctrl+o'` does NOT match `ctrl+shift+o`. This avoids surprises
|
|
237
|
-
* where a binding that should be specific accidentally fires for a
|
|
238
|
-
* superset of key combinations.
|
|
239
|
-
*/
|
|
240
|
-
declare function matchesBinding(event: {
|
|
241
|
-
name?: string;
|
|
242
|
-
ctrl?: boolean;
|
|
243
|
-
shift?: boolean;
|
|
244
|
-
meta?: boolean;
|
|
245
|
-
option?: boolean;
|
|
246
|
-
alt?: boolean;
|
|
247
|
-
}, spec: string | ParsedBinding): boolean;
|
|
248
|
-
/**
|
|
249
|
-
* Render a binding spec (`"ctrl+return"`, `"backspace"`, `"delete"`) as a
|
|
250
|
-
* compact display string the user recognizes at a glance. Substitutes
|
|
251
|
-
* arrow / enter / backspace glyphs for their verbose names so the hint
|
|
252
|
-
* row stays narrow; modifier names + plain keys pass through unchanged.
|
|
253
|
-
*
|
|
254
|
-
* Empty / missing specs return an empty string — callers decide whether
|
|
255
|
-
* to render a placeholder (e.g. `'—'` for an unbound action in the
|
|
256
|
-
* keybindings panel) or hide the surface entirely (e.g. hint rows that
|
|
257
|
-
* fall back to a different chord when the binding is empty).
|
|
258
|
-
*/
|
|
259
|
-
declare function formatBindingForDisplay(spec: string | null | undefined): string;
|
|
260
|
-
/**
|
|
261
|
-
* Merge a partial map of user overrides into the defaults. Unknown
|
|
262
|
-
* action keys are dropped (a future TUI version may have retired the
|
|
263
|
-
* action); invalid spec strings (parse fails) fall back to the default
|
|
264
|
-
* for that action.
|
|
265
|
-
*/
|
|
266
|
-
declare function mergeKeybindings(overrides: Readonly<Record<string, unknown>> | null | undefined): KeyBindings;
|
|
267
|
-
/** Path of the user-level keybindings file. */
|
|
268
|
-
declare function keybindingsPath(userDir: string): string;
|
|
269
|
-
/**
|
|
270
|
-
* One contiguous section of the catalog — every action in a single
|
|
271
|
-
* `group` rendered together with the section header inserted once.
|
|
272
|
-
* Adjacent sections with the same group are NOT merged: catalog order
|
|
273
|
-
* wins so the on-screen story matches the on-disk file.
|
|
274
|
-
*
|
|
275
|
-
* `rows` may carry built-in `KeyBindingDef`s (the common case) or
|
|
276
|
-
* extension-owned ones (when an extension contributes a keybinding).
|
|
277
|
-
* Both share label / description / spec — see {@link KeyBindingRow}.
|
|
278
|
-
*/
|
|
279
|
-
interface KeyBindingSection {
|
|
280
|
-
group: string;
|
|
281
|
-
rows: ReadonlyArray<KeyBindingRow>;
|
|
282
|
-
}
|
|
283
|
-
/**
|
|
284
|
-
* One row in the keybindings catalog. Either a built-in action (with
|
|
285
|
-
* its `def`) or an extension-contributed one (with `id` instead). The
|
|
286
|
-
* renderer reads `label` / `description` / `spec` uniformly and only
|
|
287
|
-
* needs the `kind` discriminator when offering action-specific UI
|
|
288
|
-
* (e.g. "edit in keybindings.json" by action name).
|
|
289
|
-
*/
|
|
290
|
-
type KeyBindingRow = {
|
|
291
|
-
kind: 'builtin';
|
|
292
|
-
def: KeyBindingDef;
|
|
293
|
-
spec: string;
|
|
294
|
-
} | {
|
|
295
|
-
kind: 'extension';
|
|
296
|
-
id: string;
|
|
297
|
-
label: string;
|
|
298
|
-
description: string;
|
|
299
|
-
spec: string;
|
|
300
|
-
};
|
|
301
|
-
/**
|
|
302
|
-
* Walk {@link KEYBINDING_DEFS} in order and bucket rows into contiguous
|
|
303
|
-
* sections by `group`. Shared between the standalone `KeybindingsModal`
|
|
304
|
-
* and the `Keybindings` tab inside `SettingsModal` so both surfaces
|
|
305
|
-
* render the same catalog with the same ordering rules.
|
|
306
|
-
*
|
|
307
|
-
* Pass `extensionRows` (resolved extension keybindings paired with
|
|
308
|
-
* their definitions) to append an "Extensions" section at the end so
|
|
309
|
-
* extension-contributed shortcuts are discoverable in the same UI.
|
|
310
|
-
*/
|
|
311
|
-
declare function groupBindings(bindings: KeyBindings, extensionRows?: readonly {
|
|
312
|
-
id: string;
|
|
313
|
-
label: string;
|
|
314
|
-
description: string;
|
|
315
|
-
spec: string;
|
|
316
|
-
}[]): readonly KeyBindingSection[];
|
|
317
|
-
/**
|
|
318
|
-
* Width (in cells) of the fixed key column used by every binding-row
|
|
319
|
-
* renderer. Derived once from {@link KEYBINDING_DEFS} so a new action
|
|
320
|
-
* with a wider default spec (`ctrl+shift+x`, …) automatically grows
|
|
321
|
-
* the column instead of truncating the label.
|
|
322
|
-
*/
|
|
323
|
-
declare const KEYBINDING_KEY_COL_WIDTH: number;
|
|
324
|
-
/**
|
|
325
|
-
* Load + merge the user's keybindings file (when present). Always
|
|
326
|
-
* returns a fully-resolved {@link KeyBindings} — defaults fill in for
|
|
327
|
-
* any missing / invalid entries so consumers can treat the result as
|
|
328
|
-
* total.
|
|
329
|
-
*
|
|
330
|
-
* Failure modes (all tolerated, all fall back to defaults):
|
|
331
|
-
* - File missing
|
|
332
|
-
* - File not valid JSON / JSONC (after comment stripping)
|
|
333
|
-
* - Top-level is not an object
|
|
334
|
-
* - Individual entries have invalid spec strings
|
|
335
|
-
*/
|
|
336
|
-
declare function readKeybindings(userDir: string): KeyBindings;
|
|
337
|
-
/**
|
|
338
|
-
* Create the user-level `keybindings.json` if it doesn't exist,
|
|
339
|
-
* prefilled with every default. Returns the absolute file path either
|
|
340
|
-
* way so the caller can open it in `$EDITOR`. Idempotent: an existing
|
|
341
|
-
* user file is NEVER overwritten — the user's customizations are
|
|
342
|
-
* sacred.
|
|
343
|
-
*/
|
|
344
|
-
declare function ensureKeybindingsFile(userDir: string): string;
|
|
345
|
-
/**
|
|
346
|
-
* Read the raw on-disk JSON object from `keybindings.json` after the
|
|
347
|
-
* JSONC stripper. Used by extension-keybinding resolution so the
|
|
348
|
-
* user's overrides for extension-owned ids flow through the same file
|
|
349
|
-
* the built-in actions use.
|
|
350
|
-
*
|
|
351
|
-
* Returns an empty object on missing / malformed / non-object files
|
|
352
|
-
* — same fault-tolerance contract as {@link readKeybindings}.
|
|
353
|
-
*/
|
|
354
|
-
declare function readKeybindingsRaw(userDir: string): Readonly<Record<string, unknown>>;
|
|
355
|
-
/**
|
|
356
|
-
* Resolve the live spec string for each extension-contributed
|
|
357
|
-
* keybinding. The user's `keybindings.json` is consulted for an
|
|
358
|
-
* override on the binding's `id`; absent / invalid entries fall back
|
|
359
|
-
* to the binding's `default`.
|
|
360
|
-
*
|
|
361
|
-
* Pass the raw object (from {@link readKeybindingsRaw}) — passing
|
|
362
|
-
* `KeyBindings` here wouldn't help because the typed map only carries
|
|
363
|
-
* built-in `KeyAction` entries.
|
|
364
|
-
*
|
|
365
|
-
* Returns one entry per input binding, in source order. Empty `spec`
|
|
366
|
-
* (binding declared `default: ''` and the user didn't bind it) is a
|
|
367
|
-
* legitimate "unbound" state — the dispatcher never matches an empty
|
|
368
|
-
* spec, so the action stays accessible via re-binding through
|
|
369
|
-
* `keybindings.json`.
|
|
370
|
-
*/
|
|
371
|
-
declare function resolveExtensionKeybindings(bindings: readonly {
|
|
372
|
-
id: string;
|
|
373
|
-
default: string;
|
|
374
|
-
}[], raw: Readonly<Record<string, unknown>>): ResolvedExtensionKeybinding[];
|
|
375
|
-
/**
|
|
376
|
-
* Strip `//` line comments and `/* … *\/` block comments from a JSONC
|
|
377
|
-
* source string. Stays out of string literals so a `"foo // bar"` value
|
|
378
|
-
* keeps its slashes. Exported for unit-tests; the only runtime caller
|
|
379
|
-
* is {@link readKeybindings}.
|
|
380
|
-
*
|
|
381
|
-
* Trade-off: this is a tiny state-machine, not a full JSONC parser. It
|
|
382
|
-
* doesn't understand `\\` outside strings (irrelevant for JSON) and
|
|
383
|
-
* doesn't track line numbers in error messages. Good enough for a
|
|
384
|
-
* config file — corruption in production gracefully falls back to the
|
|
385
|
-
* defaults via the try/catch in `readKeybindings`.
|
|
386
|
-
*/
|
|
387
|
-
declare function stripJsonComments(input: string): string;
|
|
388
|
-
//#endregion
|
|
389
|
-
//#region src/chat/store.d.ts
|
|
390
|
-
interface TuiState {
|
|
391
|
-
lastProvider?: ProviderKey;
|
|
392
|
-
lastSessionId?: string;
|
|
393
|
-
/** Per-provider last-used model id. */
|
|
394
|
-
lastModelByProvider?: Partial<Record<ProviderKey, string>>;
|
|
395
|
-
/**
|
|
396
|
-
* Last-applied model fallback chain (entry 0 = primary, mirroring
|
|
397
|
-
* `lastProvider` + `lastModelByProvider`; entries 1+ = fallbacks).
|
|
398
|
-
* Additive — absent for single-model users and older state files.
|
|
399
|
-
* Restored on launch only when entry 0 still matches the resolved
|
|
400
|
-
* primary; entries are re-validated against the live registry.
|
|
401
|
-
*/
|
|
402
|
-
lastModelChain?: ModelChainEntry[];
|
|
403
|
-
/**
|
|
404
|
-
* Per-model last-picked reasoning effort. Keyed by model id (not provider)
|
|
405
|
-
* so switching the same model across providers preserves the user's
|
|
406
|
-
* intent. Models without reasoning support are absent from the map.
|
|
407
|
-
*/
|
|
408
|
-
lastEffortByModel?: Record<string, ThinkingLevel>;
|
|
409
|
-
/**
|
|
410
|
-
* Per-model last-picked custom options (e.g. `{ fast: true }`). Keyed by
|
|
411
|
-
* model id like {@link lastEffortByModel}, so a toggle follows the model
|
|
412
|
-
* across providers. Models with no options are absent from the map.
|
|
413
|
-
*/
|
|
414
|
-
lastModelOptionsByModel?: Record<string, Record<string, boolean>>;
|
|
415
|
-
/**
|
|
416
|
-
* Last-active agent profile id (see {@link AgentRegistry}). Resumed on
|
|
417
|
-
* launch so a returning user lands back in the same mode (Build / Plan /
|
|
418
|
-
* a host profile). Falls back to the host's `defaultAgent` then the first
|
|
419
|
-
* registry key if the id is no longer registered.
|
|
420
|
-
*/
|
|
421
|
-
/**
|
|
422
|
-
* @deprecated No longer read: the agent profile is per-session and fresh
|
|
423
|
-
* sessions always start in the default. Kept so older state files parse.
|
|
424
|
-
*/
|
|
425
|
-
lastAgent?: string;
|
|
426
|
-
/** User-toggled transcript filters. Persisted so they outlive a launch. */
|
|
427
|
-
settings?: Partial<Settings>;
|
|
428
|
-
}
|
|
429
|
-
interface StateStoreApi {
|
|
430
|
-
load: () => TuiState;
|
|
431
|
-
save: (state: TuiState) => void;
|
|
432
|
-
}
|
|
433
|
-
declare function createStateStore(path: string): StateStoreApi;
|
|
434
|
-
declare function loadState(path: string): TuiState;
|
|
435
|
-
declare function saveState(path: string, state: TuiState): void;
|
|
436
|
-
/**
|
|
437
|
-
* Load every session and project it to the compact `SessionMeta` shape used by
|
|
438
|
-
* the picker. Sorted by recency via the underlying store's `list()` contract
|
|
439
|
-
* (sqlite store returns by `updated_at DESC`).
|
|
440
|
-
*
|
|
441
|
-
* Robust to per-row failures: `Promise.allSettled` so a single corrupt or
|
|
442
|
-
* unreadable row (malformed JSON, partial write, transient I/O error)
|
|
443
|
-
* doesn't take down the entire picker. Failed rows are silently skipped;
|
|
444
|
-
* a stderr line is emitted under `ZIDANE_DEBUG` for diagnosis.
|
|
445
|
-
*/
|
|
446
|
-
declare function listSessionMeta(store: SessionStore, filter?: {
|
|
447
|
-
/**
|
|
448
|
-
* Restrict to sessions belonging to this project. Omit to ignore
|
|
449
|
-
* the axis; pass `null` to ask for untagged (legacy) sessions
|
|
450
|
-
* specifically. The TUI defaults to passing the current git root /
|
|
451
|
-
* cwd here so each project sees only its own conversations.
|
|
452
|
-
*/
|
|
453
|
-
projectRoot?: string | null;
|
|
454
|
-
}): Promise<SessionMeta[]>;
|
|
455
|
-
/** Derive a short title from the first user message — returns null when empty. */
|
|
456
|
-
declare function titleFromTurns(turns: SessionTurn[]): string | null;
|
|
457
|
-
/**
|
|
458
|
-
* Display title for a session — preferred sources, in order:
|
|
459
|
-
*
|
|
460
|
-
* 1. `metadata.title` if it's a non-empty string (typically set by
|
|
461
|
-
* the session-details modal's "generate title" action).
|
|
462
|
-
* 2. {@link titleFromTurns} — the first user message, one-line + clipped.
|
|
463
|
-
* 3. {@link DEFAULT_SESSION_TITLE} (`'New session'`).
|
|
464
|
-
*
|
|
465
|
-
* Total / pure / defensive on non-string metadata values.
|
|
466
|
-
*/
|
|
467
|
-
declare function deriveSessionTitle(turns: SessionTurn[], metadata?: Record<string, unknown>): string;
|
|
468
|
-
/**
|
|
469
|
-
* Replay persisted turns as a viewable transcript. Mirrors the event shape
|
|
470
|
-
* produced live by the agent hooks so loaded and streaming history render
|
|
471
|
-
* identically — including subagent ancestry when `runs` is supplied.
|
|
472
|
-
*
|
|
473
|
-
* Subagent reconstruction:
|
|
474
|
-
* - Every turn carries a `runId`. We look that up in `runs` to get the
|
|
475
|
-
* run's `depth` and tag the resulting events with `{ depth, childId }`
|
|
476
|
-
* — the same shape the live `child:*` bubble hooks produce.
|
|
477
|
-
* - We synthesize `spawn-start` / `spawn-end` markers at each child-run
|
|
478
|
-
* boundary so the transcript reads the same as a live run did
|
|
479
|
-
* (`🌱 [run-id] task` … child events … `🌳 [run-id] done · tokens`).
|
|
480
|
-
* - For child runs (`depth > 0`), the user-role "task" text is suppressed
|
|
481
|
-
* because `spawn-start` already shows it.
|
|
482
|
-
*
|
|
483
|
-
* Without `runs` (legacy callers / tests), the function falls back to the
|
|
484
|
-
* old behavior: depth-0 events with no subagent grouping.
|
|
485
|
-
*/
|
|
486
|
-
/**
|
|
487
|
-
* Map a `compact-summary` content block to its `compact-summary` StreamEvent —
|
|
488
|
-
* the single source of truth for the compaction boundary card. Used by
|
|
489
|
-
* {@link eventsFromTurns} (reload / TUI live repaint) AND by chat hosts that
|
|
490
|
-
* surface the boundary live without a full reload (the GUI broadcasts this
|
|
491
|
-
* from the loop's `compact:end` hook), so the live card and the reloaded card
|
|
492
|
-
* are byte-identical regardless of who created the marker (manual, the old
|
|
493
|
-
* host trigger, or loop-native auto-compaction — all share this block shape).
|
|
494
|
-
*/
|
|
495
|
-
declare function compactSummaryEvent(block: Extract<SessionContentBlock, {
|
|
496
|
-
type: 'compact-summary';
|
|
497
|
-
}>, turnId?: string): StreamEvent;
|
|
498
|
-
declare function eventsFromTurns(turns: SessionTurn[], runs?: readonly SessionRun[]): StreamEvent[];
|
|
499
|
-
declare function toolCallPreview(name: string, input: Record<string, unknown>): string;
|
|
500
|
-
/**
|
|
501
|
-
* Update the trailing `'tool'` event matching `callId` so its
|
|
502
|
-
* `edit.outcomes` reflects the canonical merged outcomes the chat
|
|
503
|
-
* layer's `tool:transform` hook just computed. Without this, the live
|
|
504
|
-
* diff badges stay frozen at whatever the gate set (approval-side
|
|
505
|
-
* outcomes) and never reflect body-side failures from `multi_edit`'s
|
|
506
|
-
* best-effort run — only a session reload re-attaches the merged
|
|
507
|
-
* outcomes via {@link eventsFromTurns}.
|
|
508
|
-
*
|
|
509
|
-
* Walks back-to-front because the matching event is overwhelmingly the
|
|
510
|
-
* most recent (we're updating right after the body returned). Returns
|
|
511
|
-
* the same reference when no match is found (or the event already
|
|
512
|
-
* carries the target outcomes), so React skips the re-render.
|
|
513
|
-
*/
|
|
514
|
-
declare function updateToolEventOutcomes(events: readonly StreamEvent[], callId: string, outcomes: readonly EditOutcome[]): StreamEvent[];
|
|
515
|
-
/** Render tool output as plain text, whether it's a string or structured content. */
|
|
516
|
-
declare function toolResultText(output: string | ToolResultContent[]): string;
|
|
517
|
-
/**
|
|
518
|
-
* Strip the `Tokens: …` line from a spawn tool-result. The spawn-end marker
|
|
519
|
-
* displayed right above already shows the same stats; keeping the line in the
|
|
520
|
-
* rendered tool-result body just produces a visible duplicate (and, on
|
|
521
|
-
* reloaded pre-fix sessions, an *inconsistent* duplicate — the persisted line
|
|
522
|
-
* uses the old `13 in / 4075 out` shape while the freshly synthesized
|
|
523
|
-
* spawn-end uses the cache-aware `in 92615 (cache 92602) / 4075 out` shape).
|
|
524
|
-
*
|
|
525
|
-
* Display-only: the persisted tool_result content is untouched, so the LLM
|
|
526
|
-
* still sees the full string in its context window. Anchored to start-of-line
|
|
527
|
-
* and matches both `Tokens: 13 in / 4075 out` (legacy) and `Tokens: in 13 …`
|
|
528
|
-
* (post-`formatTokenUsage`) shapes.
|
|
529
|
-
*/
|
|
530
|
-
declare function stripSpawnTokensLine(text: string): string;
|
|
531
|
-
/**
|
|
532
|
-
* Resolve the top margin (in rows) for an event given the one rendered
|
|
533
|
-
* just before it. Context-aware rules:
|
|
534
|
-
*
|
|
535
|
-
* - A `tool` / `tool-result` event right after another
|
|
536
|
-
* `tool` / `tool-result` collapses to a tight list — call→result
|
|
537
|
-
* pairs and back-to-back calls read as one logical block.
|
|
538
|
-
* - Consecutive `task-notification` banners stack tight — a burst of
|
|
539
|
-
* background-task completions reads as one log column rather than
|
|
540
|
-
* scattered banners.
|
|
541
|
-
*
|
|
542
|
-
* NB: parent-level events (`depth === 0`) following a subagent block
|
|
543
|
-
* (`depth > 0`) get their normal default margin. An earlier revision
|
|
544
|
-
* collapsed this transition to 0 on the assumption that the subagent's
|
|
545
|
-
* `🌳` end-marker provided enough visual separation — it didn't. A
|
|
546
|
-
* 2-cell emoji on the same row as the close marker doesn't create a
|
|
547
|
-
* vertical break, and in hide-subagent-output mode the SubagentBlock
|
|
548
|
-
* box isn't rendered either, so the parent's follow-up markdown was
|
|
549
|
-
* glued directly against the close line. Subagents should READ like
|
|
550
|
-
* tool calls: open with breathing room, close tight inside, and open
|
|
551
|
-
* a clean gap before the parent's next thought — that's the contract
|
|
552
|
-
* the tool-call → markdown transition uses, mirrored here.
|
|
553
|
-
*
|
|
554
|
-
* Renderer-agnostic — TUI uses it as Yoga `marginTop`; a CSS host can
|
|
555
|
-
* use the same number as the row's top margin in `em` / `rem`.
|
|
556
|
-
*/
|
|
557
|
-
declare function marginTopFor(event: StreamEvent, previous: StreamEvent | undefined): number;
|
|
558
|
-
/** Effective context size of the most recent assistant turn — drives the footer indicator. */
|
|
559
|
-
/**
|
|
560
|
-
* Walk from the end of `turns` and return the cache-aware input-token total
|
|
561
|
-
* of the most recent **parent** (depth-0) assistant turn. Subagent turns
|
|
562
|
-
* are skipped because their context window is the child's, not the parent's
|
|
563
|
-
* — surfacing a subagent's `usage.input` as the footer's "context used"
|
|
564
|
-
* after a session ends mid-spawn would be misleading. The next prompt
|
|
565
|
-
* feeds the parent, so the parent's last view is what matters.
|
|
566
|
-
*
|
|
567
|
-
* Zero-context placeholder turns are also skipped. `executeTurn`
|
|
568
|
-
* synthesizes an assistant turn with `usage: { input: 0, output: 0 }`
|
|
569
|
-
* when the provider stream throws / aborts before any usage is reported
|
|
570
|
-
* (see `src/loop.ts`'s catch path) — that turn is purely a shape
|
|
571
|
-
* contract for resume, not a real context-window measurement. Without
|
|
572
|
-
* the skip, an abort mid-stream shadows the prior real turn and the
|
|
573
|
-
* footer reads `ctx 0` on the next session load even though earlier
|
|
574
|
-
* turns accumulated meaningful context (and `run.cost`).
|
|
575
|
-
*
|
|
576
|
-
* `runs` is optional for backwards compatibility (older call sites and
|
|
577
|
-
* tests that don't have ancestry info). Without it, this falls back to the
|
|
578
|
-
* pre-fix behavior — depth is unknown so every assistant turn qualifies.
|
|
579
|
-
*/
|
|
580
|
-
declare function lastContextSizeFromTurns(turns: SessionTurn[], runs?: readonly SessionRun[]): number;
|
|
581
|
-
/**
|
|
582
|
-
* Sum provider-reported USD cost across every run in a session. Used to
|
|
583
|
-
* seed the live cost indicator on session activation. Returns 0 when no
|
|
584
|
-
* run carries a `cost` (most providers — only OpenRouter reports today).
|
|
585
|
-
*/
|
|
586
|
-
declare function sumRunCosts(runs: readonly SessionRun[]): number;
|
|
587
|
-
/** Per-model token/spend totals across a session — see {@link usageByModel}. */
|
|
588
|
-
interface ModelUsageSummary {
|
|
589
|
-
/** Provider-echoed model id, or `"unknown"` for turns that never recorded one. */
|
|
590
|
-
modelId: string;
|
|
591
|
-
turns: number;
|
|
592
|
-
/** Fresh (uncached) input tokens. */
|
|
593
|
-
input: number;
|
|
594
|
-
output: number;
|
|
595
|
-
cacheRead: number;
|
|
596
|
-
cacheCreation: number;
|
|
597
|
-
/** Summed USD cost across turns that carried one (provider-reported or estimated). */
|
|
598
|
-
cost: number;
|
|
599
|
-
/**
|
|
600
|
-
* `false` when at least one turn had no cost figure (no published rate
|
|
601
|
-
* for the model) — `cost` is then a floor, not a total.
|
|
602
|
-
*/
|
|
603
|
-
costComplete: boolean;
|
|
604
|
-
}
|
|
605
|
-
/**
|
|
606
|
-
* Aggregate per-model token + spend totals across every run in a session.
|
|
607
|
-
* Parent and subagent runs alike: each turn carries its own `modelId`, so
|
|
608
|
-
* cost-tiered delegation (cheap spawn workers) shows up as separate rows
|
|
609
|
-
* priced at their own rates. Sorted by cost (desc), then total tokens, so
|
|
610
|
-
* the biggest spender reads first.
|
|
611
|
-
*/
|
|
612
|
-
declare function usageByModel(runs: readonly SessionRun[]): ModelUsageSummary[];
|
|
613
|
-
//#endregion
|
|
614
|
-
//#region src/chat/config.d.ts
|
|
615
|
-
/**
|
|
616
|
-
* Provider registry — a map keyed by `descriptor.key`. Passed verbatim to the
|
|
617
|
-
* chat engine; there is no implicit merge with built-ins. Hosts that want the
|
|
618
|
-
* four default providers spread {@link BUILTIN_PROVIDERS}; hosts that only
|
|
619
|
-
* want their own pass exactly their own.
|
|
620
|
-
*/
|
|
621
|
-
type ProviderRegistry = Readonly<Record<string, ProviderDescriptor>>;
|
|
622
|
-
/**
|
|
623
|
-
* Options accepted by `resolveConfig()` (and, transitively, by `runTui()` and
|
|
624
|
-
* any future GUI launcher). Every field is optional — defaults boot a working
|
|
625
|
-
* chat against the built-in providers with sessions stored under `~/.zidane/`.
|
|
626
|
-
*/
|
|
627
|
-
interface ChatOptions {
|
|
628
|
-
/**
|
|
629
|
-
* Directory name used under `storageDir` for sessions + state.
|
|
630
|
-
* Default: `'.zidane'` → `~/.zidane/sessions.db` + `~/.zidane/state.json`.
|
|
631
|
-
* Pass e.g. `'.myapp'` for `~/.myapp/...`, or `'myapp'` for a visible dir.
|
|
632
|
-
*/
|
|
633
|
-
prefix?: string;
|
|
634
|
-
/**
|
|
635
|
-
* Storage root. Defaults to the user's home directory. Combined with
|
|
636
|
-
* `prefix` to form the data directory.
|
|
637
|
-
*/
|
|
638
|
-
storageDir?: string;
|
|
639
|
-
/**
|
|
640
|
-
* Provider registry. Each value is a {@link ProviderDescriptor} carrying
|
|
641
|
-
* label + factory + credential metadata. **No automatic merge** — hosts
|
|
642
|
-
* pass exactly what they want.
|
|
643
|
-
*
|
|
644
|
-
* - Omitted → {@link BUILTIN_PROVIDERS} (anthropic + openai + openrouter + cerebras).
|
|
645
|
-
* - `providers: BUILTIN_PROVIDERS` → same as omitted, but explicit.
|
|
646
|
-
* - `providers: { anthropic: anthropicDescriptor }` → only Anthropic.
|
|
647
|
-
* - `providers: { ...BUILTIN_PROVIDERS, mine: customDescriptor }` → built-ins + custom.
|
|
648
|
-
* - `providers: { mine: customDescriptor }` → custom-only, **no built-ins**.
|
|
649
|
-
*/
|
|
650
|
-
providers?: ProviderRegistry;
|
|
651
|
-
/**
|
|
652
|
-
* Legacy single-agent preset (tools, system prompt, behavior). When set
|
|
653
|
-
* **without** {@link ChatOptions.agents}, the resolver wraps this preset
|
|
654
|
-
* into a one-entry {@link AgentRegistry} keyed `default` so existing
|
|
655
|
-
* callers keep working and the picker is effectively hidden.
|
|
656
|
-
*
|
|
657
|
-
* Prefer `agents` for any multi-profile setup. Passing both throws.
|
|
658
|
-
*/
|
|
659
|
-
preset?: Preset;
|
|
660
|
-
/**
|
|
661
|
-
* Agent profile registry — keyed by `profile.id`. Each profile bundles a
|
|
662
|
-
* preset with display metadata (label, description, accent). The TUI
|
|
663
|
-
* shows a picker (Ctrl+A) when more than one profile is registered.
|
|
664
|
-
*
|
|
665
|
-
* - Omitted (and `preset` omitted) → {@link BUILTIN_AGENTS} (Build + Plan).
|
|
666
|
-
* - Omitted but `preset` provided → single-entry registry around the preset.
|
|
667
|
-
* - Provided → host owns the registry; pass exactly what you want.
|
|
668
|
-
*
|
|
669
|
-
* Hosts mixing built-ins with their own typically spread:
|
|
670
|
-
* `agents: { ...BUILTIN_AGENTS, debug: myDebugProfile }`.
|
|
671
|
-
*/
|
|
672
|
-
agents?: AgentRegistry;
|
|
673
|
-
/**
|
|
674
|
-
* Id of the profile every fresh session (and the initial launch) starts
|
|
675
|
-
* in. Resolved against `agents`; unknown ids fall through to
|
|
676
|
-
* `DEFAULT_AGENT_ID`, then the registry's first key. Sessions remember
|
|
677
|
-
* the profile they were created with; this is never overridden by a
|
|
678
|
-
* previously picked profile.
|
|
679
|
-
*/
|
|
680
|
-
defaultAgent?: string;
|
|
681
|
-
/**
|
|
682
|
-
* Session store — either an instance or a factory called with the
|
|
683
|
-
* resolved storage paths. **Required** at the chat layer so this module
|
|
684
|
-
* stays platform-agnostic (no `bun:sqlite` baked in). Terminal hosts use
|
|
685
|
-
* `createTuiStore` from `zidane/session/sqlite`; a future GUI host can
|
|
686
|
-
* supply a different adapter (IndexedDB, remote API, in-memory) without
|
|
687
|
-
* touching this layer.
|
|
688
|
-
*
|
|
689
|
-
* ```ts
|
|
690
|
-
* import { createTuiStore } from 'zidane/session/sqlite'
|
|
691
|
-
*
|
|
692
|
-
* // Either pass a factory…
|
|
693
|
-
* resolveConfig({ store: paths => createTuiStore(paths.db) })
|
|
694
|
-
*
|
|
695
|
-
* // …or an instance built ahead of time.
|
|
696
|
-
* const store = createTuiStore('/path/to/sessions.db')
|
|
697
|
-
* resolveConfig({ store })
|
|
698
|
-
* ```
|
|
699
|
-
*/
|
|
700
|
-
store: SessionStore | ((paths: ResolvedPaths) => SessionStore);
|
|
701
|
-
/**
|
|
702
|
-
* Project-scoped session storage. Off by default; when it resolves
|
|
703
|
-
* to `true` and the launch happens inside a git repo, zidane
|
|
704
|
-
* auto-creates `<git-root>/.{prefix}/` and stores `sessions.db` +
|
|
705
|
-
* `state.json` there — so sessions, mcps.json, and skills all live
|
|
706
|
-
* alongside the project they belong to. Credentials and the
|
|
707
|
-
* cross-project safelist stay at `~/.{prefix}/` regardless.
|
|
708
|
-
*
|
|
709
|
-
* Precedence (most → least specific): `options.projectDb` >
|
|
710
|
-
* `ZIDANE_PROJECT_DB` env var (`0`/`false`/`off`/`no` → off,
|
|
711
|
-
* `1`/`true`/`on`/`yes` → on) > `~/.{prefix}/config.json`
|
|
712
|
-
* `projectDb` > `false`. Note the host option beats the env var —
|
|
713
|
-
* setting `ZIDANE_PROJECT_DB` has no effect when the host passes an
|
|
714
|
-
* explicit `projectDb`.
|
|
715
|
-
*
|
|
716
|
-
* When it resolves to `false`, OR when not inside a git repo,
|
|
717
|
-
* everything lives at `~/.{prefix}/` — the classic single-store
|
|
718
|
-
* layout.
|
|
719
|
-
*/
|
|
720
|
-
projectDb?: boolean;
|
|
721
|
-
/**
|
|
722
|
-
* Override for the project root. Defaults to `process.cwd()`. Hosts
|
|
723
|
-
* embedding the TUI from a non-CLI context (tests, daemons) can pin
|
|
724
|
-
* the cwd here so the git-root walk produces a stable result. Has no
|
|
725
|
-
* effect when `projectDb` resolves to `false`.
|
|
726
|
-
*/
|
|
727
|
-
cwd?: string;
|
|
728
|
-
/**
|
|
729
|
-
* Optional one-shot launch request used by CLI shells such as `zidane run`.
|
|
730
|
-
* The TUI opens/creates the requested session and submits the prompt after
|
|
731
|
-
* the first provider/session activation, while keeping the normal renderer
|
|
732
|
-
* and persistence behavior.
|
|
733
|
-
*/
|
|
734
|
-
launch?: StartLocalOptions;
|
|
735
|
-
/**
|
|
736
|
-
* Auto-update wiring. When set, the App quietly checks the npm registry
|
|
737
|
-
* for a newer release of `packageName` (matching the host's package),
|
|
738
|
-
* caches the result for a day under `userDir/`, and surfaces a passive
|
|
739
|
-
* `↑ vX.Y.Z` chip in the footer when one is available.
|
|
740
|
-
*
|
|
741
|
-
* Consumers wrapping `runTui` for their own CLI inline their own
|
|
742
|
-
* `package.json` version at build time and pass it here. The bundled
|
|
743
|
-
* `zidane-tui` binary wires this automatically in `tui/src/cli.ts`.
|
|
744
|
-
*
|
|
745
|
-
* Defaults to `null` — no auto-update plumbing, no network calls,
|
|
746
|
-
* no chip.
|
|
747
|
-
*/
|
|
748
|
-
autoUpdate?: AutoUpdateConfig | null;
|
|
749
|
-
/**
|
|
750
|
-
* Pre-built {@link ExtensionRegistry}. The `resolveConfig` surface is
|
|
751
|
-
* synchronous; extension `setup()` can be async, so the host must
|
|
752
|
-
* build the registry ahead of time and pass it here verbatim.
|
|
753
|
-
*
|
|
754
|
-
* Typical wiring (matches `runTui`):
|
|
755
|
-
*
|
|
756
|
-
* ```ts
|
|
757
|
-
* import {
|
|
758
|
-
* buildExtensionRegistry,
|
|
759
|
-
* discoverExtensions,
|
|
760
|
-
* inlineLoadedExtension,
|
|
761
|
-
* resolveConfig,
|
|
762
|
-
* } from 'zidane'
|
|
763
|
-
*
|
|
764
|
-
* const registry = await buildExtensionRegistry([
|
|
765
|
-
* // Project-scoped extensions run arbitrary local code — they stay
|
|
766
|
-
* // off unless the host establishes trust explicitly (or the user
|
|
767
|
-
* // sets ZIDANE_TRUST_PROJECT_EXTENSIONS=1).
|
|
768
|
-
* ...await discoverExtensions({ cwd, prefix, trustProjectExtensions: hostTrustsProject }),
|
|
769
|
-
* ...inlineDefinitions.map(inlineLoadedExtension),
|
|
770
|
-
* ])
|
|
771
|
-
* const config = resolveConfig({ ...opts, extensionRegistry: registry })
|
|
772
|
-
* ```
|
|
773
|
-
*
|
|
774
|
-
* Omitted → empty registry (no contributions).
|
|
775
|
-
*/
|
|
776
|
-
extensionRegistry?: ExtensionRegistry;
|
|
777
|
-
/**
|
|
778
|
-
* Extra extension scan roots the host used (or wants runtime re-discovery
|
|
779
|
-
* to use). Each path is a root containing extension dirs/packages:
|
|
780
|
-
* `<root>/<name>/index.ts`. `runTui` wires this from
|
|
781
|
-
* `ZIDANE_EXTENSION_DIRS` when omitted.
|
|
782
|
-
*/
|
|
783
|
-
extensionScanPaths?: readonly string[];
|
|
784
|
-
/**
|
|
785
|
-
* Extra Agent Plugin scan roots. Each path is a root containing plugin
|
|
786
|
-
* directories: `<root>/<name>/plugin.json`. `runTui` wires this from
|
|
787
|
-
* `ZIDANE_PLUGIN_DIRS` when omitted.
|
|
788
|
-
*
|
|
789
|
-
* Appended after the four default roots, so a project or user plugin still
|
|
790
|
-
* wins a name collision against a dev root.
|
|
791
|
-
*/
|
|
792
|
-
pluginScanPaths?: readonly string[];
|
|
793
|
-
/**
|
|
794
|
-
* Whether project-scoped extensions are trusted to run their (arbitrary,
|
|
795
|
-
* local) code. Off by default unless the embedding host has established
|
|
796
|
-
* project trust; falls back to `ZIDANE_TRUST_PROJECT_EXTENSIONS=1`.
|
|
797
|
-
*
|
|
798
|
-
* Surfaced on {@link ResolvedConfig.trustProjectExtensions} so a host
|
|
799
|
-
* that re-discovers extensions at runtime (e.g. the TUI on a working-
|
|
800
|
-
* directory change) reuses the same trust decision as boot.
|
|
801
|
-
*/
|
|
802
|
-
trustProjectExtensions?: boolean;
|
|
803
|
-
}
|
|
804
|
-
/**
|
|
805
|
-
* Host-supplied auto-update settings. The check itself is gated on
|
|
806
|
-
* `Settings.checkForUpdates`; passing a config wires the React plumbing.
|
|
807
|
-
*
|
|
808
|
-
* Hosts that want to publish their own consumer-facing package can pass
|
|
809
|
-
* different values without forking anything — the registry / channel /
|
|
810
|
-
* platform-package-prefix are all knobs.
|
|
811
|
-
*/
|
|
812
|
-
interface AutoUpdateConfig {
|
|
813
|
-
/** Top-level npm package the user installs (`zidane-tui`, `my-app`, …). */
|
|
814
|
-
packageName: string;
|
|
815
|
-
/** Inlined at build time — usually `pkg.version`. */
|
|
816
|
-
currentVersion: string;
|
|
817
|
-
/** dist-tag. Defaults to `'latest'`. */
|
|
818
|
-
channel?: string;
|
|
819
|
-
/** Registry base URL. Defaults to `'https://registry.npmjs.org'`. */
|
|
820
|
-
registry?: string;
|
|
821
|
-
/**
|
|
822
|
-
* Override the read-through cache lifetime in ms for the in-TUI hook.
|
|
823
|
-
* Defaults to `0` — every TUI launch fetches fresh, so the chip
|
|
824
|
-
* never lies. Pass a positive value (e.g. `3_600_000` for 1 h) to
|
|
825
|
-
* throttle the registry-poll rate at the cost of staleness.
|
|
826
|
-
*
|
|
827
|
-
* The on-disk cache is always WRITTEN, regardless of this value, so
|
|
828
|
-
* `zidane upgrade` and other tooling read paths benefit immediately.
|
|
829
|
-
*/
|
|
830
|
-
cacheTtlMs?: number;
|
|
831
|
-
/**
|
|
832
|
-
* Platform-package prefix used by the in-place self-update flow when
|
|
833
|
-
* resolving the per-arch tarball name. Defaults to `'<packageName>-'`
|
|
834
|
-
* (i.e. `zidane-tui-darwin-arm64` when `packageName === 'zidane-tui'`).
|
|
835
|
-
* Override only when your platform packages don't follow the `<name>-<key>`
|
|
836
|
-
* convention.
|
|
837
|
-
*/
|
|
838
|
-
platformPackagePrefix?: string;
|
|
839
|
-
/**
|
|
840
|
-
* Executable name on PATH for `packageName`, used to probe the version
|
|
841
|
-
* installed on disk (the `↻ vX` "restart to update" chip). Defaults to
|
|
842
|
-
* `packageName`; the TUI passes `'zidane'` for `zidane-tui`.
|
|
843
|
-
*/
|
|
844
|
-
binName?: string;
|
|
845
|
-
}
|
|
846
|
-
/** Resolved on-disk layout produced by {@link resolveConfig}. */
|
|
847
|
-
interface ResolvedPaths {
|
|
848
|
-
/**
|
|
849
|
-
* Effective data root — equals `userDir` (configDir) when project
|
|
850
|
-
* mode is off, `projectDir` when it's on. Kept for callers that
|
|
851
|
-
* wrote against the pre-project-db API; new code should reference
|
|
852
|
-
* the explicit slots (`configDir` / `dataDir` / `cacheDir` /
|
|
853
|
-
* `stateDir`) or `projectDir` / `db` / `state` instead.
|
|
854
|
-
*/
|
|
855
|
-
dir: string;
|
|
856
|
-
/**
|
|
857
|
-
* User-scoped config root — credentials, mcp-credentials, keybindings,
|
|
858
|
-
* `config.json`, `mcps.json`, skills. Legacy alias for `configDir`;
|
|
859
|
-
* existing call sites still reference `userDir`. In XDG mode this
|
|
860
|
-
* lands at `$XDG_CONFIG_HOME/zidane`; in legacy mode the four slots
|
|
861
|
-
* (config / data / state / cache) collapse to a single
|
|
862
|
-
* `<storageDir>/<prefix>` directory.
|
|
863
|
-
*/
|
|
864
|
-
userDir: string;
|
|
865
|
-
/**
|
|
866
|
-
* Project-scoped data root. Set to `<git-root>/<prefix>` when project
|
|
867
|
-
* mode resolved to ON and a git root was found. `null` otherwise.
|
|
868
|
-
*/
|
|
869
|
-
projectDir: string | null;
|
|
870
|
-
/** Resolved `sessions.db` path. Lives under `projectDir` when active, else `dataDir`. */
|
|
871
|
-
db: string;
|
|
872
|
-
/** Resolved `state.json` path. Lives under `projectDir` when active, else `stateDir`. */
|
|
873
|
-
state: string;
|
|
874
|
-
/**
|
|
875
|
-
* XDG config slot — `$XDG_CONFIG_HOME/zidane` on a fresh Linux install,
|
|
876
|
-
* `<storageDir>/<prefix>` (e.g. `~/.zidane/`) in legacy mode. Holds
|
|
877
|
-
* user-editable surface (`credentials.json`, `mcps.json`, …).
|
|
878
|
-
*/
|
|
879
|
-
configDir: string;
|
|
880
|
-
/**
|
|
881
|
-
* XDG data slot — `$XDG_DATA_HOME/zidane` on Linux, single-dir
|
|
882
|
-
* elsewhere. Holds long-lived chat history (`sessions.db`).
|
|
883
|
-
*/
|
|
884
|
-
dataDir: string;
|
|
885
|
-
/**
|
|
886
|
-
* XDG state slot — `$XDG_STATE_HOME/zidane` on Linux, single-dir
|
|
887
|
-
* elsewhere. Holds per-machine UI bookkeeping (`state.json`).
|
|
888
|
-
*/
|
|
889
|
-
stateDir: string;
|
|
890
|
-
/**
|
|
891
|
-
* XDG cache slot — `$XDG_CACHE_HOME/zidane` on Linux, single-dir
|
|
892
|
-
* elsewhere. Holds regenerable data: persisted tool results,
|
|
893
|
-
* background-task logs, auto-update registry cache.
|
|
894
|
-
*/
|
|
895
|
-
cacheDir: string;
|
|
896
|
-
/**
|
|
897
|
-
* Which resolution branch produced the layout. `'xdg'` when split
|
|
898
|
-
* across the four XDG dirs; one of `'legacy-explicit'`,
|
|
899
|
-
* `'legacy-existing'`, or `'default'` when the slots collapse to a
|
|
900
|
-
* single directory. Surfaced for diagnostics + tests.
|
|
901
|
-
*/
|
|
902
|
-
storageMode: StorageMode;
|
|
903
|
-
}
|
|
904
|
-
interface ResolvedConfig {
|
|
905
|
-
prefix: string;
|
|
906
|
-
storageDir: string;
|
|
907
|
-
paths: ResolvedPaths;
|
|
908
|
-
providers: ProviderRegistry;
|
|
909
|
-
/**
|
|
910
|
-
* Resolved profile registry. Always non-empty; the resolver throws when
|
|
911
|
-
* the host passes an empty `agents` map (same contract as `providers`).
|
|
912
|
-
*/
|
|
913
|
-
agents: AgentRegistry;
|
|
914
|
-
/** Id of the profile to activate on mount. Guaranteed to key into `agents`. */
|
|
915
|
-
initialAgentId: string;
|
|
916
|
-
store: SessionStore;
|
|
917
|
-
stateStore: StateStoreApi;
|
|
918
|
-
/** Lookup by `ProviderKey` returning the available models for the picker. */
|
|
919
|
-
modelsFor: (key: ProviderKey) => readonly ModelInfo[];
|
|
920
|
-
initialState: TuiState;
|
|
921
|
-
initialSettings: Partial<Settings>;
|
|
922
|
-
resumeProvider: ProviderAuth | null;
|
|
923
|
-
initialPicked: Picked | null;
|
|
924
|
-
/**
|
|
925
|
-
* Effective keybindings — defaults merged with the user-level
|
|
926
|
-
* `<userDir>/keybindings.json` (when present). Always fully-resolved
|
|
927
|
-
* so consumers can treat the record as total. See `./keybindings.ts`
|
|
928
|
-
* for the action catalog + spec format.
|
|
929
|
-
*/
|
|
930
|
-
keybindings: KeyBindings;
|
|
931
|
-
/**
|
|
932
|
-
* Resolved extension-contributed keybindings. Each entry pairs the
|
|
933
|
-
* extension's binding definition with the user's effective spec
|
|
934
|
-
* (override from `keybindings.json` when present, default
|
|
935
|
-
* otherwise). The TUI dispatcher iterates these alongside the
|
|
936
|
-
* built-in action catalog; the GUI host can do the same.
|
|
937
|
-
*
|
|
938
|
-
* Empty when no extension contributed a keybinding.
|
|
939
|
-
*/
|
|
940
|
-
extensionKeybindings: readonly ResolvedExtensionKeybinding[];
|
|
941
|
-
/**
|
|
942
|
-
* Resolved auto-update knobs (forwarded verbatim from `ChatOptions.autoUpdate`)
|
|
943
|
-
* — `null` when the host didn't wire one. The TUI feeds this into
|
|
944
|
-
* `useUpdateCheck` so the footer chip + the `zidane upgrade` subcommand
|
|
945
|
-
* share a single source of truth.
|
|
946
|
-
*/
|
|
947
|
-
autoUpdate: AutoUpdateConfig | null;
|
|
948
|
-
/**
|
|
949
|
-
* Merged extension contributions — the registry passed via
|
|
950
|
-
* {@link ChatOptions.extensionRegistry}, returned verbatim, or
|
|
951
|
-
* {@link EMPTY_EXTENSION_REGISTRY} when the host didn't pass one.
|
|
952
|
-
* `resolveConfig` is synchronous, so it never runs `setup()` itself;
|
|
953
|
-
* the host pre-builds the registry with `buildExtensionRegistry`.
|
|
954
|
-
*
|
|
955
|
-
* Renderer-side wiring reads `tuiContributions` / `guiContributions`
|
|
956
|
-
* to mount keybindings / footer hints / modals / panels. The
|
|
957
|
-
* `extensionPreset` field below carries the agent-side surface
|
|
958
|
-
* (tools / hooks / mcpServers / skills) ready to spread.
|
|
959
|
-
*/
|
|
960
|
-
extensions: ExtensionRegistry;
|
|
961
|
-
/**
|
|
962
|
-
* Extra extension scan roots used at boot. Runtime re-discovery (TUI cwd
|
|
963
|
-
* changes, future hosts) feeds these back into the shared discovery helper so
|
|
964
|
-
* local/dev package roots stay active after the initial launch.
|
|
965
|
-
*/
|
|
966
|
-
extensionScanPaths: readonly string[];
|
|
967
|
-
/**
|
|
968
|
-
* Extra Agent Plugin scan roots used at boot. Threaded into the discovery
|
|
969
|
-
* shell so a dev root stays active across project/cwd changes, same as
|
|
970
|
-
* {@link ResolvedConfig.extensionScanPaths}.
|
|
971
|
-
*/
|
|
972
|
-
pluginScanPaths: readonly string[];
|
|
973
|
-
/**
|
|
974
|
-
* Single {@link Preset} folded together from every extension's
|
|
975
|
-
* agent-side contributions. Hosts spread it into `createAgent()`
|
|
976
|
-
* alongside the active profile's preset:
|
|
977
|
-
*
|
|
978
|
-
* ```ts
|
|
979
|
-
* const profile = composePresets(extensionPreset, agentProfile.preset)
|
|
980
|
-
* const agent = createAgent({ ...profile, provider })
|
|
981
|
-
* ```
|
|
982
|
-
*
|
|
983
|
-
* Extension hooks are bucketed per event so every handler fires;
|
|
984
|
-
* tools and mcpServers compose with profile contributions via the
|
|
985
|
-
* usual `composePresets` rules. System-prompt fragments land as a
|
|
986
|
-
* trailing block on `preset.system` (host profiles that re-derive
|
|
987
|
-
* `system` per session — Build / Plan — append the fragments via
|
|
988
|
-
* the `system:transform` hook so the live system always carries
|
|
989
|
-
* them).
|
|
990
|
-
*/
|
|
991
|
-
extensionPreset: Preset;
|
|
992
|
-
/**
|
|
993
|
-
* System-prompt fragments contributed by extensions, in registration
|
|
994
|
-
* order. Surfaced separately from {@link extensionPreset} so hosts
|
|
995
|
-
* that re-derive `system` per session (Build / Plan in the TUI) can
|
|
996
|
-
* append them on `system:transform` instead of trying to merge two
|
|
997
|
-
* `preset.system` strings.
|
|
998
|
-
*/
|
|
999
|
-
extensionSystemFragments: readonly string[];
|
|
1000
|
-
/**
|
|
1001
|
-
* Spawnable subagents (adds) contributed by extensions, keyed by name.
|
|
1002
|
-
* Surfaced separately from {@link extensionPreset} (like
|
|
1003
|
-
* {@link extensionSystemFragments}) because subagents don't ride the
|
|
1004
|
-
* preset path — the host merges them onto the spawn tool's base
|
|
1005
|
-
* registry via `spawn.withSubagents(...)` at agent build time.
|
|
1006
|
-
*/
|
|
1007
|
-
extensionSubagents: SubagentRegistry;
|
|
1008
|
-
/**
|
|
1009
|
-
* Subagent edits contributed by extensions, keyed by target name and
|
|
1010
|
-
* composed in registration order. Applied (after the adds above) by
|
|
1011
|
-
* the host's `spawn.withSubagents(...)` call so extensions can edit or
|
|
1012
|
-
* delete host- / extension-provided subagents by name.
|
|
1013
|
-
*/
|
|
1014
|
-
extensionSubagentOverrides: Record<string, SubagentOverride>;
|
|
1015
|
-
/**
|
|
1016
|
-
* Merged extension-contributed config categories, keyed by category id.
|
|
1017
|
-
* Surfaced (alongside {@link extensionConfigItems}) so the TUI can read
|
|
1018
|
-
* the schema in-process — same way it reads `extensions.themes` — and
|
|
1019
|
-
* the GUI's `extensions:configSchema` IPC can serialize it.
|
|
1020
|
-
*/
|
|
1021
|
-
extensionConfigCategories: Readonly<Record<string, ExtensionConfigCategory>>;
|
|
1022
|
-
/**
|
|
1023
|
-
* Merged extension-contributed config items, namespaced
|
|
1024
|
-
* `extName → itemKey → item`. Each item carries its resolved
|
|
1025
|
-
* `category`; values are read default-first via the core resolver.
|
|
1026
|
-
*/
|
|
1027
|
-
extensionConfigItems: Readonly<Record<string, Readonly<Record<string, StoredExtensionConfigItem>>>>;
|
|
1028
|
-
/**
|
|
1029
|
-
* Resolved project-extension trust decision (option + env fallback).
|
|
1030
|
-
* Hosts that re-discover extensions at runtime feed this back into
|
|
1031
|
-
* {@link discoverAndBuildExtensionRegistry} so the rebuild trusts the
|
|
1032
|
-
* same scopes boot did.
|
|
1033
|
-
*/
|
|
1034
|
-
trustProjectExtensions: boolean;
|
|
1035
|
-
/**
|
|
1036
|
-
* Raw user `keybindings.json` object (post-JSONC-strip). Surfaced so a
|
|
1037
|
-
* host re-resolving {@link extensionKeybindings} at runtime (after an
|
|
1038
|
-
* extension registry rebuild) can reuse the same override source
|
|
1039
|
-
* without a second disk read.
|
|
1040
|
-
*/
|
|
1041
|
-
rawKeybindings: Readonly<Record<string, unknown>>;
|
|
1042
|
-
/** One-shot launch request forwarded from {@link ChatOptions.launch}. */
|
|
1043
|
-
launch: StartLocalOptions | null;
|
|
1044
|
-
}
|
|
1045
|
-
/**
|
|
1046
|
-
* Resolve user options into a fully-bound runtime config.
|
|
1047
|
-
*
|
|
1048
|
-
* NOT pure: besides disk reads, this mutates `process.env` so the harness
|
|
1049
|
-
* providers pick up the chat engine's credential store — it sets
|
|
1050
|
-
* `ZIDANE_CREDENTIALS_PATH` and reconciles stored API keys / OAuth entries
|
|
1051
|
-
* into env via `applyApiKeyEnv` (which can overwrite or delete ambient keys
|
|
1052
|
-
* like `ANTHROPIC_API_KEY`; see its JSDoc for the precedence rationale).
|
|
1053
|
-
*/
|
|
1054
|
-
declare function resolveConfig(options: ChatOptions): ResolvedConfig;
|
|
1055
|
-
/**
|
|
1056
|
-
* Compute the on-disk layout for a single TUI session. Public so hosts
|
|
1057
|
-
* (CLI tools, tests, scripted bootstraps) can ask "where will sessions
|
|
1058
|
-
* land?" without going through `resolveConfig`'s full machinery.
|
|
1059
|
-
*
|
|
1060
|
-
* Storage-slot resolution (config / data / state / cache) is delegated
|
|
1061
|
-
* to {@link resolveStorageDirs}. In legacy modes the four slots collapse
|
|
1062
|
-
* to a single `<storageDir>/<prefix>` directory; in XDG mode they fan
|
|
1063
|
-
* out into `$XDG_CONFIG_HOME/zidane`, `$XDG_DATA_HOME/zidane`,
|
|
1064
|
-
* `$XDG_STATE_HOME/zidane`, `$XDG_CACHE_HOME/zidane`. See the module
|
|
1065
|
-
* doc on `./xdg.ts` for the full precedence chain.
|
|
1066
|
-
*
|
|
1067
|
-
* Decision logic for project mode (least → most specific):
|
|
1068
|
-
*
|
|
1069
|
-
* 1. Default: OFF — sessions live in the user-scoped `dataDir`
|
|
1070
|
-
* and get scoped per-project via the `SessionData.projectRoot` tag.
|
|
1071
|
-
* 2. `<configDir>/config.json` `projectDb` flag (when present).
|
|
1072
|
-
* 3. `ZIDANE_PROJECT_DB` env var (`'0'` / `'false'` / `'off'` → off,
|
|
1073
|
-
* anything else true if set).
|
|
1074
|
-
* 4. `options.projectDb` (host call site).
|
|
1075
|
-
*
|
|
1076
|
-
* Project mode activates only when the resolution above lands on
|
|
1077
|
-
* `true` AND a git repo is found above `cwd`. Outside git or with the
|
|
1078
|
-
* flag off, sessions + state stay at the user-scoped slots.
|
|
1079
|
-
*
|
|
1080
|
-
* Auto-creates the project `.{prefix}/` directory when mode resolves
|
|
1081
|
-
* to ON (silent — mirrors `ensureStateDir`). User slots are created
|
|
1082
|
-
* lazily by the state-store + credentials writers; we don't pre-touch
|
|
1083
|
-
* them here so a read-only invocation stays read-only.
|
|
1084
|
-
*/
|
|
1085
|
-
declare function resolveStoragePaths(opts: {
|
|
1086
|
-
prefix: string; /** Explicit storage root. When set, forces legacy-explicit mode. */
|
|
1087
|
-
storageDir?: string;
|
|
1088
|
-
cwd: string; /** Host override for project mode. Beats the user-config + env-var sources. */
|
|
1089
|
-
projectDb?: boolean;
|
|
1090
|
-
}): ResolvedPaths;
|
|
1091
|
-
//#endregion
|
|
1092
|
-
//#region src/chat/credentials.d.ts
|
|
1093
|
-
interface ApiKeyCredential {
|
|
1094
|
-
kind: 'apikey';
|
|
1095
|
-
/**
|
|
1096
|
-
* Bearer API key. May be empty when the descriptor has no `envKey` and
|
|
1097
|
-
* authenticates entirely via {@link customFields} (e.g. the `local`
|
|
1098
|
-
* provider, where the auth signal is the configured base URL).
|
|
1099
|
-
*/
|
|
1100
|
-
value: string;
|
|
1101
|
-
/**
|
|
1102
|
-
* Free-form fields collected by the wizard from the descriptor's
|
|
1103
|
-
* `customFields` definitions. Keys match the descriptor field's `key`.
|
|
1104
|
-
* Mirrored into `process.env[field.envVar]` by `applyApiKeyEnv` so the
|
|
1105
|
-
* provider's factory can read them via the existing env-var convention.
|
|
1106
|
-
*/
|
|
1107
|
-
customFields?: Record<string, string>;
|
|
1108
|
-
}
|
|
1109
|
-
interface OAuthCredential {
|
|
1110
|
-
kind: 'oauth';
|
|
1111
|
-
access: string;
|
|
1112
|
-
refresh?: string;
|
|
1113
|
-
expires?: number;
|
|
1114
|
-
/**
|
|
1115
|
-
* User-given account name ("work", "personal"). Optional — absent reads as
|
|
1116
|
-
* `DEFAULT_OAUTH_ACCOUNT_LABEL` (see `oauthAccountLabel`). Survives token
|
|
1117
|
-
* refresh because the refresh path spreads the stored entry into the rotated
|
|
1118
|
-
* one (see `resolveOAuthApiKey`).
|
|
1119
|
-
*/
|
|
1120
|
-
label?: string;
|
|
1121
|
-
/** Provider-specific extras (e.g. OpenAI Codex `accountId`). */
|
|
1122
|
-
[extra: string]: unknown;
|
|
1123
|
-
}
|
|
1124
|
-
type ProviderCredential = ApiKeyCredential | OAuthCredential;
|
|
1125
|
-
/** One stored credential of a provider, addressed by the file key it lives at. */
|
|
1126
|
-
interface StoredCredential {
|
|
1127
|
-
/** File key — the selection identity for promote / remove / relabel. */
|
|
1128
|
-
key: string;
|
|
1129
|
-
credential: ProviderCredential;
|
|
1130
|
-
/** True for the canonical slot, i.e. the credential readers resolve. */
|
|
1131
|
-
active: boolean;
|
|
1132
|
-
}
|
|
1133
|
-
/** Top-level shape of `credentials.json` — keys are credential-file keys. */
|
|
1134
|
-
type CredentialsFile = Record<string, ProviderCredential>;
|
|
1135
|
-
/**
|
|
1136
|
-
* Resolve the credentials file path given the resolved TUI data directory
|
|
1137
|
-
* (typically `~/.zidane`, i.e. `config.paths.dir`).
|
|
1138
|
-
*
|
|
1139
|
-
* Matches the convention used elsewhere in the TUI (sessions.db, state.json)
|
|
1140
|
-
* so a single `ZIDANE_STORAGE_DIR` override moves the entire data root.
|
|
1141
|
-
*/
|
|
1142
|
-
declare function credentialsPath(dataDir: string): string;
|
|
1143
|
-
/**
|
|
1144
|
-
* Read credentials from disk.
|
|
1145
|
-
*
|
|
1146
|
-
* Returns `{}` when the file is missing or corrupt (last-ditch tolerance —
|
|
1147
|
-
* a hand-edit gone wrong shouldn't lock the user out of re-authing). On first
|
|
1148
|
-
* call with no file present, attempts a migration from `cwd/.credentials.json`
|
|
1149
|
-
* (the legacy location used by `bun run auth`).
|
|
1150
|
-
*/
|
|
1151
|
-
declare function readCredentials(dataDir: string): CredentialsFile;
|
|
1152
|
-
/** Read a single provider's credential (translating via the descriptor). */
|
|
1153
|
-
declare function readProviderCredential(dataDir: string, descriptor: ProviderDescriptor): ProviderCredential | undefined;
|
|
1154
|
-
/**
|
|
1155
|
-
* Both stored credentials for a provider: `active` is the one every reader
|
|
1156
|
-
* resolves, `alternate` is the stored-but-not-preferred one (if any).
|
|
1157
|
-
*
|
|
1158
|
-
* Predates multi-account and only sees the `#alt` slot; use
|
|
1159
|
-
* {@link readProviderCredentials} to list every stored account.
|
|
1160
|
-
*/
|
|
1161
|
-
declare function readProviderCredentialPair(dataDir: string, descriptor: ProviderDescriptor): {
|
|
1162
|
-
active?: ProviderCredential;
|
|
1163
|
-
alternate?: ProviderCredential;
|
|
1164
|
-
};
|
|
1165
|
-
/**
|
|
1166
|
-
* Every stored credential of a provider, active first.
|
|
1167
|
-
*
|
|
1168
|
-
* Tolerant of any kind in any slot: `#alt` is meant for the API key and
|
|
1169
|
-
* `#account:N` for OAuth accounts, but a file written by an older build (which
|
|
1170
|
-
* parked the OAuth alternate in `#alt`) must still list everything it holds.
|
|
1171
|
-
*/
|
|
1172
|
-
declare function readProviderCredentials(dataDir: string, descriptor: ProviderDescriptor): StoredCredential[];
|
|
1173
|
-
/** Pure form of {@link readProviderCredentials} over an already-read file. */
|
|
1174
|
-
declare function storedCredentialsOf(all: CredentialsFile, fileKey: string): StoredCredential[];
|
|
1175
|
-
/**
|
|
1176
|
-
* Write credentials atomically (write-then-rename) with mode 0o600.
|
|
1177
|
-
*
|
|
1178
|
-
* Atomic on the same filesystem — readers either see the previous file or the
|
|
1179
|
-
* new one, never a half-written intermediate. Creates the parent dir if needed
|
|
1180
|
-
* (first launch on a fresh machine: `~/.zidane/` may not exist yet).
|
|
1181
|
-
*/
|
|
1182
|
-
declare function writeCredentials(dataDir: string, creds: CredentialsFile): void;
|
|
1183
|
-
interface SetProviderCredentialOptions {
|
|
1184
|
-
/**
|
|
1185
|
-
* File key of the stored credential this one REPLACES (a re-auth of a known
|
|
1186
|
-
* account). The slot keeps its position — replacing the active one keeps it
|
|
1187
|
-
* active. When the key is no longer stored (removed from another window
|
|
1188
|
-
* mid-login), the credential is added as a new active account instead.
|
|
1189
|
-
*/
|
|
1190
|
-
replaceKey?: string;
|
|
1191
|
-
}
|
|
1192
|
-
/**
|
|
1193
|
-
* Store a credential as the provider's preferred one.
|
|
1194
|
-
*
|
|
1195
|
-
* The previous active credential is demoted, not destroyed: authenticating
|
|
1196
|
-
* with OAuth used to silently delete a working API key (and vice versa), and a
|
|
1197
|
-
* second OAuth login used to overwrite the first account. An API key moves to
|
|
1198
|
-
* {@link alternateCredKey}; an OAuth grant moves to the next free account slot.
|
|
1199
|
-
* Replacing an API key with an API key is a plain overwrite — there is only
|
|
1200
|
-
* ever one — and so is an OAuth login that names its predecessor via
|
|
1201
|
-
* `replaceKey`.
|
|
1202
|
-
*/
|
|
1203
|
-
declare function setProviderCredential(dataDir: string, descriptor: ProviderDescriptor, cred: ProviderCredential, opts?: SetProviderCredentialOptions): void;
|
|
1204
|
-
/**
|
|
1205
|
-
* Outcome of {@link setPreferredCredential}.
|
|
1206
|
-
*
|
|
1207
|
-
* Three states rather than a boolean because the two non-promoting cases need
|
|
1208
|
-
* opposite handling: `already-active` is a harmless idempotent call (the UI
|
|
1209
|
-
* repaints and moves on), while `not-stored` means the caller asked for a
|
|
1210
|
-
* credential that does not exist and should say so.
|
|
1211
|
-
*/
|
|
1212
|
-
type PreferCredentialResult = 'promoted' | 'already-active' | 'not-stored';
|
|
1213
|
-
/**
|
|
1214
|
-
* What {@link setPreferredCredential} promotes: a stored credential by file
|
|
1215
|
-
* key (from {@link readProviderCredentials} / `AuthMethod.key`), or the first
|
|
1216
|
-
* stored credential of a kind — the pre-multi-account form, still right when
|
|
1217
|
-
* the caller only knows "switch to the API key".
|
|
1218
|
-
*/
|
|
1219
|
-
type PreferredCredentialTarget = ProviderCredential['kind'] | {
|
|
1220
|
-
key: string;
|
|
1221
|
-
};
|
|
1222
|
-
/**
|
|
1223
|
-
* Make one of the provider's stored credentials the preferred one.
|
|
1224
|
-
*
|
|
1225
|
-
* Swaps the target into the canonical slot and parks the previous active one
|
|
1226
|
-
* (see {@link parkDemoted}). Returns which of the three outcomes happened so a
|
|
1227
|
-
* caller cannot report a swap that provably did not occur — the write is
|
|
1228
|
-
* silent either way, and a success-shaped `void` was a trap for any caller that
|
|
1229
|
-
* trusted it instead of refetching.
|
|
1230
|
-
*/
|
|
1231
|
-
declare function setPreferredCredential(dataDir: string, descriptor: ProviderDescriptor, target: PreferredCredentialTarget): PreferCredentialResult;
|
|
1232
|
-
/**
|
|
1233
|
-
* Drop ONE stored credential. Removing the active one promotes a survivor —
|
|
1234
|
-
* another credential of the same kind when there is one (a second OAuth
|
|
1235
|
-
* account), else whatever is left — so the provider does not go dark while it
|
|
1236
|
-
* still holds a working credential. Returns false when `key` was not stored.
|
|
1237
|
-
*/
|
|
1238
|
-
declare function removeStoredCredential(dataDir: string, descriptor: ProviderDescriptor, key: string): boolean;
|
|
1239
|
-
/**
|
|
1240
|
-
* Name a stored OAuth account. An empty label drops the field, which reads
|
|
1241
|
-
* back as {@link DEFAULT_OAUTH_ACCOUNT_LABEL}. Returns false when `key` holds
|
|
1242
|
-
* no OAuth credential.
|
|
1243
|
-
*/
|
|
1244
|
-
declare function setCredentialLabel(dataDir: string, descriptor: ProviderDescriptor, key: string, label: string): boolean;
|
|
1245
|
-
/**
|
|
1246
|
-
* Sign a provider out — drops EVERY stored credential.
|
|
1247
|
-
*
|
|
1248
|
-
* "Signed out" has to mean the provider resolves nothing afterwards, which is
|
|
1249
|
-
* what this has always guaranteed and what callers named it for; promoting a
|
|
1250
|
-
* survivor instead would silently leave the provider authenticated through
|
|
1251
|
-
* another source. Callers that want that behavior use
|
|
1252
|
-
* {@link removeStoredCredential} on the one slot they mean.
|
|
1253
|
-
*/
|
|
1254
|
-
declare function removeProviderCredential(dataDir: string, descriptor: ProviderDescriptor): void;
|
|
1255
|
-
/**
|
|
1256
|
-
* Reconcile `process.env` with the stored credentials so the harness providers
|
|
1257
|
-
* pick up the wizard's output via their existing env-var resolution. Called
|
|
1258
|
-
* once at TUI launch after the credentials file has been resolved.
|
|
1259
|
-
*
|
|
1260
|
-
* **Precedence: stored credential > ambient env.** When the user has run the
|
|
1261
|
-
* auth wizard, that's an explicit, recent action — it MUST win over whatever
|
|
1262
|
-
* ambient value is already in `process.env`. Otherwise an upgrade reliably
|
|
1263
|
-
* breaks for anyone whose cwd happens to contain a stale `.env`: Bun
|
|
1264
|
-
* auto-loads `.env` from cwd into `process.env` before our code runs, the
|
|
1265
|
-
* legacy `bun run auth` used to upsert tokens into `cwd/.env`, and even a
|
|
1266
|
-
* one-off `export ANTHROPIC_API_KEY=…` from months ago in the user's shell rc
|
|
1267
|
-
* can outlive its usefulness. None of those should override a key the user
|
|
1268
|
-
* just typed into the wizard.
|
|
1269
|
-
*
|
|
1270
|
-
* Three cases per registered provider with an `envKey`:
|
|
1271
|
-
*
|
|
1272
|
-
* 1. Stored `kind: 'apikey'` → overwrite env with the stored value. Wizard
|
|
1273
|
-
* wins. A debug log fires when this clobbers a different ambient value.
|
|
1274
|
-
* 2. Stored `kind: 'oauth'` → DELETE env, so {@link resolveOAuthApiKey}
|
|
1275
|
-
* falls through to the file-read + refresh path. A stale OAuth token
|
|
1276
|
-
* in env would otherwise short-circuit refresh and get rejected.
|
|
1277
|
-
* 3. No stored entry → leave env alone. Env-only setups (no wizard run yet,
|
|
1278
|
-
* hosts driving zidane purely from secrets management) keep working.
|
|
1279
|
-
*
|
|
1280
|
-
* To opt out and force ambient env to win again, the user signs the provider
|
|
1281
|
-
* out via the wizard (which deletes the stored entry → case 3 above).
|
|
1282
|
-
*
|
|
1283
|
-
* Descriptors without an `envKey` (OAuth-only providers, custom providers
|
|
1284
|
-
* that bypass env-var resolution) are skipped silently.
|
|
1285
|
-
*/
|
|
1286
|
-
declare function applyApiKeyEnv(dataDir: string, registry: Readonly<Record<string, ProviderDescriptor>>, opts?: {
|
|
1287
|
-
log?: (message: string) => void;
|
|
1288
|
-
}): void;
|
|
1289
|
-
//#endregion
|
|
1290
|
-
//#region src/chat/mcps-discovery.d.ts
|
|
1291
|
-
/**
|
|
1292
|
-
* One entry in the discovered list. `path` is the source file (one of
|
|
1293
|
-
* the `mcp(s).json` variants under `.agents/` or `.{prefix}/`) so a
|
|
1294
|
-
* Settings picker can show "Defined in ~/.zidane/mcp.json" tooltips
|
|
1295
|
-
* and the user can tell which file declared what.
|
|
1296
|
-
*/
|
|
1297
|
-
interface DiscoveredMcp {
|
|
1298
|
-
config: McpServerConfig;
|
|
1299
|
-
source: 'project' | 'user';
|
|
1300
|
-
path: string;
|
|
1301
|
-
}
|
|
1302
|
-
/**
|
|
1303
|
-
* Search order for MCP config files — see {@link projectUserPaths}.
|
|
1304
|
-
*
|
|
1305
|
-
* Both `mcps.json` (zidane's canonical name) and `mcp.json` (Cursor /
|
|
1306
|
-
* common ecosystem alias) are picked up from every search root. The
|
|
1307
|
-
* canonical name wins within the same directory; across files the
|
|
1308
|
-
* usual first-found-by-name dedup applies, so `mcp.json` effectively
|
|
1309
|
-
* merges its non-overlapping entries on top of `mcps.json`.
|
|
1310
|
-
*
|
|
1311
|
-
* Order per scope (project beats user):
|
|
1312
|
-
* 1. `{project}/.agents/mcps.json`
|
|
1313
|
-
* 2. `{project}/.agents/mcp.json`
|
|
1314
|
-
* 3. `{project}/.{prefix}/mcps.json`
|
|
1315
|
-
* 4. `{project}/.{prefix}/mcp.json`
|
|
1316
|
-
* 5. `~/.agents/mcps.json`
|
|
1317
|
-
* 6. `~/.agents/mcp.json`
|
|
1318
|
-
* 7. `~/.{prefix}/mcps.json`
|
|
1319
|
-
* 8. `~/.{prefix}/mcp.json`
|
|
1320
|
-
*
|
|
1321
|
-
* Non-existent files are skipped without error.
|
|
1322
|
-
*/
|
|
1323
|
-
declare function defaultMcpsConfigPaths(opts?: {
|
|
1324
|
-
cwd?: string;
|
|
1325
|
-
home?: string;
|
|
1326
|
-
prefix?: string;
|
|
1327
|
-
}): {
|
|
1328
|
-
path: string;
|
|
1329
|
-
source: 'project' | 'user';
|
|
1330
|
-
}[];
|
|
1331
|
-
/**
|
|
1332
|
-
* Parse one `mcps.json` file. Canonical zidane shape is a flat array; the
|
|
1333
|
-
* other shapes exist for copy-paste from neighboring tools:
|
|
1334
|
-
*
|
|
1335
|
-
* - `McpServerConfig[]` — flat array (recommended).
|
|
1336
|
-
* - `{ name: {...} }` — name-keyed map.
|
|
1337
|
-
* - `{ "mcpServers": { name: {...} } }` — Claude Desktop / Claude Code /
|
|
1338
|
-
* Cursor wrapper. Unwrapped before normalization (otherwise
|
|
1339
|
-
* `normalizeMcpServers` would treat the whole wrapper as a single server).
|
|
1340
|
-
*
|
|
1341
|
-
* Per-entry `enabled: false` (Cursor runtime state) drops the entry — same
|
|
1342
|
-
* intent as the source tool. Use the TUI toggle list for "show but disabled".
|
|
1343
|
-
*
|
|
1344
|
-
* Tolerant to common copy-paste artifacts: when strict `JSON.parse` fails,
|
|
1345
|
-
* retries after normalizing invisible whitespace that's valid Unicode but
|
|
1346
|
-
* not valid JSON whitespace (BOM, NBSP, zero-width spaces, line/paragraph
|
|
1347
|
-
* separators) — only OUTSIDE string literals, so user data isn't mutated.
|
|
1348
|
-
* If the sanitized version still fails, throws the original error with a
|
|
1349
|
-
* targeted hint when NBSPs are present.
|
|
1350
|
-
*
|
|
1351
|
-
* Validation flows through `normalizeMcpServers` so the result matches
|
|
1352
|
-
* what `createAgent` accepts. Throws on truly malformed JSON; the caller
|
|
1353
|
-
* decides whether to surface or swallow.
|
|
1354
|
-
*/
|
|
1355
|
-
declare function parseMcpsFile(text: string): McpServerConfig[];
|
|
1356
|
-
/**
|
|
1357
|
-
* Per-file failure surfaced from {@link discoverProjectMcps}. The TUI shows
|
|
1358
|
-
* these in the MCP settings empty / preamble state so a malformed
|
|
1359
|
-
* `mcps.json` doesn't look identical to a missing one.
|
|
1360
|
-
*/
|
|
1361
|
-
interface DiscoveryError {
|
|
1362
|
-
path: string;
|
|
1363
|
-
source: 'project' | 'user';
|
|
1364
|
-
message: string;
|
|
1365
|
-
/**
|
|
1366
|
-
* A deliberate, documented behavior being reported (e.g. the ruler stdio
|
|
1367
|
-
* security carve-out) rather than a failure. Hosts should style these as
|
|
1368
|
-
* info, not error — crying wolf over a working default trains users to
|
|
1369
|
-
* ignore the channel that also carries real parse failures.
|
|
1370
|
-
*/
|
|
1371
|
-
informational?: boolean;
|
|
1372
|
-
}
|
|
1373
|
-
/**
|
|
1374
|
-
* Result of {@link discoverProjectMcps}. `servers` is the per-source-priority
|
|
1375
|
-
* merged list (project beats user, first-found wins on name collision).
|
|
1376
|
-
* `errors` is one entry per file that existed but failed to parse, plus
|
|
1377
|
-
* informational entries for servers a security gate skipped (ruler stdio
|
|
1378
|
-
* without the foreign-agent opt-in) — empty on the happy path.
|
|
1379
|
-
*/
|
|
1380
|
-
interface DiscoveryResult {
|
|
1381
|
-
servers: DiscoveredMcp[];
|
|
1382
|
-
errors: DiscoveryError[];
|
|
1383
|
-
}
|
|
1384
|
-
/**
|
|
1385
|
-
* Walk the default config paths, parse every file that exists, and return
|
|
1386
|
-
* `{ servers, errors }` in source-priority order. Project entries appear
|
|
1387
|
-
* before user entries; first occurrence of a `name` wins (later
|
|
1388
|
-
* duplicates dropped).
|
|
1389
|
-
*
|
|
1390
|
-
* Parse failures are captured into `errors` rather than thrown — the picker
|
|
1391
|
-
* surfaces them while still showing whatever DID parse. A `ZIDANE_DEBUG`
|
|
1392
|
-
* log line is also emitted for ops visibility.
|
|
1393
|
-
*/
|
|
1394
|
-
declare function discoverProjectMcps(opts?: {
|
|
1395
|
-
cwd?: string;
|
|
1396
|
-
home?: string;
|
|
1397
|
-
prefix?: string;
|
|
1398
|
-
/**
|
|
1399
|
-
* Also read MCP configs other agents maintain (Claude Code, Codex,
|
|
1400
|
-
* Pi) — see `foreign-configs.ts`. Mirrors the `importForeignConfigs`
|
|
1401
|
-
* setting; native locations always win name collisions, and project
|
|
1402
|
-
* beats user within each group.
|
|
1403
|
-
*/
|
|
1404
|
-
foreignAgents?: boolean;
|
|
1405
|
-
/**
|
|
1406
|
-
* Also read Ruler MCP configs (`.ruler/ruler.toml` + `mcp.json`,
|
|
1407
|
-
* project and XDG-global) — see `ruler-configs.ts`. Mirrors the
|
|
1408
|
-
* `importRulerConfigs` setting; same collision rules as above.
|
|
1409
|
-
*/
|
|
1410
|
-
ruler?: boolean;
|
|
1411
|
-
}): DiscoveryResult;
|
|
1412
|
-
/**
|
|
1413
|
-
* Map a user-toggled enable list onto the `mcpServers` array the agent
|
|
1414
|
-
* receives. Conventions match `buildSkillsConfig`:
|
|
1415
|
-
*
|
|
1416
|
-
* - `enabled === undefined` → every discovered server enabled (default).
|
|
1417
|
-
* - `enabled === []` → no servers (the agent runs MCP-less).
|
|
1418
|
-
* - `enabled === [names]` → allowlist; servers not in the list are
|
|
1419
|
-
* dropped.
|
|
1420
|
-
*
|
|
1421
|
-
* `disabledTools` is the per-server tool deny-list from
|
|
1422
|
-
* `Settings.disabledMcpTools`. For each server that survives the
|
|
1423
|
-
* server-level enable filter, the per-tool names are merged into
|
|
1424
|
-
* `McpServerConfig.disabledTools` via **union** with anything the JSON
|
|
1425
|
-
* file already pinned — a tool listed in either source is dropped.
|
|
1426
|
-
* Union (not override) keeps JSON-side policy stable: a server file
|
|
1427
|
-
* that pins `disabledTools: ['dangerous_tool']` can't be re-enabled
|
|
1428
|
-
* via the UI by accident.
|
|
1429
|
-
*
|
|
1430
|
-
* `enabledTools` (JSON-side allowlist) takes precedence over the
|
|
1431
|
-
* UI-side deny-list when both are set on the same server — the
|
|
1432
|
-
* allowlist's "only these" semantics would be meaningless if a UI
|
|
1433
|
-
* deny-list could subtract from it again. We don't emit `disabledTools`
|
|
1434
|
-
* when `enabledTools` is present.
|
|
1435
|
-
*
|
|
1436
|
-
* Returns a fresh array — callers can mutate without affecting the
|
|
1437
|
-
* underlying discovery list. Per-server config objects are also fresh
|
|
1438
|
-
* copies (shallow), so the merged `disabledTools` doesn't leak back
|
|
1439
|
-
* onto the discovery catalog.
|
|
1440
|
-
*/
|
|
1441
|
-
declare function buildMcpServers(opts: {
|
|
1442
|
-
discovered: readonly DiscoveredMcp[];
|
|
1443
|
-
enabled?: readonly string[];
|
|
1444
|
-
disabledTools?: Record<string, readonly string[]>;
|
|
1445
|
-
}): McpServerConfig[];
|
|
1446
|
-
/**
|
|
1447
|
-
* Dedup a merged MCP-server list by `name`. First entry wins.
|
|
1448
|
-
*
|
|
1449
|
-
* Applied at agent build across every source that can contribute a server —
|
|
1450
|
-
* `mcps.json`, Agent Plugins, launch options, extensions — so the earliest
|
|
1451
|
-
* source in that order takes precedence.
|
|
1452
|
-
*
|
|
1453
|
-
* Drops are REPORTED rather than silent, via `onDropped`. A plugin shipping a
|
|
1454
|
-
* `github` server loses to a `github` in `mcps.json`, and nothing downstream
|
|
1455
|
-
* says so: the plugin's settings row still counts the server it shipped,
|
|
1456
|
-
* because the row renders what the PACKAGE declares and only this merge knows
|
|
1457
|
-
* what survived. That mirrors how the skills side reports the same class of
|
|
1458
|
-
* event — `resolveSkills` emits `name-collision-shadowed` on the winner rather
|
|
1459
|
-
* than annotating the loser.
|
|
1460
|
-
*
|
|
1461
|
-
* The reporter is injected rather than calling a logger directly so this stays
|
|
1462
|
-
* a pure function of its input, testable without a logging shim. It lives here
|
|
1463
|
-
* beside {@link buildMcpServers} rather than in the TUI because merge
|
|
1464
|
-
* precedence is a config concern, not a rendering one.
|
|
1465
|
-
*/
|
|
1466
|
-
declare function dedupMcpServersByName<T extends {
|
|
1467
|
-
name: string;
|
|
1468
|
-
}>(servers: readonly T[], onDropped?: (names: readonly string[]) => void): T[];
|
|
1469
|
-
//#endregion
|
|
1470
|
-
//#region src/chat/project-user-paths.d.ts
|
|
1471
|
-
/**
|
|
1472
|
-
* Shared search-path builder for project + user config discovery.
|
|
1473
|
-
*
|
|
1474
|
-
* Both Skills (`skills/<name>/SKILL.md`) and MCP servers (`mcps.json`)
|
|
1475
|
-
* follow the same first-found-wins order:
|
|
1476
|
-
*
|
|
1477
|
-
* 1. `{project-root}/.agents/<sub>` — project, agnostic convention
|
|
1478
|
-
* 2. `{project-root}/.{prefix}/<sub>` — project, zidane (`.zidane` default)
|
|
1479
|
-
* 3. `~/.agents/<sub>` — user, agnostic
|
|
1480
|
-
* 4. `~/.{prefix}/<sub>` — user, zidane
|
|
1481
|
-
*
|
|
1482
|
-
* `{project-root}` is the git root walked up from `cwd` when present,
|
|
1483
|
-
* else `cwd` itself. This pairs with the project-scoped session
|
|
1484
|
-
* storage (`resolveStoragePaths`) so all three project-aware surfaces
|
|
1485
|
-
* — sessions, mcps, skills — anchor at the same `.{prefix}/`.
|
|
1486
|
-
*
|
|
1487
|
-
* Centralizing the pattern keeps the four paths in one place — a third
|
|
1488
|
-
* discovery surface (hooks, rules, …) gets the same convention for free
|
|
1489
|
-
* and stays in lock-step on a prefix bump.
|
|
1490
|
-
*/
|
|
1491
|
-
/** A discovered path tagged with whether it lives in the project or the user dir. */
|
|
1492
|
-
interface ProjectUserPath {
|
|
1493
|
-
path: string;
|
|
1494
|
-
source: 'project' | 'user';
|
|
1495
|
-
}
|
|
1496
|
-
/**
|
|
1497
|
-
* Resolve the four search paths for a given subdirectory (`skills`,
|
|
1498
|
-
* `mcps.json`, …). Returns absolute paths regardless of whether they
|
|
1499
|
-
* exist — the caller chooses to `existsSync`-filter or feed straight
|
|
1500
|
-
* into a tolerant discovery routine.
|
|
1501
|
-
*/
|
|
1502
|
-
declare function projectUserPaths(opts: {
|
|
1503
|
-
/** Subdirectory or filename relative to each search root. E.g. `'skills'`, `'mcps.json'`. */subPath: string; /** Discovery cwd. Default: `process.cwd()`. */
|
|
1504
|
-
cwd?: string; /** User home directory. Default: `os.homedir()`. */
|
|
1505
|
-
home?: string; /** Storage prefix. Leading dot tolerated. Default: `'.zidane'`. */
|
|
1506
|
-
prefix?: string;
|
|
1507
|
-
}): ProjectUserPath[];
|
|
1508
|
-
//#endregion
|
|
1509
|
-
//#region src/chat/plugins-discovery.d.ts
|
|
1510
|
-
/** One plugin found on disk, loaded (successfully or not). */
|
|
1511
|
-
interface DiscoveredPlugin {
|
|
1512
|
-
/**
|
|
1513
|
-
* Identity for dedup + the enabled allowlist. The manifest's `name` when
|
|
1514
|
-
* the plugin loaded; the directory basename when it didn't, so a rejected
|
|
1515
|
-
* plugin still has something stable to key a row and a toggle on.
|
|
1516
|
-
*/
|
|
1517
|
-
name: string;
|
|
1518
|
-
/** Load result. Check `ok` before trusting `manifest`. */
|
|
1519
|
-
plugin: LoadedPlugin;
|
|
1520
|
-
/** Which search root it came from. */
|
|
1521
|
-
source: 'project' | 'user';
|
|
1522
|
-
/** Plugin root directory, as discovered. */
|
|
1523
|
-
path: string;
|
|
1524
|
-
}
|
|
1525
|
-
/**
|
|
1526
|
-
* Load every plugin reachable from the default search roots.
|
|
1527
|
-
*
|
|
1528
|
-
* Each immediate child directory of a root is one plugin — the same
|
|
1529
|
-
* depth-1 rule the spec applies inside `skills/`. A child that isn't a
|
|
1530
|
-
* directory, or that holds no `plugin.json`, is silently skipped: dropping a
|
|
1531
|
-
* README next to your plugins is not an error.
|
|
1532
|
-
*
|
|
1533
|
-
* Dedup is by plugin NAME, not directory name, because the manifest owns
|
|
1534
|
-
* identity — two directories called `tools/` shipping different plugins are
|
|
1535
|
-
* two plugins, and one plugin vendored at two scopes is one plugin.
|
|
1536
|
-
*/
|
|
1537
|
-
declare function discoverProjectPlugins(opts?: {
|
|
1538
|
-
cwd?: string;
|
|
1539
|
-
home?: string;
|
|
1540
|
-
prefix?: string;
|
|
1541
|
-
/**
|
|
1542
|
-
* Extra scan roots appended AFTER the four defaults — typically from
|
|
1543
|
-
* {@link parsePluginScanPathEnv}. Ordered last so a real project or user
|
|
1544
|
-
* plugin always wins a name collision against a dev/host-provided root.
|
|
1545
|
-
*
|
|
1546
|
-
* Scoped `'project'`: they're supplied by whoever launched the process, the
|
|
1547
|
-
* same trust level as a plugin sitting in the working tree.
|
|
1548
|
-
*/
|
|
1549
|
-
extraRoots?: readonly string[];
|
|
1550
|
-
signal?: AbortSignal;
|
|
1551
|
-
}): Promise<{
|
|
1552
|
-
plugins: DiscoveredPlugin[];
|
|
1553
|
-
errors: DiscoveryError[];
|
|
1554
|
-
}>;
|
|
1555
|
-
/**
|
|
1556
|
-
* Map the user's enabled-plugin list onto the contributions a host merges
|
|
1557
|
-
* into the agent.
|
|
1558
|
-
*
|
|
1559
|
-
* Conventions match `enabledSkills` / `enabledMcps`:
|
|
1560
|
-
* - `undefined` → every discovered plugin is enabled (default)
|
|
1561
|
-
* - `[]` → all off
|
|
1562
|
-
* - `[names]` → allowlist
|
|
1563
|
-
*
|
|
1564
|
-
* A plugin that failed to load contributes nothing regardless of the
|
|
1565
|
-
* allowlist — `ok: false` means components were never discovered.
|
|
1566
|
-
*/
|
|
1567
|
-
declare function buildPluginContributions(opts: {
|
|
1568
|
-
discovered: readonly DiscoveredPlugin[];
|
|
1569
|
-
enabled?: readonly string[];
|
|
1570
|
-
}): {
|
|
1571
|
-
skills: SkillConfig[];
|
|
1572
|
-
mcpServers: McpServerConfig[];
|
|
1573
|
-
};
|
|
1574
|
-
//#endregion
|
|
1575
|
-
//#region src/chat/enabled-toggle-set.d.ts
|
|
1576
|
-
/**
|
|
1577
|
-
* Renderer-agnostic state machine for an "enabled allowlist" — the shape
|
|
1578
|
-
* used by `settings.enabledSkills` / `settings.enabledMcps` (and any future
|
|
1579
|
-
* `enabledX` toggle backed by a `Settings` field).
|
|
1580
|
-
*
|
|
1581
|
-
* Semantics, kept identical across all three call sites:
|
|
1582
|
-
* - `undefined` → every catalog entry is enabled (default — user has
|
|
1583
|
-
* never opened the picker; new entries flow in).
|
|
1584
|
-
* - `[]` → the whole subsystem is off.
|
|
1585
|
-
* - `[names]` → explicit allowlist; the persisted shape stays a
|
|
1586
|
-
* concrete array once the user has toggled anything.
|
|
1587
|
-
*
|
|
1588
|
-
* The hook exposes a live `enabledSet` (Set<string>) + a `toggle(name)`
|
|
1589
|
-
* callback that persists the result through `useSettings().setSetting`.
|
|
1590
|
-
* The first toggle seeds the persisted allowlist from the current catalog
|
|
1591
|
-
* so newly-added entries don't silently drop on the next launch.
|
|
1592
|
-
*
|
|
1593
|
-
* Renderer-neutral: works for the TUI's `<ToggleListModal>`, a GUI
|
|
1594
|
-
* checkbox list, a CLI flag tool. Hook tests live alongside the chat
|
|
1595
|
-
* suite; the rendering layer is tested where it lives.
|
|
1596
|
-
*/
|
|
1597
|
-
/** Settings keys whose value type is `readonly string[] | undefined`. */
|
|
1598
|
-
type EnabledAllowlistKey = 'enabledSkills' | 'enabledMcps' | 'enabledExtensions' | 'enabledPlugins';
|
|
1599
|
-
interface EnabledToggleSet {
|
|
1600
|
-
/** Live set of enabled names — `Set` for O(1) `has`. */
|
|
1601
|
-
enabledSet: ReadonlySet<string>;
|
|
1602
|
-
/** Toggle one name on/off; persists immediately via `setSetting`. */
|
|
1603
|
-
toggle: (name: string) => void;
|
|
1604
|
-
}
|
|
1605
|
-
/**
|
|
1606
|
-
* Bind an "enabled allowlist" setting to a discovered catalog.
|
|
1607
|
-
*
|
|
1608
|
-
* `keyOf` extracts the persisted identity from a catalog entry (skill name,
|
|
1609
|
-
* MCP server name, …). Pass a stable, collision-free key — the persisted
|
|
1610
|
-
* allowlist is keyed against it forever.
|
|
1611
|
-
*/
|
|
1612
|
-
declare function useEnabledToggleSet<T>(opts: {
|
|
1613
|
-
catalog: readonly T[];
|
|
1614
|
-
keyOf: (entry: T) => string;
|
|
1615
|
-
settingKey: EnabledAllowlistKey;
|
|
1616
|
-
/**
|
|
1617
|
-
* Names that survive the persisted-allowlist GC even when absent from
|
|
1618
|
-
* `catalog`. Use when the catalog deliberately hides entries that are
|
|
1619
|
-
* still known to exist — e.g. errored / untrusted extensions are kept
|
|
1620
|
-
* out of the toggle list but must not be dropped from the allowlist
|
|
1621
|
-
* by an unrelated toggle. Defaults to the catalog keys.
|
|
1622
|
-
*/
|
|
1623
|
-
gcKeys?: readonly string[];
|
|
1624
|
-
}): EnabledToggleSet;
|
|
1625
|
-
//#endregion
|
|
1626
|
-
//#region src/chat/session-export.d.ts
|
|
1627
|
-
/** File format supported by the exporter. */
|
|
1628
|
-
type SessionExportFormat = 'markdown' | 'json';
|
|
1629
|
-
/**
|
|
1630
|
-
* Anchor for the resolved destination directory:
|
|
1631
|
-
* - `project` — the nearest enclosing git repository (`<repoRoot>/.{prefix}/sessions`)
|
|
1632
|
-
* - `home` — fallback when no repo was found (`~/.{prefix}/sessions`)
|
|
1633
|
-
*/
|
|
1634
|
-
type SessionExportAnchor = 'project' | 'home';
|
|
1635
|
-
/** Resolved file destination for a session export. */
|
|
1636
|
-
interface SessionExportTarget {
|
|
1637
|
-
/** Absolute directory holding the file. May not exist yet — `writeSessionExport` creates it on demand. */
|
|
1638
|
-
dir: string;
|
|
1639
|
-
/** Absolute path of the file (`dir/{id}.{ext}`). */
|
|
1640
|
-
filepath: string;
|
|
1641
|
-
/** Where the destination was anchored. */
|
|
1642
|
-
anchor: SessionExportAnchor;
|
|
1643
|
-
}
|
|
1644
|
-
/** Options shared by every resolve / write entry-point. */
|
|
1645
|
-
interface ResolveOptions {
|
|
1646
|
-
/** Discovery cwd. Defaults to `process.cwd()`. */
|
|
1647
|
-
cwd?: string;
|
|
1648
|
-
/** User home directory. Defaults to `os.homedir()`. */
|
|
1649
|
-
home?: string;
|
|
1650
|
-
/**
|
|
1651
|
-
* Storage prefix. Leading dot tolerated (`zidane` and `.zidane` are
|
|
1652
|
-
* equivalent). Defaults to `'.zidane'`.
|
|
1653
|
-
*/
|
|
1654
|
-
prefix?: string;
|
|
1655
|
-
}
|
|
1656
|
-
/**
|
|
1657
|
-
* Resolve the export target for a session id + format. Pure: no fs
|
|
1658
|
-
* write happens here, the caller decides whether to `existsSync` the
|
|
1659
|
-
* directory or hand the path to `writeSessionExport`.
|
|
1660
|
-
*
|
|
1661
|
-
* Anchor selection walks upward from `cwd` looking for a `.git` entry;
|
|
1662
|
-
* the first hit anchors to that repo's root (`project`). When the walk
|
|
1663
|
-
* exits without finding `.git`, the destination anchors to `home`.
|
|
1664
|
-
*
|
|
1665
|
-
* @throws RangeError when `sessionId` would resolve to an empty / `..`
|
|
1666
|
-
* filename — defensive guard against malicious or buggy callers
|
|
1667
|
-
* crossing into a sibling directory via the id.
|
|
1668
|
-
*/
|
|
1669
|
-
declare function resolveSessionExportTarget(opts: {
|
|
1670
|
-
sessionId: string;
|
|
1671
|
-
format: SessionExportFormat;
|
|
1672
|
-
} & ResolveOptions): SessionExportTarget;
|
|
1673
|
-
/**
|
|
1674
|
-
* Render a session into a string in the requested format.
|
|
1675
|
-
*
|
|
1676
|
-
* `markdown` produces a human-readable transcript: a YAML-free header
|
|
1677
|
-
* block with the title and a one-line `id · created · turns` summary,
|
|
1678
|
-
* a stats section (turns / runs / tokens / cost / status), then a
|
|
1679
|
-
* `## Conversation` block where each turn renders as `### N. role ·
|
|
1680
|
-
* run_X · ISO-date` with text, thinking, tool calls, and tool results
|
|
1681
|
-
* formatted as appropriate fenced blocks. Useful for sharing a session
|
|
1682
|
-
* with a teammate or pasting into an issue tracker.
|
|
1683
|
-
*
|
|
1684
|
-
* `json` returns a 2-space-indented, deterministic dump of the full
|
|
1685
|
-
* `SessionData` blob. Useful for re-importing into the store or for
|
|
1686
|
-
* post-hoc analysis tooling.
|
|
1687
|
-
*/
|
|
1688
|
-
declare function renderSession(session: SessionData, format: SessionExportFormat): string;
|
|
1689
|
-
/**
|
|
1690
|
-
* Render `session` and write the resulting bytes to disk. Returns the
|
|
1691
|
-
* resolved target so the caller can show the user where the file
|
|
1692
|
-
* landed. The parent directory is created on demand (`recursive: true`)
|
|
1693
|
-
* — first-time exports don't need any pre-flight setup.
|
|
1694
|
-
*/
|
|
1695
|
-
declare function writeSessionExport(opts: {
|
|
1696
|
-
session: SessionData;
|
|
1697
|
-
format: SessionExportFormat;
|
|
1698
|
-
} & ResolveOptions): Promise<SessionExportTarget>;
|
|
1699
|
-
//#endregion
|
|
1700
|
-
//#region src/chat/transcript-anchors.d.ts
|
|
1701
|
-
/**
|
|
1702
|
-
* One entry in the partitioned transcript-row list. Single events
|
|
1703
|
-
* render as a normal row; a `child-run` groups ONE subagent's events
|
|
1704
|
-
* from a consecutive run of subagent output into one bordered box
|
|
1705
|
-
* (concurrent siblings get a `child-run` each, so their rows never
|
|
1706
|
-
* braid together inside a shared frame); `tool-group`s
|
|
1707
|
-
* collect ALL parent-owned tool/tool-result events of one exchange
|
|
1708
|
-
* into a single collapsible summary row (`Settings.groupToolCalls`);
|
|
1709
|
-
* an `exchange-fold` goes further (`Settings.transcriptDensity:
|
|
1710
|
-
* 'compact'`) and takes every thinking, tool and worker event of the
|
|
1711
|
-
* exchange, leaving only the prompt and the assistant's prose in place.
|
|
1712
|
-
* `key` is stable across re-partitions of the same stream (derived
|
|
1713
|
-
* from the first grouped event) so expand state survives appends.
|
|
1714
|
-
*
|
|
1715
|
-
* Currently produced by the TUI's `partitionTranscript`; a GUI shell
|
|
1716
|
-
* grouping subagent runs the same way can produce the same shape.
|
|
1717
|
-
*/
|
|
1718
|
-
type TranscriptItem = {
|
|
1719
|
-
kind: 'event';
|
|
1720
|
-
event: StreamEvent;
|
|
1721
|
-
previous?: StreamEvent;
|
|
1722
|
-
} | {
|
|
1723
|
-
kind: 'child-run';
|
|
1724
|
-
events: StreamEvent[];
|
|
1725
|
-
previous?: StreamEvent;
|
|
1726
|
-
} | {
|
|
1727
|
-
kind: 'tool-group';
|
|
1728
|
-
key: string;
|
|
1729
|
-
events: StreamEvent[];
|
|
1730
|
-
previous?: StreamEvent;
|
|
1731
|
-
} | {
|
|
1732
|
-
kind: 'exchange-fold';
|
|
1733
|
-
key: string;
|
|
1734
|
-
events: StreamEvent[];
|
|
1735
|
-
previous?: StreamEvent;
|
|
1736
|
-
};
|
|
1737
|
-
/**
|
|
1738
|
-
* Per-item anchor ids for auto-scroll. Walks `items` in render order
|
|
1739
|
-
* and, for each event, returns either:
|
|
1740
|
-
* - `'turn-anchor-<turnId>'` — the first event of this turn (the
|
|
1741
|
-
* scroll target).
|
|
1742
|
-
* - `undefined` — later event of an already-tagged turn (or a
|
|
1743
|
-
* synthetic event with no `turnId`).
|
|
1744
|
-
*
|
|
1745
|
-
* `ids[i]` is a tuple per item: length 1 for plain events, length N
|
|
1746
|
-
* for subagent runs (one entry per inner event). `idByTurn` is the
|
|
1747
|
-
* inverse lookup used by the scroll effect. `lastTurnId` is the
|
|
1748
|
-
* most-recently-rendered turn — the scroll effect special-cases it to
|
|
1749
|
-
* snap to bottom rather than scroll the anchor into view (which would
|
|
1750
|
-
* stop short of the actual tail).
|
|
1751
|
-
*
|
|
1752
|
-
* Exported so the anchor-tagging matrix can be unit-tested without
|
|
1753
|
-
* rendering anything.
|
|
1754
|
-
*/
|
|
1755
|
-
declare function computeTurnAnchors(items: readonly TranscriptItem[]): {
|
|
1756
|
-
idByTurn: ReadonlyMap<string, string>;
|
|
1757
|
-
ids: readonly (readonly (string | undefined)[])[];
|
|
1758
|
-
lastTurnId: string | undefined;
|
|
1759
|
-
};
|
|
1760
|
-
//#endregion
|
|
1761
|
-
export { ModelUsageSummary as $, ProviderCredential as A, groupBindings as At, removeStoredCredential as B, Hint as Bt, discoverProjectMcps as C, KeyBindingDef as Ct, OAuthCredential as D, ResolvedExtensionKeybinding as Dt, CredentialsFile as E, ParsedBinding as Et, readCredentials as F, readKeybindings as Ft, writeCredentials as G, setPreferredCredential as H, hintsLength as Ht, readProviderCredential as I, readKeybindingsRaw as It, ProviderRegistry as J, AutoUpdateConfig as K, readProviderCredentialPair as L, resolveExtensionKeybindings as Lt, StoredCredential as M, matchesBinding as Mt, applyApiKeyEnv as N, mergeKeybindings as Nt, PreferCredentialResult as O, ensureKeybindingsFile as Ot, credentialsPath as P, parseBindingSpec as Pt, resolveStoragePaths as Q, readProviderCredentials as R, stripJsonComments as Rt, defaultMcpsConfigPaths as S, KeyAction as St, ApiKeyCredential as T, KeyBindings as Tt, setProviderCredential as U, truncateTrailing as Ut, setCredentialLabel as V, clipHintsToWidth as Vt, storedCredentialsOf as W, ResolvedPaths as X, ResolvedConfig as Y, resolveConfig as Z, DiscoveredMcp as _, usageByModel as _t, SessionExportTarget as a, eventsFromTurns as at, buildMcpServers as b, KEYBINDING_DEF_BY_ACTION as bt, writeSessionExport as c, loadState as ct, useEnabledToggleSet as d, stripSpawnTokensLine as dt, StateStoreApi as et, DiscoveredPlugin as f, sumRunCosts as ft, projectUserPaths as g, updateToolEventOutcomes as gt, ProjectUserPath as h, toolResultText as ht, SessionExportFormat as i, deriveSessionTitle as it, SetProviderCredentialOptions as j, keybindingsPath as jt, PreferredCredentialTarget as k, formatBindingForDisplay as kt, EnabledAllowlistKey as l, marginTopFor as lt, discoverProjectPlugins as m, toolCallPreview as mt, computeTurnAnchors as n, compactSummaryEvent as nt, renderSession as o, lastContextSizeFromTurns as ot, buildPluginContributions as p, titleFromTurns as pt, ChatOptions as q, SessionExportAnchor as r, createStateStore as rt, resolveSessionExportTarget as s, listSessionMeta as st, TranscriptItem as t, TuiState as tt, EnabledToggleSet as u, saveState as ut, DiscoveryError as v, DEFAULT_KEYBINDINGS as vt, parseMcpsFile as w, KeyBindingSection as wt, dedupMcpServersByName as x, KEYBINDING_KEY_COL_WIDTH as xt, DiscoveryResult as y, KEYBINDING_DEFS as yt, removeProviderCredential as z, EMPTY_HINTS as zt };
|
|
1762
|
-
//# sourceMappingURL=transcript-anchors-BeudMbXx.d.ts.map
|