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
|
@@ -0,0 +1,511 @@
|
|
|
1
|
+
import { t as escapeXml } from "./xml-D5HBhJle.js";
|
|
2
|
+
import { i as fmtCost } from "./format-C2NQEVUH.js";
|
|
3
|
+
//#region src/chat/run-receipt.ts
|
|
4
|
+
/** Leads the turn count: one cycle = one model round trip. */
|
|
5
|
+
const RUN_RECEIPT_TURN_GLYPH = "↻";
|
|
6
|
+
/** `1.2k` / `48k` / `1.3M` — token counts are read at a glance, not counted. */
|
|
7
|
+
function formatTokenCount(tokens) {
|
|
8
|
+
if (tokens >= 1e6) return `${(tokens / 1e6).toFixed(1)}M`;
|
|
9
|
+
if (tokens >= 1e3) return `${(tokens / 1e3).toFixed(tokens >= 1e4 ? 0 : 1)}k`;
|
|
10
|
+
return String(tokens);
|
|
11
|
+
}
|
|
12
|
+
/** `2m18s` / `48s` / `<1s` / `1h05m`. Compact — this is a receipt, not a profiler. */
|
|
13
|
+
function formatRunDuration(ms) {
|
|
14
|
+
if (ms < 1e3) return "<1s";
|
|
15
|
+
const s = Math.round(ms / 1e3);
|
|
16
|
+
if (s < 60) return `${s}s`;
|
|
17
|
+
const m = Math.floor(s / 60);
|
|
18
|
+
const rest = s % 60;
|
|
19
|
+
if (m < 60) return rest ? `${m}m${String(rest).padStart(2, "0")}s` : `${m}m`;
|
|
20
|
+
return `${Math.floor(m / 60)}h${String(m % 60).padStart(2, "0")}m`;
|
|
21
|
+
}
|
|
22
|
+
/** `$0.04`, or four decimals under a cent so a cheap run is not shown as `$0.00`. Same as `fmtCost`. */
|
|
23
|
+
const formatCostUsd = fmtCost;
|
|
24
|
+
/**
|
|
25
|
+
* Build the receipt for a run record. `now` stands in for `endedAt` when the
|
|
26
|
+
* record is not finalized yet (`run:end` is broadcast a beat before it is).
|
|
27
|
+
*/
|
|
28
|
+
function runReceiptFromRun(run, now = Date.now()) {
|
|
29
|
+
const sumIn = (u) => u.input + (u.cacheRead ?? 0) + (u.cacheCreation ?? 0);
|
|
30
|
+
const usage = run.totalUsage ? {
|
|
31
|
+
input: sumIn(run.totalUsage),
|
|
32
|
+
output: run.totalUsage.output
|
|
33
|
+
} : run.turnUsage?.reduce((acc, u) => ({
|
|
34
|
+
input: acc.input + sumIn(u),
|
|
35
|
+
output: acc.output + u.output
|
|
36
|
+
}), {
|
|
37
|
+
input: 0,
|
|
38
|
+
output: 0
|
|
39
|
+
});
|
|
40
|
+
const models = (run.turnUsage ?? []).map((u) => u.modelId).filter((m) => typeof m === "string" && m.length > 0);
|
|
41
|
+
const modelId = models.at(-1);
|
|
42
|
+
const otherModels = modelId ? new Set(models).size - 1 : 0;
|
|
43
|
+
const durationMs = (run.endedAt ?? now) - run.startedAt;
|
|
44
|
+
const cost = run.cost ?? run.turnUsage?.reduce((n, u) => n + (u.cost ?? 0), 0) ?? 0;
|
|
45
|
+
const turns = run.turns ?? run.turnUsage?.length ?? 0;
|
|
46
|
+
let genMs = 0;
|
|
47
|
+
let genOut = 0;
|
|
48
|
+
for (const u of run.turnUsage ?? []) {
|
|
49
|
+
if (u.streamDurationMs === void 0 || u.output <= 0) continue;
|
|
50
|
+
const ms = u.streamDurationMs - (u.timeToFirstTokenMs ?? 0);
|
|
51
|
+
if (ms <= 0) continue;
|
|
52
|
+
genMs += ms;
|
|
53
|
+
genOut += u.output;
|
|
54
|
+
}
|
|
55
|
+
const tokensPerSecond = genMs > 0 && genOut > 0 ? genOut * 1e3 / genMs : void 0;
|
|
56
|
+
return {
|
|
57
|
+
...modelId ? { modelId } : {},
|
|
58
|
+
...otherModels > 0 ? { otherModels } : {},
|
|
59
|
+
...durationMs > 0 ? { durationMs } : {},
|
|
60
|
+
...turns > 0 ? { turns } : {},
|
|
61
|
+
...cost > 0 ? { costUsd: cost } : {},
|
|
62
|
+
...usage && usage.input > 0 ? { tokensIn: usage.input } : {},
|
|
63
|
+
...usage && usage.output > 0 ? { tokensOut: usage.output } : {},
|
|
64
|
+
...tokensPerSecond !== void 0 ? { tokensPerSecond } : {}
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
/** `42 tk/s`; one decimal under 10 so a slow model is not shown as `0 tk/s`. */
|
|
68
|
+
function formatTokensPerSecond(tps) {
|
|
69
|
+
return `${tps < 10 ? tps.toFixed(1) : Math.round(tps).toString()} tk/s`;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* The receipt's cells, in display order. Renderers join them with their own
|
|
73
|
+
* separator, tint them by `kind`, and truncate to their own width; the CONTENT
|
|
74
|
+
* is fixed here.
|
|
75
|
+
*/
|
|
76
|
+
function formatRunReceiptCells(r) {
|
|
77
|
+
const cells = [];
|
|
78
|
+
if (r.modelId) cells.push({
|
|
79
|
+
kind: "model",
|
|
80
|
+
text: r.otherModels ? `${r.modelId} +${r.otherModels}` : r.modelId
|
|
81
|
+
});
|
|
82
|
+
if (r.durationMs !== void 0) cells.push({
|
|
83
|
+
kind: "duration",
|
|
84
|
+
text: formatRunDuration(r.durationMs)
|
|
85
|
+
});
|
|
86
|
+
if (r.turns !== void 0) cells.push({
|
|
87
|
+
kind: "turns",
|
|
88
|
+
text: `↻${r.turns}`
|
|
89
|
+
});
|
|
90
|
+
if (r.costUsd !== void 0) cells.push({
|
|
91
|
+
kind: "cost",
|
|
92
|
+
text: fmtCost(r.costUsd)
|
|
93
|
+
});
|
|
94
|
+
if (r.tokensIn !== void 0 || r.tokensOut !== void 0) {
|
|
95
|
+
const segments = [{
|
|
96
|
+
kind: "tokens-in",
|
|
97
|
+
text: `↑${formatTokenCount(r.tokensIn ?? 0)}`
|
|
98
|
+
}, {
|
|
99
|
+
kind: "tokens-out",
|
|
100
|
+
text: `↓${formatTokenCount(r.tokensOut ?? 0)}`
|
|
101
|
+
}];
|
|
102
|
+
cells.push({
|
|
103
|
+
kind: "tokens",
|
|
104
|
+
text: segments.map((seg) => seg.text).join(" "),
|
|
105
|
+
segments
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
if (r.tokensPerSecond !== void 0) cells.push({
|
|
109
|
+
kind: "speed",
|
|
110
|
+
text: formatTokensPerSecond(r.tokensPerSecond)
|
|
111
|
+
});
|
|
112
|
+
return cells;
|
|
113
|
+
}
|
|
114
|
+
/** The glyph that leads the line on every surface. */
|
|
115
|
+
const RUN_RECEIPT_GLYPH = "≡";
|
|
116
|
+
/**
|
|
117
|
+
* Fit cells to `width` columns for a tinted renderer: returns the cells that
|
|
118
|
+
* fit whole, plus whether the last one was cut. A cut cell is truncated with
|
|
119
|
+
* `…`; anything after it is dropped. Never wraps. `prefix` is the columns the
|
|
120
|
+
* renderer already spent (glyph + space).
|
|
121
|
+
*/
|
|
122
|
+
function fitRunReceiptCells(cells, width, prefix = 0) {
|
|
123
|
+
let used = prefix;
|
|
124
|
+
const out = [];
|
|
125
|
+
for (const cell of cells) {
|
|
126
|
+
const need = (out.length ? 3 : 0) + cell.text.length;
|
|
127
|
+
if (used + need <= width) {
|
|
128
|
+
out.push(cell);
|
|
129
|
+
used += need;
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
const room = width - used - (out.length ? 3 : 0);
|
|
133
|
+
if (room >= 2) out.push({
|
|
134
|
+
kind: cell.kind,
|
|
135
|
+
text: `${cell.text.slice(0, room - 1).trimEnd()}…`
|
|
136
|
+
});
|
|
137
|
+
break;
|
|
138
|
+
}
|
|
139
|
+
return out;
|
|
140
|
+
}
|
|
141
|
+
/** One line, ` · `-joined, ellipsized to `width` columns. Never wraps. */
|
|
142
|
+
function formatRunReceiptLine(r, width = Number.POSITIVE_INFINITY) {
|
|
143
|
+
const line = formatRunReceiptCells(r).map((c) => c.text).join(" · ");
|
|
144
|
+
if (line.length <= width) return line;
|
|
145
|
+
if (width <= 1) return width === 1 ? "…" : "";
|
|
146
|
+
return `${line.slice(0, width - 1).trimEnd()}…`;
|
|
147
|
+
}
|
|
148
|
+
/** Anything to show? A run with no record data renders no line at all. */
|
|
149
|
+
function hasRunReceipt(r) {
|
|
150
|
+
return formatRunReceiptCells(r).length > 0;
|
|
151
|
+
}
|
|
152
|
+
//#endregion
|
|
153
|
+
//#region src/chat/orchestration.ts
|
|
154
|
+
/**
|
|
155
|
+
* Orchestration — the pure model for a "main" session that drives others.
|
|
156
|
+
*
|
|
157
|
+
* A main session is an ordinary session with a role, and a worker is an
|
|
158
|
+
* ordinary session with a parent pointer. Both are `metadata` keys, so every
|
|
159
|
+
* existing surface (sidebar, history, attach, search, replay) works on them
|
|
160
|
+
* with no special cases; only the surfaces that WANT to treat them specially
|
|
161
|
+
* (pinning, the event row, the jump shortcut) read these keys.
|
|
162
|
+
*
|
|
163
|
+
* This is deliberately not `spawn`. A spawned child is ephemeral, inline, and
|
|
164
|
+
* dies with the parent's run; a worker is a persistent, resumable session with
|
|
165
|
+
* its own cwd, model chain, todos and history, visible in every window, and it
|
|
166
|
+
* outlives the main's run. The parent pointer is what makes them a tree.
|
|
167
|
+
*
|
|
168
|
+
* Node-free: re-exported from `zidane/chat/pure` for the Electron renderer,
|
|
169
|
+
* which needs `isMainSession` / `orchestratedBy` for pinning and the event row.
|
|
170
|
+
*/
|
|
171
|
+
/** Title the main session is created with. Users can rename it; the ROLE is what matters. */
|
|
172
|
+
const MAIN_SESSION_TITLE = "Main";
|
|
173
|
+
/** `session.metadata.role` — present and `'main'` on the one orchestrating session. */
|
|
174
|
+
const SESSION_ROLE_KEY = "role";
|
|
175
|
+
/** `session.metadata.orchestratedBy` — the main session's id, on a worker. */
|
|
176
|
+
const ORCHESTRATED_BY_KEY = "orchestratedBy";
|
|
177
|
+
/** Type guard over untrusted metadata. */
|
|
178
|
+
function isMainSession(metadata) {
|
|
179
|
+
return metadata?.[SESSION_ROLE_KEY] === "main";
|
|
180
|
+
}
|
|
181
|
+
/** The main session id a worker reports to, or `null` for an ordinary session. */
|
|
182
|
+
function orchestratedBy(metadata) {
|
|
183
|
+
const value = metadata?.[ORCHESTRATED_BY_KEY];
|
|
184
|
+
return typeof value === "string" && value.length > 0 ? value : null;
|
|
185
|
+
}
|
|
186
|
+
/** Tools whose `path` input means "this file changed". */
|
|
187
|
+
const CHANGE_TOOLS = /* @__PURE__ */ new Set([
|
|
188
|
+
"edit",
|
|
189
|
+
"multi_edit",
|
|
190
|
+
"write_file"
|
|
191
|
+
]);
|
|
192
|
+
const ARTIFACT_PATH_CAP = 12;
|
|
193
|
+
/**
|
|
194
|
+
* What a run touched, read off its assistant turns' tool calls. Only the
|
|
195
|
+
* tools that MUTATE count as "changed" — reads are not artifacts. Capped so a
|
|
196
|
+
* refactor across a hundred files does not turn the event into a manifest;
|
|
197
|
+
* the count still tells the truth.
|
|
198
|
+
*/
|
|
199
|
+
function artifactsFromTurns(turns) {
|
|
200
|
+
const changed = [];
|
|
201
|
+
const seen = /* @__PURE__ */ new Set();
|
|
202
|
+
let commands = 0;
|
|
203
|
+
let toolCalls = 0;
|
|
204
|
+
for (const turn of turns) {
|
|
205
|
+
if (turn.role !== "assistant") continue;
|
|
206
|
+
for (const block of turn.content) {
|
|
207
|
+
if (block.type !== "tool_call" || !block.name) continue;
|
|
208
|
+
toolCalls++;
|
|
209
|
+
if (block.name === "shell") commands++;
|
|
210
|
+
if (CHANGE_TOOLS.has(block.name)) {
|
|
211
|
+
const path = block.input?.path;
|
|
212
|
+
if (typeof path === "string" && path && !seen.has(path)) {
|
|
213
|
+
seen.add(path);
|
|
214
|
+
changed.push(path);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
if (toolCalls === 0) return void 0;
|
|
220
|
+
return {
|
|
221
|
+
changed: changed.slice(0, ARTIFACT_PATH_CAP),
|
|
222
|
+
commands,
|
|
223
|
+
toolCalls
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
const STATUSES = [
|
|
227
|
+
"done",
|
|
228
|
+
"error",
|
|
229
|
+
"cancelled",
|
|
230
|
+
"needs-attention"
|
|
231
|
+
];
|
|
232
|
+
/**
|
|
233
|
+
* Wire format between the harness and the model — and, because it is persisted
|
|
234
|
+
* inside the user turn's text block, between a live session and its replay.
|
|
235
|
+
*
|
|
236
|
+
* Follows `<task-notification>` exactly: child-tag XML, one block per event,
|
|
237
|
+
* escaped with `escapeXml`. The model already knows this shape as "the harness
|
|
238
|
+
* telling me something", which is the point — a main that mistook a worker
|
|
239
|
+
* report for a human instruction would act on it as one. `eventsFromTurns`
|
|
240
|
+
* detects the block on replay and re-synthesizes the structured row instead of
|
|
241
|
+
* painting the raw XML as a user prompt.
|
|
242
|
+
*/
|
|
243
|
+
function renderSessionEventXml(event) {
|
|
244
|
+
const tag = (name, value) => value === void 0 ? [] : [` <${name}>${escapeXml(String(value))}</${name}>`];
|
|
245
|
+
return [
|
|
246
|
+
"<session-event>",
|
|
247
|
+
...tag("session-id", event.sessionId),
|
|
248
|
+
...tag("title", event.title),
|
|
249
|
+
...tag("status", event.status),
|
|
250
|
+
...tag("at", event.at),
|
|
251
|
+
...tag("cwd", event.cwd ?? ""),
|
|
252
|
+
...tag("cost-usd", event.costUsd),
|
|
253
|
+
...tag("duration-ms", event.durationMs),
|
|
254
|
+
...tag("tokens", event.tokens),
|
|
255
|
+
...tag("turns", event.turns),
|
|
256
|
+
...tag("worker", event.worker === void 0 ? void 0 : String(event.worker)),
|
|
257
|
+
...tag("seq", event.seq),
|
|
258
|
+
...tag("finish-reason", event.finishReason),
|
|
259
|
+
...tag("error", event.error),
|
|
260
|
+
...tag("detail", event.detail),
|
|
261
|
+
...tag("goal", event.goal),
|
|
262
|
+
...event.artifacts ? [
|
|
263
|
+
` <artifacts tool-calls="${event.artifacts.toolCalls}" commands="${event.artifacts.commands}">`,
|
|
264
|
+
...event.artifacts.changed.map((p) => ` <changed>${escapeXml(p)}</changed>`),
|
|
265
|
+
" </artifacts>"
|
|
266
|
+
] : [],
|
|
267
|
+
...tag("summary", event.summary),
|
|
268
|
+
"</session-event>"
|
|
269
|
+
].join("\n");
|
|
270
|
+
}
|
|
271
|
+
const SESSION_EVENT_RE = /^\s*<session-event>([\s\S]*?)<\/session-event>\s*$/;
|
|
272
|
+
const FIELD = {
|
|
273
|
+
sessionId: /<session-id>([\s\S]*?)<\/session-id>/,
|
|
274
|
+
title: /<title>([\s\S]*?)<\/title>/,
|
|
275
|
+
status: /<status>([\s\S]*?)<\/status>/,
|
|
276
|
+
at: /<at>([\s\S]*?)<\/at>/,
|
|
277
|
+
cwd: /<cwd>([\s\S]*?)<\/cwd>/,
|
|
278
|
+
costUsd: /<cost-usd>([\s\S]*?)<\/cost-usd>/,
|
|
279
|
+
durationMs: /<duration-ms>([\s\S]*?)<\/duration-ms>/,
|
|
280
|
+
tokens: /<tokens>([\s\S]*?)<\/tokens>/,
|
|
281
|
+
turns: /<turns>([\s\S]*?)<\/turns>/,
|
|
282
|
+
worker: /<worker>([\s\S]*?)<\/worker>/,
|
|
283
|
+
error: /<error>([\s\S]*?)<\/error>/,
|
|
284
|
+
detail: /<detail>([\s\S]*?)<\/detail>/,
|
|
285
|
+
seq: /<seq>([\s\S]*?)<\/seq>/,
|
|
286
|
+
goal: /<goal>([\s\S]*?)<\/goal>/,
|
|
287
|
+
finishReason: /<finish-reason>([\s\S]*?)<\/finish-reason>/,
|
|
288
|
+
artifacts: /<artifacts tool-calls="(\d+)" commands="(\d+)">([\s\S]*?)<\/artifacts>/,
|
|
289
|
+
summary: /<summary>([\s\S]*?)<\/summary>/
|
|
290
|
+
};
|
|
291
|
+
const CHANGED_RE = /<changed>([\s\S]*?)<\/changed>/g;
|
|
292
|
+
const FINISH_REASONS = /* @__PURE__ */ new Set([
|
|
293
|
+
"length",
|
|
294
|
+
"pause",
|
|
295
|
+
"content-filter"
|
|
296
|
+
]);
|
|
297
|
+
/**
|
|
298
|
+
* Inverse of {@link renderSessionEventXml}. Untrusted input — it comes off disk
|
|
299
|
+
* and outlives this module's versions — so it validates each field and returns
|
|
300
|
+
* `null` for anything malformed, in which case the turn replays as the plain
|
|
301
|
+
* user text it structurally is.
|
|
302
|
+
*/
|
|
303
|
+
function parseSessionEventXml(text) {
|
|
304
|
+
const m = text.match(SESSION_EVENT_RE);
|
|
305
|
+
if (!m) return null;
|
|
306
|
+
const body = m[1];
|
|
307
|
+
const pick = (re) => {
|
|
308
|
+
const inner = body.match(re);
|
|
309
|
+
return inner ? unescapeXml(inner[1].trim()) : void 0;
|
|
310
|
+
};
|
|
311
|
+
const sessionId = pick(FIELD.sessionId);
|
|
312
|
+
const title = pick(FIELD.title);
|
|
313
|
+
const status = pick(FIELD.status);
|
|
314
|
+
const at = Number(pick(FIELD.at));
|
|
315
|
+
const summary = pick(FIELD.summary);
|
|
316
|
+
if (!sessionId || title === void 0 || summary === void 0) return null;
|
|
317
|
+
if (!status || !STATUSES.includes(status)) return null;
|
|
318
|
+
if (!Number.isFinite(at)) return null;
|
|
319
|
+
const cost = Number(pick(FIELD.costUsd));
|
|
320
|
+
const cwd = pick(FIELD.cwd);
|
|
321
|
+
const positive = (raw) => {
|
|
322
|
+
const n = Number(raw);
|
|
323
|
+
return Number.isFinite(n) && n > 0 ? n : void 0;
|
|
324
|
+
};
|
|
325
|
+
const durationMs = positive(pick(FIELD.durationMs));
|
|
326
|
+
const tokens = positive(pick(FIELD.tokens));
|
|
327
|
+
const turns = positive(pick(FIELD.turns));
|
|
328
|
+
const worker = pick(FIELD.worker);
|
|
329
|
+
const error = pick(FIELD.error);
|
|
330
|
+
const detail = pick(FIELD.detail);
|
|
331
|
+
const seq = positive(pick(FIELD.seq));
|
|
332
|
+
const goal = pick(FIELD.goal);
|
|
333
|
+
const finishReason = pick(FIELD.finishReason);
|
|
334
|
+
const art = body.match(FIELD.artifacts);
|
|
335
|
+
const artifacts = art ? {
|
|
336
|
+
toolCalls: Number(art[1]),
|
|
337
|
+
commands: Number(art[2]),
|
|
338
|
+
changed: [...art[3].matchAll(CHANGED_RE)].map((m) => unescapeXml(m[1].trim()))
|
|
339
|
+
} : void 0;
|
|
340
|
+
return {
|
|
341
|
+
sessionId,
|
|
342
|
+
title,
|
|
343
|
+
status,
|
|
344
|
+
summary,
|
|
345
|
+
at,
|
|
346
|
+
...Number.isFinite(cost) && cost > 0 ? { costUsd: cost } : {},
|
|
347
|
+
...cwd !== void 0 ? { cwd } : {},
|
|
348
|
+
...durationMs !== void 0 ? { durationMs } : {},
|
|
349
|
+
...tokens !== void 0 ? { tokens } : {},
|
|
350
|
+
...turns !== void 0 ? { turns } : {},
|
|
351
|
+
...worker === "true" ? { worker: true } : worker === "false" ? { worker: false } : {},
|
|
352
|
+
...error ? { error } : {},
|
|
353
|
+
...detail ? { detail } : {},
|
|
354
|
+
...seq !== void 0 ? { seq } : {},
|
|
355
|
+
...goal ? { goal } : {},
|
|
356
|
+
...finishReason && FINISH_REASONS.has(finishReason) ? { finishReason } : {},
|
|
357
|
+
...artifacts ? { artifacts } : {}
|
|
358
|
+
};
|
|
359
|
+
}
|
|
360
|
+
function unescapeXml(s) {
|
|
361
|
+
return s.replace(/</g, "<").replace(/>/g, ">").replace(/"/g, "\"").replace(/'/g, "'").replace(/&/g, "&");
|
|
362
|
+
}
|
|
363
|
+
/**
|
|
364
|
+
* The short label a transcript row shows — `api-refactor · done`. Status words
|
|
365
|
+
* are chosen to read as a verb phrase after the title.
|
|
366
|
+
*/
|
|
367
|
+
function sessionEventLabel(event) {
|
|
368
|
+
return `${event.title} ${{
|
|
369
|
+
"done": "finished",
|
|
370
|
+
"error": "failed",
|
|
371
|
+
"cancelled": "was cancelled",
|
|
372
|
+
"needs-attention": "needs attention"
|
|
373
|
+
}[event.status]}`;
|
|
374
|
+
}
|
|
375
|
+
/**
|
|
376
|
+
* Status → how it reads. `needs-attention` is deliberately the loudest: it is
|
|
377
|
+
* the one status where the human, not the main, has to act.
|
|
378
|
+
*/
|
|
379
|
+
const SESSION_EVENT_STATUS_STYLE = {
|
|
380
|
+
"done": {
|
|
381
|
+
glyph: "✓",
|
|
382
|
+
tone: "accent",
|
|
383
|
+
verb: "finished"
|
|
384
|
+
},
|
|
385
|
+
"error": {
|
|
386
|
+
glyph: "✗",
|
|
387
|
+
tone: "error",
|
|
388
|
+
verb: "failed"
|
|
389
|
+
},
|
|
390
|
+
"cancelled": {
|
|
391
|
+
glyph: "⊘",
|
|
392
|
+
tone: "dim",
|
|
393
|
+
verb: "was cancelled"
|
|
394
|
+
},
|
|
395
|
+
"needs-attention": {
|
|
396
|
+
glyph: "!",
|
|
397
|
+
tone: "warn",
|
|
398
|
+
verb: "needs your input"
|
|
399
|
+
}
|
|
400
|
+
};
|
|
401
|
+
/**
|
|
402
|
+
* The directory name a session lives in — the same basename label the sidebar
|
|
403
|
+
* groups by. `undefined` for a directory-less session (the main) or no cwd.
|
|
404
|
+
*/
|
|
405
|
+
function sessionDirLabel(cwd) {
|
|
406
|
+
if (!cwd) return void 0;
|
|
407
|
+
const parts = cwd.split(/[\\/]+/).filter(Boolean);
|
|
408
|
+
return parts[parts.length - 1];
|
|
409
|
+
}
|
|
410
|
+
/** Short, stable id fragment for the header — enough to disambiguate, not to read. */
|
|
411
|
+
function shortSessionId(id) {
|
|
412
|
+
return id.length <= 8 ? id : id.slice(0, 8);
|
|
413
|
+
}
|
|
414
|
+
/**
|
|
415
|
+
* The header's metadata cells, in display order, omitting anything unknown.
|
|
416
|
+
* Renderers join them with their own separator; the CONTENT is fixed here so
|
|
417
|
+
* both surfaces show the same receipt for the same run.
|
|
418
|
+
*
|
|
419
|
+
* The session id is deliberately NOT a cell: it is the least legible datum and
|
|
420
|
+
* exists only to disambiguate. Renderers append `shortSessionId` LAST and
|
|
421
|
+
* dimmer than the rest.
|
|
422
|
+
*/
|
|
423
|
+
function sessionEventMeta(event) {
|
|
424
|
+
const cells = [];
|
|
425
|
+
const dir = sessionDirLabel(event.cwd);
|
|
426
|
+
if (dir) cells.push(dir);
|
|
427
|
+
if (event.durationMs !== void 0) cells.push(formatRunDuration(event.durationMs));
|
|
428
|
+
if (event.tokens !== void 0) cells.push(`${formatTokenCount(event.tokens)} tok`);
|
|
429
|
+
if (event.turns !== void 0) cells.push(`${event.turns} turn${event.turns === 1 ? "" : "s"}`);
|
|
430
|
+
if (event.costUsd !== void 0) cells.push(fmtCost(event.costUsd));
|
|
431
|
+
return cells;
|
|
432
|
+
}
|
|
433
|
+
/**
|
|
434
|
+
* The dimmed second line: the last thing the session said, collapsed to one
|
|
435
|
+
* paragraph and capped. Renderers may clamp further (line-clamp in the GUI,
|
|
436
|
+
* width in the TUI); this is the upper bound and the shared ellipsis rule.
|
|
437
|
+
*/
|
|
438
|
+
function sessionEventExcerpt(event, max = 240) {
|
|
439
|
+
const flat = (event.status === "needs-attention" && event.detail ? event.detail : event.status === "error" && event.error ? event.error : event.summary).replace(/\s+/g, " ").trim();
|
|
440
|
+
return flat.length <= max ? flat : `${flat.slice(0, max - 1).trimEnd()}…`;
|
|
441
|
+
}
|
|
442
|
+
/** Ellipsize a title to `max` characters; titles are user text and can be a paragraph. */
|
|
443
|
+
function truncateTitle(title, max = 48) {
|
|
444
|
+
const flat = title.replace(/\s+/g, " ").trim();
|
|
445
|
+
return flat.length <= max ? flat : `${flat.slice(0, max - 1).trimEnd()}…`;
|
|
446
|
+
}
|
|
447
|
+
/**
|
|
448
|
+
* System-prompt fragment appended to every WORKER's agent. A worker's last
|
|
449
|
+
* message becomes the main's `summary`, so it must be a report, not a sign-off
|
|
450
|
+
* — the main should be able to act on it without reading the transcript.
|
|
451
|
+
*/
|
|
452
|
+
const WORKER_REPORT_FRAGMENT = `You are a worker session created by an orchestrating main session. Your final message of a run is delivered to it verbatim as your report, so end every run with a short structured report:
|
|
453
|
+
|
|
454
|
+
## Report
|
|
455
|
+
- **Goal**: what you were asked, in one line
|
|
456
|
+
- **Outcome**: done / partial / blocked — one line, and why if not done
|
|
457
|
+
- **Changed**: files or artifacts touched (paths), or "none"
|
|
458
|
+
- **Checks**: what you ran and the result (tests, typecheck, lint), or "none"
|
|
459
|
+
- **Open questions**: anything the main or a human must decide, or "none"
|
|
460
|
+
- **Next**: the concrete next step you recommend, or "none"
|
|
461
|
+
|
|
462
|
+
Keep it factual and under ~15 lines. This block is what the main decides on; prose before it is fine, prose instead of it is not.`;
|
|
463
|
+
/**
|
|
464
|
+
* System-prompt fragment appended to the MAIN's agent: how to delegate without
|
|
465
|
+
* wasting calls. The `sessions` tool description says what each verb does;
|
|
466
|
+
* this says which one to reach for, and when not to call at all.
|
|
467
|
+
*/
|
|
468
|
+
const MAIN_PLAYBOOK_FRAGMENT = `You are the main session: an orchestrator. Work happens in worker sessions; you brief them, integrate their reports, and keep the human informed. Do not do the workers' work here.
|
|
469
|
+
|
|
470
|
+
Work efficiently with the \`sessions\` tool:
|
|
471
|
+
- Never poll. After create or send you WILL receive a <session-event> when the worker finishes, fails, or blocks. Do not read or list a worker that has not reported yet.
|
|
472
|
+
- Reuse before creating. To continue work in a project, send to its existing idle session (listed under Projects below; its context is already warm). Create a worker only for a new, independent unit of work, or when the project has no suitable session.
|
|
473
|
+
- You already know the ids. Take them from Projects below, from a <session-event>, or from an earlier list. Do not list just to find an id you have.
|
|
474
|
+
- send vs steer: send when the worker is idle or the new prompt should queue after its current run; steer only to change course mid-run.
|
|
475
|
+
- Fire-and-forget when you can. For work you will not act on when it lands (docs, cleanup, low-stakes checks), pass wake: false on create or send; the report still reaches your history, you just are not woken for it.
|
|
476
|
+
- Brief completely. A worker prompt states the goal, the constraints, what to check (tests, typecheck, lint), and that it must end with its report. Follow-up questions cost a full round trip.
|
|
477
|
+
- read is cheap (last message); transcript is not. Use transcript only when a report is unclear.
|
|
478
|
+
- Report to the human briefly: what went where, what came back, what needs a decision. Do not re-narrate worker reports.`;
|
|
479
|
+
/**
|
|
480
|
+
* The main's "Projects" briefing: which directories have ongoing work and
|
|
481
|
+
* the session to address in each, so the main does not rediscover them with
|
|
482
|
+
* a list call every run. Snapshot at agent start — live state is one `list`
|
|
483
|
+
* away and the text says so.
|
|
484
|
+
*/
|
|
485
|
+
function renderProjectsBriefing(projects, now) {
|
|
486
|
+
const lines = ["## Projects", "Known as of this session's start; live state comes from `sessions list`. Directory-less sessions are omitted."];
|
|
487
|
+
if (projects.length === 0) {
|
|
488
|
+
lines.push("- none yet");
|
|
489
|
+
return lines.join("\n");
|
|
490
|
+
}
|
|
491
|
+
for (const p of projects) {
|
|
492
|
+
const cells = [`${p.sessions} session${p.sessions === 1 ? "" : "s"}`, `last active ${agoLabel(now - p.lastActiveAt)}`];
|
|
493
|
+
if (p.active > 0) cells.push(`${p.active} active`);
|
|
494
|
+
lines.push(`- ${sessionDirLabel(p.root) ?? p.root} (${p.root}) · ${cells.join(" · ")}`);
|
|
495
|
+
lines.push(` latest: ${p.latest.sessionId} "${truncateTitle(p.latest.title, 60)}" (${p.latest.state})`);
|
|
496
|
+
}
|
|
497
|
+
return lines.join("\n");
|
|
498
|
+
}
|
|
499
|
+
/** Coarse relative time for the briefing: `just now`, `12m ago`, `3h ago`, `5d ago`. */
|
|
500
|
+
function agoLabel(elapsedMs) {
|
|
501
|
+
const m = Math.floor(Math.max(0, elapsedMs) / 6e4);
|
|
502
|
+
if (m < 1) return "just now";
|
|
503
|
+
if (m < 60) return `${m}m ago`;
|
|
504
|
+
const h = Math.floor(m / 60);
|
|
505
|
+
if (h < 48) return `${h}h ago`;
|
|
506
|
+
return `${Math.floor(h / 24)}d ago`;
|
|
507
|
+
}
|
|
508
|
+
//#endregion
|
|
509
|
+
export { formatRunDuration as C, formatTokensPerSecond as D, formatTokenCount as E, hasRunReceipt as O, formatCostUsd as S, formatRunReceiptLine as T, shortSessionId as _, SESSION_ROLE_KEY as a, RUN_RECEIPT_TURN_GLYPH as b, isMainSession as c, renderProjectsBriefing as d, renderSessionEventXml as f, sessionEventMeta as g, sessionEventLabel as h, SESSION_EVENT_STATUS_STYLE as i, runReceiptFromRun as k, orchestratedBy as l, sessionEventExcerpt as m, MAIN_SESSION_TITLE as n, WORKER_REPORT_FRAGMENT as o, sessionDirLabel as p, ORCHESTRATED_BY_KEY as r, artifactsFromTurns as s, MAIN_PLAYBOOK_FRAGMENT as t, parseSessionEventXml as u, truncateTitle as v, formatRunReceiptCells as w, fitRunReceiptCells as x, RUN_RECEIPT_GLYPH as y };
|
|
510
|
+
|
|
511
|
+
//# sourceMappingURL=orchestration-BCGmB8Ps.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"orchestration-BCGmB8Ps.js","names":[],"sources":["../src/chat/run-receipt.ts","../src/chat/orchestration.ts"],"sourcesContent":["/**\n * The per-run receipt — the dimmed one-liner under every finished run:\n *\n * claude-sonnet-4 · 2m14s · ↻3 · $0.04 · ↑4.2k ↓812\n *\n * One definition for three consumers — live in the TUI, live in the GUI, and\n * replay after reload — so a run never describes itself differently depending\n * on where you read it. Cells are omitted rather than zeroed when unknown: a\n * `$0.00` or `0 tok` cell is a claim, and an untrue one (most providers do not\n * report cost at all).\n *\n * Read off the persisted `SessionRun` record, which the loop already totals\n * (`turns`, `totalUsage`, `cost`, `endedAt`) — exact, and the same numbers the\n * orchestration event carries for the same run.\n *\n * Node-free; re-exported from `zidane/chat/pure` for the renderer.\n */\nimport type { SessionRun } from '../session/index'\nimport { fmtCost } from './format'\n\nexport interface RunReceipt {\n /** Model that produced the LAST turn — the one the answer came from. */\n modelId?: string\n /** Distinct models beyond the last one (a fallback chain that engaged). */\n otherModels?: number\n durationMs?: number\n turns?: number\n costUsd?: number\n tokensIn?: number\n tokensOut?: number\n /**\n * Output tokens per second of GENERATION — output over (stream duration −\n * time to first token), summed across the run's turns. Excludes the wait\n * for the first byte and everything outside the provider stream (tool\n * execution, approvals), so it measures the model, not the run.\n */\n tokensPerSecond?: number\n}\n\n/** Leads the turn count: one cycle = one model round trip. */\nexport const RUN_RECEIPT_TURN_GLYPH = '↻'\n\n/** `1.2k` / `48k` / `1.3M` — token counts are read at a glance, not counted. */\nexport function formatTokenCount(tokens: number): string {\n if (tokens >= 1_000_000)\n return `${(tokens / 1_000_000).toFixed(1)}M`\n if (tokens >= 1_000)\n return `${(tokens / 1_000).toFixed(tokens >= 10_000 ? 0 : 1)}k`\n return String(tokens)\n}\n\n/** `2m18s` / `48s` / `<1s` / `1h05m`. Compact — this is a receipt, not a profiler. */\nexport function formatRunDuration(ms: number): string {\n if (ms < 1000)\n return '<1s'\n const s = Math.round(ms / 1000)\n if (s < 60)\n return `${s}s`\n const m = Math.floor(s / 60)\n const rest = s % 60\n if (m < 60)\n return rest ? `${m}m${String(rest).padStart(2, '0')}s` : `${m}m`\n const h = Math.floor(m / 60)\n return `${h}h${String(m % 60).padStart(2, '0')}m`\n}\n\n/** `$0.04`, or four decimals under a cent so a cheap run is not shown as `$0.00`. Same as `fmtCost`. */\nexport const formatCostUsd = fmtCost\n\n/**\n * Build the receipt for a run record. `now` stands in for `endedAt` when the\n * record is not finalized yet (`run:end` is broadcast a beat before it is).\n */\nexport function runReceiptFromRun(run: SessionRun, now = Date.now()): RunReceipt {\n /*\n * \"in\" = everything sent to the model, cache INCLUDED. Anthropic reports\n * cached prefix tokens in `cacheRead` / `cacheCreation`, not `input`, so raw\n * `input` alone under-reports by ~99% on a warm session (the usage panel\n * applies the same correction). Without this a run read `58 in / 21k out`.\n */\n const sumIn = (u: { input: number, cacheRead?: number, cacheCreation?: number }): number =>\n u.input + (u.cacheRead ?? 0) + (u.cacheCreation ?? 0)\n const usage = run.totalUsage\n ? { input: sumIn(run.totalUsage), output: run.totalUsage.output }\n : run.turnUsage?.reduce((acc, u) => ({ input: acc.input + sumIn(u), output: acc.output + u.output }), { input: 0, output: 0 })\n const models = (run.turnUsage ?? []).map(u => u.modelId).filter((m): m is string => typeof m === 'string' && m.length > 0)\n const modelId = models.at(-1)\n const otherModels = modelId ? new Set(models).size - 1 : 0\n const durationMs = (run.endedAt ?? now) - run.startedAt\n const cost = run.cost ?? run.turnUsage?.reduce((n, u) => n + (u.cost ?? 0), 0) ?? 0\n const turns = run.turns ?? run.turnUsage?.length ?? 0\n /*\n * Generation speed needs per-turn stream timing, which only turns recorded\n * after `streamDurationMs` shipped carry — older runs simply omit the cell.\n * Per turn, generation time is the stream minus the first-byte wait; a turn\n * with no TTFT (tool-only) uses its whole stream, the closest honest proxy.\n */\n let genMs = 0\n let genOut = 0\n for (const u of run.turnUsage ?? []) {\n if (u.streamDurationMs === undefined || u.output <= 0)\n continue\n const ms = u.streamDurationMs - (u.timeToFirstTokenMs ?? 0)\n if (ms <= 0)\n continue\n genMs += ms\n genOut += u.output\n }\n const tokensPerSecond = genMs > 0 && genOut > 0 ? (genOut * 1000) / genMs : undefined\n return {\n ...(modelId ? { modelId } : {}),\n ...(otherModels > 0 ? { otherModels } : {}),\n ...(durationMs > 0 ? { durationMs } : {}),\n ...(turns > 0 ? { turns } : {}),\n ...(cost > 0 ? { costUsd: cost } : {}),\n ...(usage && usage.input > 0 ? { tokensIn: usage.input } : {}),\n ...(usage && usage.output > 0 ? { tokensOut: usage.output } : {}),\n ...(tokensPerSecond !== undefined ? { tokensPerSecond } : {}),\n }\n}\n\n/** `42 tk/s`; one decimal under 10 so a slow model is not shown as `0 tk/s`. */\nexport function formatTokensPerSecond(tps: number): string {\n return `${tps < 10 ? tps.toFixed(1) : Math.round(tps).toString()} tk/s`\n}\n\n/** What a cell IS, so renderers can tint by meaning rather than by position. */\nexport type RunReceiptCellKind = 'model' | 'duration' | 'turns' | 'cost' | 'tokens' | 'speed'\n/** Sub-parts of a cell that want their own tint — the two token arrows. */\nexport type RunReceiptSegmentKind = 'tokens-in' | 'tokens-out'\n\nexport interface RunReceiptSegment {\n kind: RunReceiptSegmentKind\n text: string\n}\n\nexport interface RunReceiptCell {\n kind: RunReceiptCellKind\n /** Plain rendering — what `formatRunReceiptLine` and width fitting use. */\n text: string\n /**\n * Optional tinted sub-parts, space-joined; `text` is their plain join. A\n * renderer without per-segment color just paints `text`.\n */\n segments?: readonly RunReceiptSegment[]\n}\n\n/**\n * The receipt's cells, in display order. Renderers join them with their own\n * separator, tint them by `kind`, and truncate to their own width; the CONTENT\n * is fixed here.\n */\nexport function formatRunReceiptCells(r: RunReceipt): RunReceiptCell[] {\n const cells: RunReceiptCell[] = []\n if (r.modelId)\n cells.push({ kind: 'model', text: r.otherModels ? `${r.modelId} +${r.otherModels}` : r.modelId })\n if (r.durationMs !== undefined)\n cells.push({ kind: 'duration', text: formatRunDuration(r.durationMs) })\n // `↻` reads as \"a cycle\" — one model round trip — so `↻7` is seven turns\n // without spending the word.\n if (r.turns !== undefined)\n cells.push({ kind: 'turns', text: `${RUN_RECEIPT_TURN_GLYPH}${r.turns}` })\n if (r.costUsd !== undefined)\n cells.push({ kind: 'cost', text: fmtCost(r.costUsd) })\n // `↑` = sent to the model, `↓` = received from it. Arrows over words: two\n // glyphs instead of six characters on a line that competes for width, and\n // they read the same in every locale.\n if (r.tokensIn !== undefined || r.tokensOut !== undefined) {\n const segments: RunReceiptSegment[] = [\n { kind: 'tokens-in', text: `↑${formatTokenCount(r.tokensIn ?? 0)}` },\n { kind: 'tokens-out', text: `↓${formatTokenCount(r.tokensOut ?? 0)}` },\n ]\n cells.push({ kind: 'tokens', text: segments.map(seg => seg.text).join(' '), segments })\n }\n if (r.tokensPerSecond !== undefined)\n cells.push({ kind: 'speed', text: formatTokensPerSecond(r.tokensPerSecond) })\n return cells\n}\n\n/** The glyph that leads the line on every surface. */\nexport const RUN_RECEIPT_GLYPH = '≡'\n\n/**\n * Fit cells to `width` columns for a tinted renderer: returns the cells that\n * fit whole, plus whether the last one was cut. A cut cell is truncated with\n * `…`; anything after it is dropped. Never wraps. `prefix` is the columns the\n * renderer already spent (glyph + space).\n */\nexport function fitRunReceiptCells(cells: readonly RunReceiptCell[], width: number, prefix = 0): RunReceiptCell[] {\n const sep = ' · '\n let used = prefix\n const out: RunReceiptCell[] = []\n for (const cell of cells) {\n const need = (out.length ? sep.length : 0) + cell.text.length\n if (used + need <= width) {\n out.push(cell)\n used += need\n continue\n }\n const room = width - used - (out.length ? sep.length : 0)\n if (room >= 2)\n out.push({ kind: cell.kind, text: `${cell.text.slice(0, room - 1).trimEnd()}…` })\n break\n }\n return out\n}\n\n/** One line, ` · `-joined, ellipsized to `width` columns. Never wraps. */\nexport function formatRunReceiptLine(r: RunReceipt, width = Number.POSITIVE_INFINITY): string {\n const line = formatRunReceiptCells(r).map(c => c.text).join(' · ')\n if (line.length <= width)\n return line\n if (width <= 1)\n return width === 1 ? '…' : ''\n return `${line.slice(0, width - 1).trimEnd()}…`\n}\n\n/** Anything to show? A run with no record data renders no line at all. */\nexport function hasRunReceipt(r: RunReceipt): boolean {\n return formatRunReceiptCells(r).length > 0\n}\n","import { escapeXml } from '../xml'\n/**\n * Orchestration — the pure model for a \"main\" session that drives others.\n *\n * A main session is an ordinary session with a role, and a worker is an\n * ordinary session with a parent pointer. Both are `metadata` keys, so every\n * existing surface (sidebar, history, attach, search, replay) works on them\n * with no special cases; only the surfaces that WANT to treat them specially\n * (pinning, the event row, the jump shortcut) read these keys.\n *\n * This is deliberately not `spawn`. A spawned child is ephemeral, inline, and\n * dies with the parent's run; a worker is a persistent, resumable session with\n * its own cwd, model chain, todos and history, visible in every window, and it\n * outlives the main's run. The parent pointer is what makes them a tree.\n *\n * Node-free: re-exported from `zidane/chat/pure` for the Electron renderer,\n * which needs `isMainSession` / `orchestratedBy` for pinning and the event row.\n */\nimport { fmtCost } from './format'\nimport { formatRunDuration, formatTokenCount } from './run-receipt'\n\n/** Title the main session is created with. Users can rename it; the ROLE is what matters. */\nexport const MAIN_SESSION_TITLE = 'Main'\n\n/** `session.metadata.role` — present and `'main'` on the one orchestrating session. */\nexport const SESSION_ROLE_KEY = 'role'\n/** `session.metadata.orchestratedBy` — the main session's id, on a worker. */\nexport const ORCHESTRATED_BY_KEY = 'orchestratedBy'\n/**\n * What happened in a worker. `needs-attention` is a worker blocked on an\n * approval or interaction that no window has answered — the main can steer,\n * but a human still has to decide.\n */\nexport type SessionEventStatus = 'done' | 'error' | 'cancelled' | 'needs-attention'\n\nexport interface SessionEvent {\n /** The worker the event is about. Click target in both clients. */\n sessionId: string\n /** Worker title at event time — titles change, the event should not. */\n title: string\n status: SessionEventStatus\n /** One-line human summary; also what the model reads. */\n summary: string\n /** Wall-clock at the event. */\n at: number\n /** Run cost in USD when the provider reported one. Omitted, never `0`. */\n costUsd?: number\n /** Worker cwd — lets the main reason about which project reported. */\n cwd?: string\n /** Wall-clock of the run that produced this event, when it has ended. */\n durationMs?: number\n /** Input + output tokens across the run's assistant turns. Omitted, never `0`. */\n tokens?: number\n /** Turns the run produced. Omitted, never `0`. */\n turns?: number\n /** Created by the main (vs. a session the human started elsewhere). */\n worker?: boolean\n /** For `error`: the failure text, separate from `summary` so the UI can style it. */\n error?: string\n /**\n * For `needs-attention`: WHAT is being asked — the approval's tool, the\n * plan's title, the question's prompt. The main can often answer from this\n * alone instead of reading the worker's transcript.\n */\n detail?: string\n /**\n * Monotonic per-main sequence. Lets a consumer dedup or detect a gap when\n * the same event can arrive twice (live signal, then replay) or a window\n * reattaches.\n */\n seq?: number\n /**\n * The prompt that started the run — \"what was asked\". Paired with\n * `summary` (\"what it said\") this is what turns telemetry into a decision:\n * a 692-token essay is fine if that was the goal, and noise if it wasn't.\n */\n goal?: string\n /**\n * Abnormal terminal state beyond `status`: the run ended because the model\n * hit a ceiling (`length`), spun on empty pauses (`pause`), or was refused\n * (`content-filter`). Omitted for a normal `stop`.\n */\n finishReason?: 'length' | 'pause' | 'content-filter'\n /** What the run touched — the receipts a decision needs. */\n artifacts?: RunArtifacts\n}\n\nexport interface RunArtifacts {\n /** Files edited or written, deduplicated, in first-touch order; capped. */\n changed: readonly string[]\n /** Shell commands run. */\n commands: number\n /** Tool calls in total. */\n toolCalls: number\n}\n\n/** Type guard over untrusted metadata. */\nexport function isMainSession(metadata: Readonly<Record<string, unknown>> | undefined): boolean {\n return metadata?.[SESSION_ROLE_KEY] === 'main'\n}\n\n/** The main session id a worker reports to, or `null` for an ordinary session. */\nexport function orchestratedBy(metadata: Readonly<Record<string, unknown>> | undefined): string | null {\n const value = metadata?.[ORCHESTRATED_BY_KEY]\n return typeof value === 'string' && value.length > 0 ? value : null\n}\n\n/** Tools whose `path` input means \"this file changed\". */\nconst CHANGE_TOOLS = new Set(['edit', 'multi_edit', 'write_file'])\nconst ARTIFACT_PATH_CAP = 12\n\n/**\n * What a run touched, read off its assistant turns' tool calls. Only the\n * tools that MUTATE count as \"changed\" — reads are not artifacts. Capped so a\n * refactor across a hundred files does not turn the event into a manifest;\n * the count still tells the truth.\n */\nexport function artifactsFromTurns(turns: readonly { role: string, content: readonly { type: string, name?: string, input?: Record<string, unknown> }[] }[]): RunArtifacts | undefined {\n const changed: string[] = []\n const seen = new Set<string>()\n let commands = 0\n let toolCalls = 0\n for (const turn of turns) {\n if (turn.role !== 'assistant')\n continue\n for (const block of turn.content) {\n if (block.type !== 'tool_call' || !block.name)\n continue\n toolCalls++\n if (block.name === 'shell')\n commands++\n if (CHANGE_TOOLS.has(block.name)) {\n const path = block.input?.path\n if (typeof path === 'string' && path && !seen.has(path)) {\n seen.add(path)\n changed.push(path)\n }\n }\n }\n }\n if (toolCalls === 0)\n return undefined\n return { changed: changed.slice(0, ARTIFACT_PATH_CAP), commands, toolCalls }\n}\n\nconst STATUSES: readonly SessionEventStatus[] = ['done', 'error', 'cancelled', 'needs-attention']\n\n/**\n * Wire format between the harness and the model — and, because it is persisted\n * inside the user turn's text block, between a live session and its replay.\n *\n * Follows `<task-notification>` exactly: child-tag XML, one block per event,\n * escaped with `escapeXml`. The model already knows this shape as \"the harness\n * telling me something\", which is the point — a main that mistook a worker\n * report for a human instruction would act on it as one. `eventsFromTurns`\n * detects the block on replay and re-synthesizes the structured row instead of\n * painting the raw XML as a user prompt.\n */\nexport function renderSessionEventXml(event: SessionEvent): string {\n const tag = (name: string, value: string | number | undefined): string[] =>\n value === undefined ? [] : [` <${name}>${escapeXml(String(value))}</${name}>`]\n return [\n '<session-event>',\n ...tag('session-id', event.sessionId),\n ...tag('title', event.title),\n ...tag('status', event.status),\n ...tag('at', event.at),\n ...tag('cwd', event.cwd ?? ''),\n ...tag('cost-usd', event.costUsd),\n ...tag('duration-ms', event.durationMs),\n ...tag('tokens', event.tokens),\n ...tag('turns', event.turns),\n ...tag('worker', event.worker === undefined ? undefined : String(event.worker)),\n ...tag('seq', event.seq),\n ...tag('finish-reason', event.finishReason),\n ...tag('error', event.error),\n ...tag('detail', event.detail),\n ...tag('goal', event.goal),\n ...(event.artifacts\n ? [\n ` <artifacts tool-calls=\"${event.artifacts.toolCalls}\" commands=\"${event.artifacts.commands}\">`,\n ...event.artifacts.changed.map(p => ` <changed>${escapeXml(p)}</changed>`),\n ' </artifacts>',\n ]\n : []),\n ...tag('summary', event.summary),\n '</session-event>',\n ].join('\\n')\n}\n\nconst SESSION_EVENT_RE = /^\\s*<session-event>([\\s\\S]*?)<\\/session-event>\\s*$/\nconst FIELD = {\n sessionId: /<session-id>([\\s\\S]*?)<\\/session-id>/,\n title: /<title>([\\s\\S]*?)<\\/title>/,\n status: /<status>([\\s\\S]*?)<\\/status>/,\n at: /<at>([\\s\\S]*?)<\\/at>/,\n cwd: /<cwd>([\\s\\S]*?)<\\/cwd>/,\n costUsd: /<cost-usd>([\\s\\S]*?)<\\/cost-usd>/,\n durationMs: /<duration-ms>([\\s\\S]*?)<\\/duration-ms>/,\n tokens: /<tokens>([\\s\\S]*?)<\\/tokens>/,\n turns: /<turns>([\\s\\S]*?)<\\/turns>/,\n worker: /<worker>([\\s\\S]*?)<\\/worker>/,\n error: /<error>([\\s\\S]*?)<\\/error>/,\n detail: /<detail>([\\s\\S]*?)<\\/detail>/,\n seq: /<seq>([\\s\\S]*?)<\\/seq>/,\n goal: /<goal>([\\s\\S]*?)<\\/goal>/,\n finishReason: /<finish-reason>([\\s\\S]*?)<\\/finish-reason>/,\n artifacts: /<artifacts tool-calls=\"(\\d+)\" commands=\"(\\d+)\">([\\s\\S]*?)<\\/artifacts>/,\n summary: /<summary>([\\s\\S]*?)<\\/summary>/,\n} as const\nconst CHANGED_RE = /<changed>([\\s\\S]*?)<\\/changed>/g\nconst FINISH_REASONS = new Set(['length', 'pause', 'content-filter'])\n\n/**\n * Inverse of {@link renderSessionEventXml}. Untrusted input — it comes off disk\n * and outlives this module's versions — so it validates each field and returns\n * `null` for anything malformed, in which case the turn replays as the plain\n * user text it structurally is.\n */\nexport function parseSessionEventXml(text: string): SessionEvent | null {\n const m = text.match(SESSION_EVENT_RE)\n if (!m)\n return null\n const body = m[1]\n const pick = (re: RegExp): string | undefined => {\n const inner = body.match(re)\n return inner ? unescapeXml(inner[1].trim()) : undefined\n }\n const sessionId = pick(FIELD.sessionId)\n const title = pick(FIELD.title)\n const status = pick(FIELD.status)\n const at = Number(pick(FIELD.at))\n const summary = pick(FIELD.summary)\n if (!sessionId || title === undefined || summary === undefined)\n return null\n if (!status || !(STATUSES as readonly string[]).includes(status))\n return null\n if (!Number.isFinite(at))\n return null\n const cost = Number(pick(FIELD.costUsd))\n const cwd = pick(FIELD.cwd)\n const positive = (raw: string | undefined): number | undefined => {\n const n = Number(raw)\n return Number.isFinite(n) && n > 0 ? n : undefined\n }\n const durationMs = positive(pick(FIELD.durationMs))\n const tokens = positive(pick(FIELD.tokens))\n const turns = positive(pick(FIELD.turns))\n const worker = pick(FIELD.worker)\n const error = pick(FIELD.error)\n const detail = pick(FIELD.detail)\n const seq = positive(pick(FIELD.seq))\n const goal = pick(FIELD.goal)\n const finishReason = pick(FIELD.finishReason)\n const art = body.match(FIELD.artifacts)\n const artifacts: RunArtifacts | undefined = art\n ? {\n toolCalls: Number(art[1]),\n commands: Number(art[2]),\n changed: [...art[3].matchAll(CHANGED_RE)].map(m => unescapeXml(m[1].trim())),\n }\n : undefined\n return {\n sessionId,\n title,\n status: status as SessionEventStatus,\n summary,\n at,\n ...(Number.isFinite(cost) && cost > 0 ? { costUsd: cost } : {}),\n ...(cwd !== undefined ? { cwd } : {}),\n ...(durationMs !== undefined ? { durationMs } : {}),\n ...(tokens !== undefined ? { tokens } : {}),\n ...(turns !== undefined ? { turns } : {}),\n ...(worker === 'true' ? { worker: true } : worker === 'false' ? { worker: false } : {}),\n ...(error ? { error } : {}),\n ...(detail ? { detail } : {}),\n ...(seq !== undefined ? { seq } : {}),\n ...(goal ? { goal } : {}),\n ...(finishReason && FINISH_REASONS.has(finishReason) ? { finishReason: finishReason as SessionEvent['finishReason'] } : {}),\n ...(artifacts ? { artifacts } : {}),\n }\n}\n\nfunction unescapeXml(s: string): string {\n return s\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/"/g, '\"')\n .replace(/'/g, '\\'')\n .replace(/&/g, '&')\n}\n\n/**\n * The short label a transcript row shows — `api-refactor · done`. Status words\n * are chosen to read as a verb phrase after the title.\n */\nexport function sessionEventLabel(event: SessionEvent): string {\n const word: Record<SessionEventStatus, string> = {\n 'done': 'finished',\n 'error': 'failed',\n 'cancelled': 'was cancelled',\n 'needs-attention': 'needs attention',\n }\n return `${event.title} ${word[event.status]}`\n}\n\n// ---------------------------------------------------------------------------\n// Presentation shared by both clients — one definition of the card's content\n// so a TUI card and a GUI card describe the same event with the same words.\n// ---------------------------------------------------------------------------\n\n/** Semantic tone a renderer maps onto its theme. */\nexport type SessionEventTone = 'accent' | 'error' | 'dim' | 'warn'\n\nexport interface SessionEventStatusStyle {\n /** Glyph for the icon column. */\n glyph: string\n tone: SessionEventTone\n /** Verb phrase after the title: \"finished\", \"needs your input\", … */\n verb: string\n}\n\n/**\n * Status → how it reads. `needs-attention` is deliberately the loudest: it is\n * the one status where the human, not the main, has to act.\n */\nexport const SESSION_EVENT_STATUS_STYLE: Readonly<Record<SessionEventStatus, SessionEventStatusStyle>> = {\n 'done': { glyph: '✓', tone: 'accent', verb: 'finished' },\n 'error': { glyph: '✗', tone: 'error', verb: 'failed' },\n 'cancelled': { glyph: '⊘', tone: 'dim', verb: 'was cancelled' },\n 'needs-attention': { glyph: '!', tone: 'warn', verb: 'needs your input' },\n}\n\n/**\n * The directory name a session lives in — the same basename label the sidebar\n * groups by. `undefined` for a directory-less session (the main) or no cwd.\n */\nexport function sessionDirLabel(cwd: string | undefined): string | undefined {\n if (!cwd)\n return undefined\n const parts = cwd.split(/[\\\\/]+/).filter(Boolean)\n return parts[parts.length - 1]\n}\n\n/** Short, stable id fragment for the header — enough to disambiguate, not to read. */\nexport function shortSessionId(id: string): string {\n return id.length <= 8 ? id : id.slice(0, 8)\n}\n\n/**\n * The header's metadata cells, in display order, omitting anything unknown.\n * Renderers join them with their own separator; the CONTENT is fixed here so\n * both surfaces show the same receipt for the same run.\n *\n * The session id is deliberately NOT a cell: it is the least legible datum and\n * exists only to disambiguate. Renderers append `shortSessionId` LAST and\n * dimmer than the rest.\n */\nexport function sessionEventMeta(event: SessionEvent): string[] {\n const cells: string[] = []\n // Directory first: it is identity, not a receipt number — two sessions can\n // share a title across projects, and the sidebar disambiguates the same way.\n const dir = sessionDirLabel(event.cwd)\n if (dir)\n cells.push(dir)\n if (event.durationMs !== undefined)\n cells.push(formatRunDuration(event.durationMs))\n if (event.tokens !== undefined)\n cells.push(`${formatTokenCount(event.tokens)} tok`)\n if (event.turns !== undefined)\n cells.push(`${event.turns} turn${event.turns === 1 ? '' : 's'}`)\n if (event.costUsd !== undefined)\n cells.push(fmtCost(event.costUsd))\n return cells\n}\n\n/**\n * The dimmed second line: the last thing the session said, collapsed to one\n * paragraph and capped. Renderers may clamp further (line-clamp in the GUI,\n * width in the TUI); this is the upper bound and the shared ellipsis rule.\n */\nexport function sessionEventExcerpt(event: SessionEvent, max = 240): string {\n /*\n * What the second line is FOR depends on the status. A blocked session's\n * most useful line is the question being asked; a failed one's is the error.\n * Only a finished session's is \"what it last said\".\n */\n const source = event.status === 'needs-attention' && event.detail\n ? event.detail\n : event.status === 'error' && event.error\n ? event.error\n : event.summary\n const flat = source.replace(/\\s+/g, ' ').trim()\n return flat.length <= max ? flat : `${flat.slice(0, max - 1).trimEnd()}…`\n}\n\n/** Ellipsize a title to `max` characters; titles are user text and can be a paragraph. */\nexport function truncateTitle(title: string, max = 48): string {\n const flat = title.replace(/\\s+/g, ' ').trim()\n return flat.length <= max ? flat : `${flat.slice(0, max - 1).trimEnd()}…`\n}\n\n/**\n * System-prompt fragment appended to every WORKER's agent. A worker's last\n * message becomes the main's `summary`, so it must be a report, not a sign-off\n * — the main should be able to act on it without reading the transcript.\n */\nexport const WORKER_REPORT_FRAGMENT = `You are a worker session created by an orchestrating main session. Your final message of a run is delivered to it verbatim as your report, so end every run with a short structured report:\n\n## Report\n- **Goal**: what you were asked, in one line\n- **Outcome**: done / partial / blocked — one line, and why if not done\n- **Changed**: files or artifacts touched (paths), or \"none\"\n- **Checks**: what you ran and the result (tests, typecheck, lint), or \"none\"\n- **Open questions**: anything the main or a human must decide, or \"none\"\n- **Next**: the concrete next step you recommend, or \"none\"\n\nKeep it factual and under ~15 lines. This block is what the main decides on; prose before it is fine, prose instead of it is not.`\n\n/**\n * System-prompt fragment appended to the MAIN's agent: how to delegate without\n * wasting calls. The `sessions` tool description says what each verb does;\n * this says which one to reach for, and when not to call at all.\n */\nexport const MAIN_PLAYBOOK_FRAGMENT = `You are the main session: an orchestrator. Work happens in worker sessions; you brief them, integrate their reports, and keep the human informed. Do not do the workers' work here.\n\nWork efficiently with the \\`sessions\\` tool:\n- Never poll. After create or send you WILL receive a <session-event> when the worker finishes, fails, or blocks. Do not read or list a worker that has not reported yet.\n- Reuse before creating. To continue work in a project, send to its existing idle session (listed under Projects below; its context is already warm). Create a worker only for a new, independent unit of work, or when the project has no suitable session.\n- You already know the ids. Take them from Projects below, from a <session-event>, or from an earlier list. Do not list just to find an id you have.\n- send vs steer: send when the worker is idle or the new prompt should queue after its current run; steer only to change course mid-run.\n- Fire-and-forget when you can. For work you will not act on when it lands (docs, cleanup, low-stakes checks), pass wake: false on create or send; the report still reaches your history, you just are not woken for it.\n- Brief completely. A worker prompt states the goal, the constraints, what to check (tests, typecheck, lint), and that it must end with its report. Follow-up questions cost a full round trip.\n- read is cheap (last message); transcript is not. Use transcript only when a report is unclear.\n- Report to the human briefly: what went where, what came back, what needs a decision. Do not re-narrate worker reports.`\n\n/** One known project, for the main's briefing. */\nexport interface ProjectBrief {\n /** Absolute directory. */\n root: string\n /** Non-main sessions rooted here. */\n sessions: number\n /** Most recent change across those sessions, epoch ms. */\n lastActiveAt: number\n /** Sessions currently running or blocked. */\n active: number\n /** Most recently active session here — the natural target for `send`. */\n latest: { sessionId: string, title: string, state: 'idle' | 'running' | 'blocked' }\n}\n\n/**\n * The main's \"Projects\" briefing: which directories have ongoing work and\n * the session to address in each, so the main does not rediscover them with\n * a list call every run. Snapshot at agent start — live state is one `list`\n * away and the text says so.\n */\nexport function renderProjectsBriefing(projects: readonly ProjectBrief[], now: number): string {\n const lines = ['## Projects', 'Known as of this session\\'s start; live state comes from `sessions list`. Directory-less sessions are omitted.']\n if (projects.length === 0) {\n lines.push('- none yet')\n return lines.join('\\n')\n }\n for (const p of projects) {\n const cells = [\n `${p.sessions} session${p.sessions === 1 ? '' : 's'}`,\n `last active ${agoLabel(now - p.lastActiveAt)}`,\n ]\n if (p.active > 0)\n cells.push(`${p.active} active`)\n lines.push(`- ${sessionDirLabel(p.root) ?? p.root} (${p.root}) · ${cells.join(' · ')}`)\n lines.push(` latest: ${p.latest.sessionId} \"${truncateTitle(p.latest.title, 60)}\" (${p.latest.state})`)\n }\n return lines.join('\\n')\n}\n\n/** Coarse relative time for the briefing: `just now`, `12m ago`, `3h ago`, `5d ago`. */\nexport function agoLabel(elapsedMs: number): string {\n const m = Math.floor(Math.max(0, elapsedMs) / 60_000)\n if (m < 1)\n return 'just now'\n if (m < 60)\n return `${m}m ago`\n const h = Math.floor(m / 60)\n if (h < 48)\n return `${h}h ago`\n return `${Math.floor(h / 24)}d ago`\n}\n\nexport { formatRunDuration, formatTokenCount } from './run-receipt'\n"],"mappings":"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"}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { $n as
|
|
2
|
-
|
|
1
|
+
import { $n as HeadlessOutputFormat, Jn as FormattedHeadlessResult, Yi as Agent, Yn as FormattedHeadlessTurnEvent, Zn as HeadlessEvent, er as HeadlessResult } from "../index-BGe1fQT7.js";
|
|
3
2
|
//#region src/output/stream-json.d.ts
|
|
4
3
|
type StreamJsonOutputFormat = HeadlessOutputFormat;
|
|
5
4
|
type StreamJsonTurnEvent = Extract<HeadlessEvent, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stream-json.d.ts","names":[],"sources":["../../src/output/stream-json.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"stream-json.d.ts","names":[],"sources":["../../src/output/stream-json.ts"],"mappings":";;KA2BY,yBAAyB;KACzB,sBAAsB,QAAQ;EAAiB;;UAE1C;EACf,SAAS;EACT;;UAGe,gCAAgC;EAC/C,SAAS;;iBAiBK,0BACd,OAAO,qBACP,UAAS,0BACR;iBAIa,2BACd,OAAO,qBACP,UAAS;iBAKK,uBACd,QAAQ,gBACR,UAAS,0BACR;iBAIa,wBACd,QAAQ,gBACR,UAAS;iBAKK,8BACd,UAAS,2BACP,OAAO;iBASK,sBACd,OAAO,OACP,UAAS"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { i as formattedHeadlessTurnEventToJsonl, n as formatHeadlessResult, o as installHeadlessEventAdapter, r as formatHeadlessTurnEvent } from "../headless-C_rNUuYC.js";
|
|
2
2
|
//#region src/output/stream-json.ts
|
|
3
3
|
function resolveFormatOptions(options) {
|
|
4
4
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"terminal.d.ts","names":[],"sources":["../../src/output/terminal.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"terminal.d.ts","names":[],"sources":["../../src/output/terminal.ts"],"mappings":";;UA+CiB;EACf;EACA;EACA;EACA,uBAAuB,KAAK,WAAW;EACvC,sBAAsB,OAAO,WAAW;;iBAG1B,oBAAoB,OAAO,OAAO,eAAe,gBAAgB,QAAQ,QAAQ;;;;;;;;;iBAsB3E,oBAAoB,OAAO,OAAO,eAAe,gBAAgB,QAAQ,QAAQ,UAAS,wBAA6B"}
|