zidane 9.1.1 → 9.1.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/dist/{acp-Di9WvMDF.js → acp-Cl4gCZN6.js} +7 -7
- package/dist/{acp-Di9WvMDF.js.map → acp-Cl4gCZN6.js.map} +1 -1
- package/dist/acp-cli.js +5 -5
- package/dist/acp.d.ts +2 -2
- package/dist/acp.js +1 -1
- package/dist/{agent-DJhpTS-B.js → agent-Dh_XZ7fj.js} +74 -19
- package/dist/agent-Dh_XZ7fj.js.map +1 -0
- package/dist/agent.d.ts +1 -1
- package/dist/agent.js +1 -1
- package/dist/{auth-store-port-DFgf22oo.js → auth-store-port-DBl2JUC6.js} +2 -2
- package/dist/{auth-store-port-DFgf22oo.js.map → auth-store-port-DBl2JUC6.js.map} +1 -1
- package/dist/{auto-update-restart-BFB7Ek87.js → auto-update-restart-CF_kjcJd.js} +277 -41
- package/dist/auto-update-restart-CF_kjcJd.js.map +1 -0
- package/dist/{browser-BcoCCB_n.js → browser-BkdeKnxO.js} +56 -2
- package/dist/browser-BkdeKnxO.js.map +1 -0
- package/dist/{browser-entry-ypi8CyE-.d.ts → browser-entry-BCwruqNa.d.ts} +10 -10
- package/dist/{browser-entry-ypi8CyE-.d.ts.map → browser-entry-BCwruqNa.d.ts.map} +1 -1
- package/dist/channels.d.ts +5 -5
- package/dist/chat/browser.d.ts +4 -4
- package/dist/chat/browser.js +6 -6
- package/dist/chat/pure.d.ts +5 -5
- package/dist/chat/pure.js +8 -8
- package/dist/chat.d.ts +5 -5
- package/dist/chat.js +55 -55
- package/dist/chat.js.map +1 -1
- package/dist/{cli-shared-CabruH8Z.js → cli-shared-DIV9c5Nr.js} +4 -4
- package/dist/{cli-shared-CabruH8Z.js.map → cli-shared-DIV9c5Nr.js.map} +1 -1
- package/dist/cli-style-DBEm6CyT.js +105 -0
- package/dist/cli-style-DBEm6CyT.js.map +1 -0
- package/dist/{client-core-CIixwznM.d.ts → client-core-C_4m_oL6.d.ts} +4 -4
- package/dist/{client-core-CIixwznM.d.ts.map → client-core-C_4m_oL6.d.ts.map} +1 -1
- package/dist/{client-CCaIXWue.d.ts → client-ygTASGis.d.ts} +2 -2
- package/dist/{client-CCaIXWue.d.ts.map → client-ygTASGis.d.ts.map} +1 -1
- package/dist/codemode-worker.js +8 -5
- package/dist/codemode-worker.js.map +1 -1
- package/dist/codemode.d.ts +16 -0
- package/dist/codemode.d.ts.map +1 -1
- package/dist/codemode.js +2 -2
- package/dist/{connection-loop-QmWL-fJf.d.ts → connection-loop-D_pRONCr.d.ts} +4 -4
- package/dist/{connection-loop-QmWL-fJf.d.ts.map → connection-loop-D_pRONCr.d.ts.map} +1 -1
- package/dist/contexts/daytona.d.ts +3 -3
- package/dist/contexts/docker.d.ts +1 -1
- package/dist/contexts/e2b.d.ts +2 -2
- package/dist/contexts/sandbox.d.ts +1 -1
- package/dist/{contexts-C72b0mMa.js → contexts-DLZTSRHU.js} +17 -106
- package/dist/contexts-DLZTSRHU.js.map +1 -0
- package/dist/contexts.d.ts +4 -4
- package/dist/contexts.js +2 -2
- package/dist/{credentials-wwETW8rI.js → credentials-D71duF64.js} +2 -2
- package/dist/{credentials-wwETW8rI.js.map → credentials-D71duF64.js.map} +1 -1
- package/dist/{cwd-picker-CcekODCt.js → cwd-picker-BsHA6HKv.js} +4 -4
- package/dist/{cwd-picker-CcekODCt.js.map → cwd-picker-BsHA6HKv.js.map} +1 -1
- package/dist/daemon-cli.js +4 -3
- package/dist/daemon-cli.js.map +1 -1
- package/dist/{decisions-CXmK0nz9.js → decisions-hsw5XS2g.js} +3 -1
- package/dist/decisions-hsw5XS2g.js.map +1 -0
- package/dist/{discovery-DycXFxdA.js → discovery-DD4wPWKS.js} +4 -4
- package/dist/{discovery-DycXFxdA.js.map → discovery-DD4wPWKS.js.map} +1 -1
- package/dist/durable/sqlite.d.ts +2 -2
- package/dist/durable.d.ts +1 -1
- package/dist/{engine-VQ86XGdG.js → engine-BDmtgr2O.js} +6 -6
- package/dist/{engine-VQ86XGdG.js.map → engine-BDmtgr2O.js.map} +1 -1
- package/dist/{eval-Bod0I1W_.js → eval-CfGUDAkN.js} +3 -3
- package/dist/{eval-Bod0I1W_.js.map → eval-CfGUDAkN.js.map} +1 -1
- package/dist/eval.d.ts +1 -1
- package/dist/eval.js +1 -1
- package/dist/{executor-C7RQrkEq.js → executor-EWOhLyd9.js} +4 -4
- package/dist/{executor-C7RQrkEq.js.map → executor-EWOhLyd9.js.map} +1 -1
- package/dist/{extension-mark-BqKdEZwF.js → extension-mark-_rhkDWL5.js} +9 -6
- package/dist/extension-mark-_rhkDWL5.js.map +1 -0
- package/dist/extensions/testing.d.ts +1 -1
- package/dist/extensions/testing.js +2 -2
- package/dist/{extensions-BCx4QuGB.js → extensions-DklXPjiq.js} +8 -8
- package/dist/{extensions-BCx4QuGB.js.map → extensions-DklXPjiq.js.map} +1 -1
- package/dist/{extensions-client-D8tEAcMw.d.ts → extensions-client-D4Q2XRKV.d.ts} +31 -5
- package/dist/extensions-client-D4Q2XRKV.d.ts.map +1 -0
- package/dist/extensions.d.ts +1 -1
- package/dist/extensions.js +6 -6
- package/dist/{fold-rules-DvLK8pbf.d.ts → fold-rules-1DpDwG9h.d.ts} +2 -2
- package/dist/{fold-rules-DvLK8pbf.d.ts.map → fold-rules-1DpDwG9h.d.ts.map} +1 -1
- package/dist/{google-Crva32sk.js → google-BtMW9KzL.js} +2 -2
- package/dist/{google-Crva32sk.js.map → google-BtMW9KzL.js.map} +1 -1
- package/dist/{headless-CCm-jLLT.js → headless-CQm19BL0.js} +4 -4
- package/dist/{headless-CCm-jLLT.js.map → headless-CQm19BL0.js.map} +1 -1
- package/dist/headless.d.ts +1 -1
- package/dist/headless.js +1 -1
- package/dist/history-worker.js +1 -1
- package/dist/{host-BHMs9jsN.js → host-DEoEzQal.js} +13 -4
- package/dist/host-DEoEzQal.js.map +1 -0
- package/dist/{host-scoped-settings-CrbcqOkP.js → host-scoped-settings-WBYaCork.js} +2 -2
- package/dist/{host-scoped-settings-CrbcqOkP.js.map → host-scoped-settings-WBYaCork.js.map} +1 -1
- package/dist/{host-signals-Jsjd_-4g.js → host-signals-91zyko_i.js} +5 -5
- package/dist/{host-signals-Jsjd_-4g.js.map → host-signals-91zyko_i.js.map} +1 -1
- package/dist/{host-wO_6GW0y.js → host-uP3t08w8.js} +276 -103
- package/dist/host-uP3t08w8.js.map +1 -0
- package/dist/{host-version-CNAr9pov.js → host-version-_RHlAB29.js} +2 -2
- package/dist/{host-version-CNAr9pov.js.map → host-version-_RHlAB29.js.map} +1 -1
- package/dist/{index-C6nnKu32.d.ts → index-B0PLo9jn.d.ts} +4 -4
- package/dist/{index-C6nnKu32.d.ts.map → index-B0PLo9jn.d.ts.map} +1 -1
- package/dist/{index-Djnc8Peh.d.ts → index-De4x-s76.d.ts} +14 -14
- package/dist/{index-Djnc8Peh.d.ts.map → index-De4x-s76.d.ts.map} +1 -1
- package/dist/{index-CGbOWa7y.d.ts → index-WlE93Q6d.d.ts} +411 -3
- package/dist/index-WlE93Q6d.d.ts.map +1 -0
- package/dist/{index-CCf_WeTQ.d.ts → index-f-XWIoYo.d.ts} +2 -2
- package/dist/{index-CCf_WeTQ.d.ts.map → index-f-XWIoYo.d.ts.map} +1 -1
- package/dist/index.d.ts +5 -5
- package/dist/index.js +17 -17
- package/dist/ipc/browser-types.d.ts +304 -7
- package/dist/ipc/browser-types.d.ts.map +1 -1
- package/dist/ipc/browser.d.ts +4 -4
- package/dist/ipc/browser.js +2 -2
- package/dist/ipc/remote.d.ts +6 -6
- package/dist/ipc/remote.js +3 -3
- package/dist/{ipc-BzWhIybr.js → ipc-CatnsVEd.js} +4 -4
- package/dist/{ipc-BzWhIybr.js.map → ipc-CatnsVEd.js.map} +1 -1
- package/dist/ipc.d.ts +10 -10
- package/dist/ipc.js +8 -8
- package/dist/{json-Dj-YATkZ.js → json-BjClr43H.js} +2 -20
- package/dist/json-BjClr43H.js.map +1 -0
- package/dist/{links-CJG_rFvf.js → links-a8C9eby4.js} +9 -9
- package/dist/{links-CJG_rFvf.js.map → links-a8C9eby4.js.map} +1 -1
- package/dist/{loaded-entry-DTURJo_R.js → loaded-entry-D6jzt5HQ.js} +2 -2
- package/dist/{loaded-entry-DTURJo_R.js.map → loaded-entry-D6jzt5HQ.js.map} +1 -1
- package/dist/mcp.d.ts +1 -1
- package/dist/{media-type-BtA0cbfI.d.ts → media-type-ZSmAGHvg.d.ts} +188 -7
- package/dist/media-type-ZSmAGHvg.d.ts.map +1 -0
- package/dist/{memory-DuVGrzbl.js → memory-CJy52DNi.js} +132 -31
- package/dist/memory-CJy52DNi.js.map +1 -0
- package/dist/model-test-CAtJ76kM.js.map +1 -1
- package/dist/{move-session-kylExJ5H.js → move-session-D7ILECs-.js} +4 -4
- package/dist/{move-session-kylExJ5H.js.map → move-session-D7ILECs-.js.map} +1 -1
- package/dist/{nested-call-record-DlzPeTB7.js → nested-call-record-OayszZBQ.js} +4 -3
- package/dist/nested-call-record-OayszZBQ.js.map +1 -0
- package/dist/output/stream-json.d.ts +1 -1
- package/dist/output/terminal.d.ts +1 -1
- package/dist/{path-display-COVV71Yu.js → path-display-CAWz-sMq.js} +3 -3
- package/dist/{path-display-COVV71Yu.js.map → path-display-CAWz-sMq.js.map} +1 -1
- package/dist/plugins.d.ts +1 -1
- package/dist/{prelude-CVKoUzV8.js → prelude-BwiSR1uA.js} +16 -5
- package/dist/prelude-BwiSR1uA.js.map +1 -0
- package/dist/{presets-CBt6rFfS.js → presets-CMY43nUP.js} +3 -3
- package/dist/{presets-CBt6rFfS.js.map → presets-CMY43nUP.js.map} +1 -1
- package/dist/presets.d.ts +1 -1
- package/dist/presets.js +1 -1
- package/dist/{protocol-CEVqBO-q.d.ts → protocol-C2lqKuMd.d.ts} +50 -7
- package/dist/protocol-C2lqKuMd.d.ts.map +1 -0
- package/dist/protocol-DOGyHgLQ.js.map +1 -1
- package/dist/protocol-NSllElLw.js.map +1 -1
- package/dist/providers/anthropic.d.ts +1 -1
- package/dist/providers/arcee.d.ts +1 -1
- package/dist/providers/baseten.d.ts +1 -1
- package/dist/providers/cerebras.d.ts +1 -1
- package/dist/providers/google.d.ts +1 -1
- package/dist/providers/google.js +1 -1
- package/dist/providers/local.d.ts +1 -1
- package/dist/providers/neuralwatt.d.ts +1 -1
- package/dist/providers/openai-compat.d.ts +1 -1
- package/dist/providers/openai.d.ts +1 -1
- package/dist/providers/openrouter.d.ts +1 -1
- package/dist/providers/xai.d.ts +1 -1
- package/dist/{providers-Z0TaBp1O.js → providers-zVRxiJDv.js} +5 -5
- package/dist/providers-zVRxiJDv.js.map +1 -0
- package/dist/providers.d.ts +1 -1
- package/dist/providers.js +1 -1
- package/dist/{readonly-db-D7Z-k0pQ.js → readonly-db-DrbT8tX6.js} +2 -2
- package/dist/{readonly-db-D7Z-k0pQ.js.map → readonly-db-DrbT8tX6.js.map} +1 -1
- package/dist/{registry-BKjeBnoy.js → registry-CBoYDIND.js} +2 -2
- package/dist/{registry-BKjeBnoy.js.map → registry-CBoYDIND.js.map} +1 -1
- package/dist/{registry-B6Ww76iW.js → registry-CQOU5jvF.js} +2 -2
- package/dist/{registry-B6Ww76iW.js.map → registry-CQOU5jvF.js.map} +1 -1
- package/dist/{registry-B9INJwJR.js → registry-YUUqbYGr.js} +324 -39
- package/dist/registry-YUUqbYGr.js.map +1 -0
- package/dist/{remote-hosts-BMWoHCWO.js → remote-hosts-CT8Q95dR.js} +4 -4
- package/dist/{remote-hosts-BMWoHCWO.js.map → remote-hosts-CT8Q95dR.js.map} +1 -1
- package/dist/{repo-url-D4Dr8NfZ.js → repo-url-DLjjuVk_.js} +169 -2
- package/dist/repo-url-DLjjuVk_.js.map +1 -0
- package/dist/restate.d.ts +2 -2
- package/dist/{sandbox-BwiPGKF7.d.ts → sandbox-B4OW6oNx.d.ts} +2 -2
- package/dist/{sandbox-BwiPGKF7.d.ts.map → sandbox-B4OW6oNx.d.ts.map} +1 -1
- package/dist/script-progress-CrZ507Qq.js +900 -0
- package/dist/script-progress-CrZ507Qq.js.map +1 -0
- package/dist/session/sqlite.d.ts +1 -1
- package/dist/session.d.ts +1 -1
- package/dist/{setting-BQBSyUq0.js → setting-_jh2OtiL.js} +6 -6
- package/dist/{setting-BQBSyUq0.js.map → setting-_jh2OtiL.js.map} +1 -1
- package/dist/{settings-catalog-4IU2i_jG.js → settings-catalog-DEZlXP51.js} +14 -2
- package/dist/settings-catalog-DEZlXP51.js.map +1 -0
- package/dist/{settings-keys-iI_Y-7MC.js → settings-keys-BT0_oKjO.js} +3 -3
- package/dist/{settings-keys-iI_Y-7MC.js.map → settings-keys-BT0_oKjO.js.map} +1 -1
- package/dist/{skills-CFXRItJ6.js → skills-CEbosUlM.js} +2 -2
- package/dist/{skills-CFXRItJ6.js.map → skills-CEbosUlM.js.map} +1 -1
- package/dist/skills.d.ts +1 -1
- package/dist/skills.js +1 -1
- package/dist/{source-Bl1Z501r.js → source-3ZnEPOSa.js} +3 -2
- package/dist/source-3ZnEPOSa.js.map +1 -0
- package/dist/{sqlite-runtime-BZ2L4RaG.d.ts → sqlite-runtime-CS_LBaAN.d.ts} +2 -2
- package/dist/sqlite-runtime-CS_LBaAN.d.ts.map +1 -0
- package/dist/{src-BY_ND2xn.js → src-BmTXDta8.js} +2 -2
- package/dist/{src-BY_ND2xn.js.map → src-BmTXDta8.js.map} +1 -1
- package/dist/{store-C6gI7FfZ.js → store-ByCDaKgJ.js} +14 -3
- package/dist/store-ByCDaKgJ.js.map +1 -0
- package/dist/{system-freeze-m5o1sGIM.js → system-freeze-DxJ-lRhu.js} +3 -3
- package/dist/{system-freeze-m5o1sGIM.js.map → system-freeze-DxJ-lRhu.js.map} +1 -1
- package/dist/{todo-edits-CbukbjyV.js → todo-edits-Dyj32ds6.js} +4 -3
- package/dist/todo-edits-Dyj32ds6.js.map +1 -0
- package/dist/tools/fetch-url.d.ts +1 -1
- package/dist/tools/web-search.d.ts +1 -1
- package/dist/{tools-CVTGhggj.js → tools-BsrGQ8K4.js} +2 -2
- package/dist/{tools-CVTGhggj.js.map → tools-BsrGQ8K4.js.map} +1 -1
- package/dist/tools.d.ts +1 -1
- package/dist/tools.js +3 -3
- package/dist/{transcript-anchors-CiSi_UBn.js → transcript-anchors-DMjvyUjk.js} +3 -3
- package/dist/{transcript-anchors-CiSi_UBn.js.map → transcript-anchors-DMjvyUjk.js.map} +1 -1
- package/dist/{transcript-reconcile-jbSBjLq2.js → transcript-reconcile-DpQO85wl.js} +3 -3
- package/dist/{transcript-reconcile-jbSBjLq2.js.map → transcript-reconcile-DpQO85wl.js.map} +1 -1
- package/dist/tui.d.ts +9 -9
- package/dist/tui.d.ts.map +1 -1
- package/dist/tui.js +289 -38
- package/dist/tui.js.map +1 -1
- package/dist/{types-bDQagoiL.d.ts → types-2HrgolQz.d.ts} +20 -8
- package/dist/types-2HrgolQz.d.ts.map +1 -0
- package/dist/types-4q1bFG53.js +122 -0
- package/dist/types-4q1bFG53.js.map +1 -0
- package/dist/{types-DnRd9_cA.d.ts → types-SXqk6hLD.d.ts} +3 -3
- package/dist/{types-DnRd9_cA.d.ts.map → types-SXqk6hLD.d.ts.map} +1 -1
- package/dist/types-myxheQkw.js.map +1 -1
- package/dist/types.d.ts +3 -3
- package/dist/{usage-summary-BfcXjiSM.js → usage-summary-BM7B3JdI.js} +2 -2
- package/dist/{usage-summary-BfcXjiSM.js.map → usage-summary-BM7B3JdI.js.map} +1 -1
- package/dist/{version-DqqqvHDP.js → version-DwQI12WA.js} +2 -2
- package/dist/{version-DqqqvHDP.js.map → version-DwQI12WA.js.map} +1 -1
- package/dist/{wait-task-BX4NcOOm.js → wait-task-BiI5UaZQ.js} +13 -3
- package/dist/wait-task-BiI5UaZQ.js.map +1 -0
- package/dist/{wire-CLm2rMK0.js → wire-Dxwxb7QQ.js} +2 -2
- package/dist/{wire-CLm2rMK0.js.map → wire-Dxwxb7QQ.js.map} +1 -1
- package/dist/{write-file-0E6TUJ9A.js → write-file-Dquu7MzB.js} +5 -3
- package/dist/write-file-Dquu7MzB.js.map +1 -0
- package/dist/{ws-DfGGYQ4W.js → ws-CA3o2nie.js} +4 -4
- package/dist/{ws-DfGGYQ4W.js.map → ws-CA3o2nie.js.map} +1 -1
- package/dist/{ws-client-CFMbhsNq.js → ws-client-C0iPAAzc.js} +2 -2
- package/dist/{ws-client-CFMbhsNq.js.map → ws-client-C0iPAAzc.js.map} +1 -1
- package/docs/CHAT.md +55 -0
- package/docs/CODEMODE.md +37 -0
- package/docs/EXTENSIONS.md +8 -6
- package/docs/RELEASE-NOTES-NEXT.md +48 -1
- package/docs/RELEASE.md +9 -1
- package/package.json +2 -3
- package/dist/agent-DJhpTS-B.js.map +0 -1
- package/dist/auto-update-restart-BFB7Ek87.js.map +0 -1
- package/dist/browser-BcoCCB_n.js.map +0 -1
- package/dist/contexts-C72b0mMa.js.map +0 -1
- package/dist/decisions-CXmK0nz9.js.map +0 -1
- package/dist/extension-mark-BqKdEZwF.js.map +0 -1
- package/dist/extensions-client-D8tEAcMw.d.ts.map +0 -1
- package/dist/host-BHMs9jsN.js.map +0 -1
- package/dist/host-wO_6GW0y.js.map +0 -1
- package/dist/index-CGbOWa7y.d.ts.map +0 -1
- package/dist/json-Dj-YATkZ.js.map +0 -1
- package/dist/media-type-BtA0cbfI.d.ts.map +0 -1
- package/dist/memory-DuVGrzbl.js.map +0 -1
- package/dist/nested-call-events-BYk8XvGX.js +0 -182
- package/dist/nested-call-events-BYk8XvGX.js.map +0 -1
- package/dist/nested-call-record-DlzPeTB7.js.map +0 -1
- package/dist/prelude-CVKoUzV8.js.map +0 -1
- package/dist/protocol-CEVqBO-q.d.ts.map +0 -1
- package/dist/providers-Z0TaBp1O.js.map +0 -1
- package/dist/registry-B9INJwJR.js.map +0 -1
- package/dist/repo-url-D4Dr8NfZ.js.map +0 -1
- package/dist/settings-catalog-4IU2i_jG.js.map +0 -1
- package/dist/source-Bl1Z501r.js.map +0 -1
- package/dist/sqlite-runtime-BZ2L4RaG.d.ts.map +0 -1
- package/dist/store-C6gI7FfZ.js.map +0 -1
- package/dist/todo-edits-CbukbjyV.js.map +0 -1
- package/dist/types-DTMEhKJO.js +0 -14
- package/dist/types-DTMEhKJO.js.map +0 -1
- package/dist/types-bDQagoiL.d.ts.map +0 -1
- package/dist/wait-task-BX4NcOOm.js.map +0 -1
- package/dist/write-file-0E6TUJ9A.js.map +0 -1
- package/scripts/eval.ts +0 -179
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"todo-edits-CbukbjyV.js","names":[],"sources":["../src/chat/session-query/group.ts","../src/chat/session-query/view.ts","../src/continue-prompt.ts","../src/chat/hosts/host-index.ts","../src/chat/hosts/session-key.ts","../src/chat/attachment-rules.ts","../src/chat/auth-rows.ts","../src/chat/fold-actions.ts","../src/chat/fold-rules.ts","../src/chat/heatmap-levels.ts","../src/chat/instruction-rows.ts","../src/chat/machines-view.ts","../src/chat/mcp-form.ts","../src/chat/notice-format.ts","../src/chat/panels.ts","../src/chat/prompt-text.ts","../src/chat/run-stops.ts","../src/chat/stream-rate.ts","../src/chat/todo-edits.ts"],"sourcesContent":["/**\n * Grouping rows by a field or facet.\n */\n\nimport type { SessionGroup, SessionGroupBy, SessionQueryRow } from './types'\nimport { parseFieldPath, readParsedField } from './fields'\nimport { SessionQueryError } from './types'\nimport { validateGroupBy } from './validate'\n\nconst collator = new Intl.Collator('en', { numeric: true, sensitivity: 'base' })\n\n/** Options of {@link groupRows}. */\nexport interface GroupOptions {\n /** Labels by group key the caller knows (agent names, project names). The grouping's own `labels` win. */\n labels?: Readonly<Record<string, string>>\n /** Label of the group of rows without a value. Default `'None'`. */\n missingLabel?: string\n}\n\nfunction keyOf(value: unknown): string {\n return typeof value === 'string' ? value : typeof value === 'object' ? JSON.stringify(value) : String(value)\n}\n\n/**\n * The group keys of a value: one for a scalar, one per distinct element for\n * a list, none for a missing value or an empty list.\n *\n * @param value - A field value.\n */\nexport function groupKeysOf(value: unknown): string[] {\n if (value === undefined || value === null)\n return []\n if (Array.isArray(value))\n return [...new Set(value.filter(v => v !== undefined && v !== null).map(keyOf))]\n return [keyOf(value)]\n}\n\n/**\n * Groups rows by `groupBy.field`. Rows keep their input order inside each\n * group, so sort first. Groups are ordered by `groupBy.order`; the group of\n * rows without a value (key `null`) comes last. Throws\n * {@link SessionQueryError} for an invalid grouping.\n *\n * @param rows - The rows, already sorted.\n * @param groupBy - The grouping.\n * @param options - Caller labels and the missing-value label.\n */\nexport function groupRows<R extends SessionQueryRow>(rows: readonly R[], groupBy: SessionGroupBy, options: GroupOptions = {}): SessionGroup<R>[] {\n const issues = validateGroupBy(groupBy)\n if (issues.length > 0)\n throw new SessionQueryError(issues)\n const field = parseFieldPath(groupBy.field)!\n const groups = new Map<string, SessionGroup<R>>()\n const missing: R[] = []\n for (const row of rows) {\n const keys = groupKeysOf(readParsedField(row, field))\n if (keys.length === 0)\n missing.push(row)\n for (const key of keys) {\n let group = groups.get(key)\n if (!group) {\n const label = (groupBy.labels && Object.hasOwn(groupBy.labels, key) ? groupBy.labels[key] : undefined)\n ?? (options.labels && Object.hasOwn(options.labels, key) ? options.labels[key] : undefined)\n ?? key\n group = { key, label, rows: [] }\n groups.set(key, group)\n }\n group.rows.push(row)\n }\n }\n const byLabel = (a: SessionGroup<R>, b: SessionGroup<R>): number => collator.compare(a.label, b.label) || (a.key! < b.key! ? -1 : a.key! > b.key! ? 1 : 0)\n const order = groupBy.order ?? 'asc'\n let list = [...groups.values()]\n if (order === 'asc' || order === 'desc') {\n list.sort(byLabel)\n if (order === 'desc')\n list.reverse()\n }\n else {\n const rankOf = new Map<string, number>()\n order.forEach((key, i) => {\n if (!rankOf.has(key))\n rankOf.set(key, i)\n })\n const listed = list.filter(g => rankOf.has(g.key!)).sort((a, b) => rankOf.get(a.key!)! - rankOf.get(b.key!)!)\n list = [...listed, ...list.filter(g => !rankOf.has(g.key!)).sort(byLabel)]\n }\n if (missing.length > 0)\n list.push({ key: null, label: options.missingLabel ?? 'None', rows: missing })\n return list\n}\n","/**\n * The query a sidebar view stands for: the space's sessions, then the\n * view's filters. Every app that saves a view as a space builds it here,\n * so the saved space lists what the view listed.\n */\n\nimport type { QueryBound, SessionQuery, SessionQueryIssue } from './types'\nimport { validateQuery } from './validate'\n\n/** The Default space's id (`DEFAULT_SPACE_ID` in `src/chat/spaces.ts`; a test keeps the two equal). */\nconst DEFAULT_SPACE = 'default'\n\n/** The space a view is on. */\nexport interface SessionViewSpace {\n /** Space id: `default`, a user space's id, or `<extension>/<id>`. */\n id: string\n /** The space's own query, when it has one: the sessions it lists besides those tagged with it. */\n query?: SessionQuery\n}\n\n/** The filters of a sidebar view. Each one left out keeps every session. */\nexport interface SessionView {\n /** Only sessions of this project, by folder name (`projectName`, exact). */\n project?: string | null\n /** Only sessions on this agent profile. */\n agent?: string | null\n /** `active`: leave archived sessions out; `archived`: only those; `all`: both. */\n archive?: 'active' | 'archived' | 'all'\n /** Only sessions updated at or after this bound (`'-7d'`, epoch ms). */\n updatedSince?: QueryBound\n /** The queries of the extension filters the user turned on, each one holding. */\n filters?: readonly SessionQuery[]\n}\n\n/** What {@link viewQuery} takes. */\nexport interface ViewQueryInput {\n /** The space the view is on. `null` or absent while spaces are off: the view spans every session. */\n space?: SessionViewSpace | null\n /** The view's filters. */\n view: SessionView\n /** The id of every space that exists (user and extension spaces; `default` may be in it). */\n knownSpaceIds: readonly string[]\n}\n\n/** What {@link viewQuery} returns: the query, or the problems that made it invalid. */\nexport type ViewQueryResult\n = | { query: SessionQuery, issues?: undefined }\n | { query?: undefined, issues: SessionQueryIssue[] }\n\n/**\n * `query` with nested `all` in `all` and `any` in `any` merged into their\n * parent, and a one-element `all` / `any` replaced by its element. Matches\n * the same rows.\n *\n * @param query - A query.\n */\nexport function flattenQuery(query: SessionQuery): SessionQuery {\n if ('not' in query && query.not !== undefined)\n return { not: flattenQuery(query.not) }\n for (const kind of ['all', 'any'] as const) {\n const list = (query as unknown as Record<string, unknown>)[kind]\n if (!Array.isArray(list))\n continue\n const merged = (list as SessionQuery[]).map(flattenQuery).flatMap((child) => {\n const inner = (child as unknown as Record<string, unknown>)[kind]\n return Array.isArray(inner) ? inner as SessionQuery[] : [child]\n })\n if (merged.length === 1)\n return merged[0]!\n return (kind === 'all' ? { all: merged } : { any: merged })\n }\n return query\n}\n\n/**\n * Which sessions a space lists, as a query: the Main session, those tagged\n * with the space, and those its own query matches. Default's tagged sessions\n * are those tagged with no space that exists (untagged, `default`, or a\n * deleted or unknown space).\n */\nfunction membership(space: SessionViewSpace, knownSpaceIds: readonly string[]): SessionQuery {\n const tagged: SessionQuery = space.id === DEFAULT_SPACE\n ? { field: 'spaceId', nin: [...new Set(knownSpaceIds.filter(id => id !== DEFAULT_SPACE))] }\n : { field: 'spaceId', eq: space.id }\n return { any: [{ field: 'isMain', eq: true }, tagged, ...(space.query ? [space.query] : [])] }\n}\n\n/**\n * The query a sidebar view stands for, to save it as a space: the space's\n * membership (see {@link SessionViewSpace}), then the project, agent,\n * archive, activity and extension filters, all holding, flattened. Returns\n * the problems instead when the result is not a valid query (too deep, too\n * many nodes or values).\n *\n * @param input - The space, the view and the known space ids.\n */\nexport function viewQuery(input: ViewQueryInput): ViewQueryResult {\n const { space, view } = input\n const parts: SessionQuery[] = []\n if (space)\n parts.push(membership(space, input.knownSpaceIds))\n if (view.project)\n parts.push({ field: 'projectName', eq: view.project })\n if (view.agent)\n parts.push({ field: 'agentId', eq: view.agent })\n if (view.archive === 'active' || view.archive === 'archived')\n parts.push({ field: 'archived', eq: view.archive === 'archived' })\n if (view.updatedSince !== undefined)\n parts.push({ field: 'updatedAt', gte: view.updatedSince })\n parts.push(...(view.filters ?? []))\n const query = flattenQuery({ all: parts })\n const issues = validateQuery(query, 'query')\n return issues.length > 0 ? { issues } : { query }\n}\n","/** What the \"continue\" action sends after a run that had done work. */\nexport const CONTINUE_PROMPT = 'Continue from where you stopped.'\n","/**\n * Which host an id lives on: a session (or a request a host handed out: an\n * approval, a question, a terminal). A client learns it from what a host\n * tells it (its lists, a create, an activation, its signals) and routes\n * every later call on that id there.\n *\n * Never guessed: an id no host told about is an error\n * ({@link UnknownHostIdError}), one several hosts list is an error unless the\n * lookup names its host ({@link AmbiguousHostIdError}), and the ids of a host\n * that was removed stay remembered as such ({@link HostRemovedError}) until\n * a host claims them again, so nothing aimed at a removed server quietly\n * lands on another host.\n * Node-free, shared by the TUI and the GUI main process.\n */\n\n/** No host told this client about the id: nothing to route it to. */\nexport class UnknownHostIdError extends Error {\n /** Machine-readable error code. */\n readonly code = 'unknown-host-id'\n /**\n * Creates the error.\n * @param id - Id that no host reported.\n * @param noun - What the id names, used in the message.\n */\n constructor(readonly id: string, noun = 'session') {\n super(`No host is known for ${noun} \"${id}\": list or open it on its host first.`)\n this.name = 'UnknownHostIdError'\n }\n}\n\n/** The id lived on a host that was removed from this window. */\nexport class HostRemovedError extends Error {\n /** Machine-readable error code. */\n readonly code = 'host-removed'\n /**\n * Creates the error.\n * @param hostKey - Key of the removed host.\n * @param hostName - Display name of the removed host.\n */\n constructor(readonly hostKey: string, readonly hostName: string) {\n super(`${hostName} was removed.`)\n this.name = 'HostRemovedError'\n }\n}\n\n/**\n * Several hosts list the id (two hosts can hold the same session id: a\n * server sharing this machine's data dir, a copied store) and the lookup\n * did not say which: refused, never guessed.\n */\nexport class AmbiguousHostIdError extends Error {\n /** Machine-readable error code. */\n readonly code = 'ambiguous-host-id'\n /**\n * Creates the error.\n * @param id - Id that several hosts list.\n * @param hostKeys - Keys of the hosts that list it.\n * @param noun - What the id names, used in the message.\n */\n constructor(readonly id: string, readonly hostKeys: readonly string[], noun = 'session') {\n super(`${noun[0]!.toUpperCase()}${noun.slice(1)} \"${id}\" exists on several hosts (${hostKeys.join(', ')}): say which one.`)\n this.name = 'AmbiguousHostIdError'\n }\n}\n\n/**\n * Keyed by (host, id): the same id may live on several hosts. A lookup that\n * names its host (`hostKey`) gets exactly that pair; one that doesn't\n * resolves only when one host has the id.\n */\nexport interface HostIndex {\n /** `id` lives on `hostKey` (clears that pair's removed-host mark). */\n note: (id: string, hostKey: string) => void\n /** The id is gone from `hostKey` (deleted there), or from every host. */\n forget: (id: string, hostKey?: string) => void\n /** With `hostKey`: it, when `id` is known live there. Without: the one live host of `id` (`undefined` when none, or several). */\n hostOf: (id: string, hostKey?: string) => string | undefined\n /** Every live host of `id`. */\n hostsOf: (id: string) => string[]\n /**\n * The live host of `id` (with `hostKey`: that pair). Throws\n * {@link HostRemovedError}, {@link UnknownHostIdError}, or without\n * `hostKey` {@link AmbiguousHostIdError} when several hosts have it.\n */\n require: (id: string, hostKey?: string) => string\n /** The removed host `id` lived on (with `hostKey`: that one), if any. */\n removedHostOf: (id: string, hostKey?: string) => { key: string, name: string } | undefined\n /** Ids noted on `hostKey`. */\n idsOf: (hostKey: string) => string[]\n /** The host was removed: its pairs are marked so (lookups say so); returns their ids. */\n dropHost: (hostKey: string, hostName: string) => string[]\n}\n\n/**\n * Creates an empty index of which host holds each id.\n *\n * @param noun - What the ids name, used in error messages.\n */\nexport function createHostIndex(noun = 'session'): HostIndex {\n /** id → live host keys, in the order they were noted. */\n const live = new Map<string, Set<string>>()\n /** id → removed host key → its name. */\n const removed = new Map<string, Map<string, string>>()\n const liveOf = (id: string): string[] => [...(live.get(id) ?? [])]\n const removedOf = (id: string, hostKey?: string): { key: string, name: string } | undefined => {\n const marks = removed.get(id)\n if (!marks)\n return undefined\n if (hostKey !== undefined) {\n const name = marks.get(hostKey)\n return name === undefined ? undefined : { key: hostKey, name }\n }\n const first = [...marks][0]\n return first ? { key: first[0], name: first[1] } : undefined\n }\n const index: HostIndex = {\n note: (id, hostKey) => {\n let hosts = live.get(id)\n if (!hosts)\n live.set(id, hosts = new Set())\n hosts.add(hostKey)\n const marks = removed.get(id)\n marks?.delete(hostKey)\n if (marks?.size === 0)\n removed.delete(id)\n },\n forget: (id, hostKey) => {\n if (hostKey === undefined) {\n live.delete(id)\n removed.delete(id)\n return\n }\n live.get(id)?.delete(hostKey)\n if (live.get(id)?.size === 0)\n live.delete(id)\n removed.get(id)?.delete(hostKey)\n if (removed.get(id)?.size === 0)\n removed.delete(id)\n },\n hostOf: (id, hostKey) => {\n const hosts = liveOf(id)\n if (hostKey !== undefined)\n return hosts.includes(hostKey) ? hostKey : undefined\n return hosts.length === 1 ? hosts[0] : undefined\n },\n hostsOf: liveOf,\n require: (id, hostKey) => {\n const hosts = liveOf(id)\n if (hostKey !== undefined) {\n if (hosts.includes(hostKey))\n return hostKey\n const gone = removedOf(id, hostKey)\n if (gone)\n throw new HostRemovedError(gone.key, gone.name)\n throw new UnknownHostIdError(id, noun)\n }\n if (hosts.length === 1)\n return hosts[0]!\n if (hosts.length > 1)\n throw new AmbiguousHostIdError(id, hosts, noun)\n const gone = removedOf(id)\n if (gone)\n throw new HostRemovedError(gone.key, gone.name)\n throw new UnknownHostIdError(id, noun)\n },\n removedHostOf: removedOf,\n idsOf: hostKey => [...live].filter(([, hosts]) => hosts.has(hostKey)).map(([id]) => id),\n dropHost: (hostKey, hostName) => {\n const ids = index.idsOf(hostKey)\n for (const id of ids) {\n index.forget(id, hostKey)\n let marks = removed.get(id)\n if (!marks)\n removed.set(id, marks = new Map())\n marks.set(hostKey, hostName)\n }\n return ids\n },\n }\n return index\n}\n","/**\n * A session's identity across hosts: the (host, session) pair, as one\n * string every client keys rows, maps and persisted state by. Two hosts may\n * hold the same session id (a server sharing this computer's data dir, a\n * copied store), so a bare id never names a session on its own once several\n * hosts are listed.\n *\n * The host is named by its HOST KEY, the key of a client's host directory:\n * {@link LOCAL_HOST_KEY} for This computer (the in-process host or the\n * daemon), a saved server's `hostId` (for a server, hostKey === hostId),\n * or a client's own key for a host it never saves (the TUI's `--host`\n * server: `'ad-hoc'`).\n *\n * The encoding, shared by the TUI and the GUI:\n *\n * - This computer: the bare id (`abc`). Local-only users see exactly the\n * ids, and state persisted before keys existed still means the same\n * session.\n * - Any other host: `<hostKey>␟<id>` (U+001F, never in a host key).\n *\n * A local id that itself contains U+001F is written `local␟<id>`, so a key\n * always parses back to the pair it was made from. Node-free.\n */\nimport { LOCAL_HOST_KEY } from './connection'\n\n/** Character that separates the host key from the session id in a session key (U+001F). */\nexport const SESSION_KEY_SEPARATOR = '\\u001F'\n\n/** The pair a session key names. */\nexport interface SessionKeyParts {\n /** Always explicit: {@link LOCAL_HOST_KEY} for This computer. */\n hostKey: string\n /** Session id on that host. */\n sessionId: string\n}\n\n/**\n * The key of `sessionId` on `hostKey` (`null` / absent / {@link LOCAL_HOST_KEY}: a local session).\n *\n * @param hostKey - Key of the host. `null`, absent or the local host key mean This computer.\n * @param sessionId - Session id on that host.\n */\nexport function sessionKey(hostKey: string | null | undefined, sessionId: string): string {\n if (!hostKey || hostKey === LOCAL_HOST_KEY)\n return sessionId.includes(SESSION_KEY_SEPARATOR) ? `${LOCAL_HOST_KEY}${SESSION_KEY_SEPARATOR}${sessionId}` : sessionId\n if (hostKey.includes(SESSION_KEY_SEPARATOR))\n throw new Error('A host key cannot contain U+001F.')\n return `${hostKey}${SESSION_KEY_SEPARATOR}${sessionId}`\n}\n\n/**\n * The pair `key` names (a bare id: This computer's).\n *\n * @param key - Key built by {@link sessionKey}.\n */\nexport function parseSessionKey(key: string): SessionKeyParts {\n const at = key.indexOf(SESSION_KEY_SEPARATOR)\n if (at < 0)\n return { hostKey: LOCAL_HOST_KEY, sessionId: key }\n return { hostKey: key.slice(0, at), sessionId: key.slice(at + 1) }\n}\n","/**\n * What a prompt can carry as an attachment, the same in every composer: the\n * image types every provider reads, PDFs, and files whose bytes read as\n * text, each under its size cap. Anything else is refused with a reason the\n * composer puts into words.\n *\n * Pure: a browser composer reads a file's first bytes and asks\n * {@link planAttachment}; the TUI shares the caps.\n */\nimport { looksBinary } from '../tools/binary-detect'\n\n/**\n * Cap on an image's bytes. Base64 inflates ~33%, so this keeps the encoded\n * payload under Anthropic's 5 MB image ceiling while covering essentially\n * every screenshot. A composer scales a bigger image down to fit.\n */\nexport const MAX_IMAGE_ATTACHMENT_BYTES = 3.5 * 1024 * 1024\n\n/** Cap on a PDF's or a text file's bytes. */\nexport const MAX_FILE_ATTACHMENT_BYTES = 20 * 1024 * 1024\n\n/** How much of a file's start {@link planAttachment} reads to tell text from binary. */\nexport const ATTACHMENT_SNIFF_BYTES = 8192\n\n/** Image types every provider takes as they are. */\nexport const SENDABLE_IMAGE_TYPES: ReadonlySet<string> = new Set(['image/png', 'image/jpeg', 'image/gif', 'image/webp'])\n\n/** Image types by extension, for files handed over untyped. */\nconst IMAGE_BY_EXTENSION: Readonly<Record<string, string>> = {\n png: 'image/png',\n jpg: 'image/jpeg',\n jpeg: 'image/jpeg',\n gif: 'image/gif',\n webp: 'image/webp',\n avif: 'image/avif',\n bmp: 'image/bmp',\n ico: 'image/x-icon',\n svg: 'image/svg+xml',\n heic: 'image/heic',\n heif: 'image/heif',\n tif: 'image/tiff',\n tiff: 'image/tiff',\n}\n\n/** Office and iWork documents: the model reads them once exported as PDF. */\nconst EXPORT_AS_PDF: ReadonlySet<string> = new Set(['doc', 'docx', 'odt', 'pages', 'ppt', 'pptx', 'odp', 'key', 'xls', 'xlsx', 'ods', 'numbers'])\n\n/** A file a composer was handed, as {@link planAttachment} needs it. */\nexport interface AttachmentCandidate {\n /** The file's name. Its extension stands in for a missing type. */\n name: string\n /** The type the browser or the OS reported. Often empty. */\n mediaType: string\n /** Size in bytes. */\n size: number\n /** The file's first {@link ATTACHMENT_SNIFF_BYTES} bytes decoded as UTF-8, invalid bytes as U+FFFD. */\n head: string\n}\n\n/** Why a file is not attached. */\nexport type AttachmentRefusal\n = | { reason: 'empty' }\n | { reason: 'too-large', size: number, limit: number }\n /** An Office or iWork document. */\n | { reason: 'export-pdf' }\n /** An image the composer could not decode to convert it (HEIC or TIFF in Chromium). */\n | { reason: 'unreadable-image' }\n | { reason: 'unsupported' }\n\n/**\n * What to do with a file: attach its bytes as they are, typed `mediaType`;\n * decode and re-encode an image first (a format providers don't take, or\n * over {@link MAX_IMAGE_ATTACHMENT_BYTES}); or refuse it.\n */\nexport type AttachmentPlan\n = | { kind: 'image' | 'pdf' | 'text', mediaType: string }\n | { kind: 'convert-image', mediaType: string }\n | ({ kind: 'refuse' } & AttachmentRefusal)\n\n/** Declared types that already say text: kept as they are. */\nfunction isTextType(mime: string): boolean {\n return mime.startsWith('text/')\n || mime === 'application/json'\n || mime === 'application/xml'\n || mime === 'application/javascript'\n || mime === 'application/typescript'\n || mime.endsWith('+json')\n || mime.endsWith('+xml')\n}\n\nfunction extensionOf(name: string): string {\n const base = name.slice(name.lastIndexOf('/') + 1).toLowerCase()\n const dot = base.lastIndexOf('.')\n return dot > 0 ? base.slice(dot + 1) : ''\n}\n\nconst tooLarge = (size: number, limit: number): AttachmentPlan => ({ kind: 'refuse', reason: 'too-large', size, limit })\n\n/**\n * Decide how a file is attached. Images go by type (or extension); PDFs by\n * type, extension or their `%PDF-` signature; anything else is text when its\n * first bytes read as text, sent as `text/plain` unless its type already\n * names text (a `.ts` file the browser types `video/mp2t` is text).\n *\n * @param file - The file's name, reported type, size and first bytes.\n */\nexport function planAttachment(file: AttachmentCandidate): AttachmentPlan {\n if (file.size === 0)\n return { kind: 'refuse', reason: 'empty' }\n const declared = file.mediaType.split(';')[0]!.trim().toLowerCase()\n const ext = extensionOf(file.name)\n const image = declared.startsWith('image/') ? declared : IMAGE_BY_EXTENSION[ext]\n if (image) {\n return SENDABLE_IMAGE_TYPES.has(image) && file.size <= MAX_IMAGE_ATTACHMENT_BYTES\n ? { kind: 'image', mediaType: image }\n : { kind: 'convert-image', mediaType: image }\n }\n if (declared === 'application/pdf' || ext === 'pdf' || file.head.startsWith('%PDF-')) {\n return file.size > MAX_FILE_ATTACHMENT_BYTES\n ? tooLarge(file.size, MAX_FILE_ATTACHMENT_BYTES)\n : { kind: 'pdf', mediaType: 'application/pdf' }\n }\n if (EXPORT_AS_PDF.has(ext))\n return { kind: 'refuse', reason: 'export-pdf' }\n if (looksBinary(file.head))\n return { kind: 'refuse', reason: 'unsupported' }\n if (file.size > MAX_FILE_ATTACHMENT_BYTES)\n return tooLarge(file.size, MAX_FILE_ATTACHMENT_BYTES)\n return { kind: 'text', mediaType: isTextType(declared) ? declared : 'text/plain' }\n}\n","/**\n * Renderer-agnostic data model for the Authentication settings list when a\n * provider holds more than one credential source.\n *\n * Mirrors `chat/mcp-rows.ts` deliberately: a flat row list plus a single\n * integer cursor that walks both provider headers AND their nested source\n * rows, so a renderer iterates once and never needs separate \"which provider\n * am I on / which source inside it\" state.\n *\n * Lives in `chat/` rather than `tui/` for the same reason as the MCP model —\n * the flattening and cursor arithmetic are pure, and pure means they can be\n * asserted directly instead of through a rendered modal.\n *\n * A provider is only expandable when it has MORE THAN ONE source. Single-source\n * providers (the overwhelming majority) are one row with no chevron and no\n * expansion state. That keeps the list quiet for anyone who has not stacked two\n * credentials.\n */\n\nimport type { AuthMethod, ProviderAuth } from './auth'\n\n/**\n * One row in the flattened Authentication list. Two kinds:\n *\n * - `'provider'` — provider header with label, configured badge, and (when\n * expandable) the chevron. Always present.\n * - `'source'` — one credential source belonging to the provider above.\n * Present only while that provider is expanded.\n */\nexport type VisibleAuthRow\n = | { kind: 'provider', provider: ProviderAuth, expandable: boolean }\n | { kind: 'source', providerKey: string, method: AuthMethod }\n\n/**\n * Stored credentials, i.e. the ones a user can actually choose between.\n *\n * `env` is excluded: it is observed rather than stored, and is usually just the\n * mirror `applyApiKeyEnv` wrote from the stored API key, so counting it would\n * advertise a choice that does not exist.\n *\n * @param provider - The provider whose auth methods are filtered.\n */\nexport function selectableSources(provider: ProviderAuth): AuthMethod[] {\n return provider.methods.filter(m => m.source !== 'env')\n}\n\n/**\n * A provider earns a chevron only when there is a real choice to reveal.\n *\n * @param provider - The provider to test.\n */\nexport function isExpandableProvider(provider: ProviderAuth): boolean {\n return selectableSources(provider).length > 1\n}\n\n/**\n * Flatten the provider list plus the expanded set into the visible-row list.\n *\n * - `providers` — filtered / ordered provider list (post-search).\n * - `expanded` — keys of providers whose sources are open. Keys for\n * providers that are no longer expandable are ignored rather\n * than cleaned up, so stale expansion state (a credential\n * removed while the modal is open) can't desync the cursor.\n *\n * @param providers - Filtered and ordered provider list.\n * @param expanded - Keys of providers whose sources are open.\n */\nexport function buildVisibleAuthRows(\n providers: readonly ProviderAuth[],\n expanded: ReadonlySet<string>,\n): VisibleAuthRow[] {\n const out: VisibleAuthRow[] = []\n for (const provider of providers) {\n const expandable = isExpandableProvider(provider)\n out.push({ kind: 'provider', provider, expandable })\n if (!expandable || !expanded.has(provider.key))\n continue\n for (const method of selectableSources(provider))\n out.push({ kind: 'source', providerKey: provider.key, method })\n // The env slot is listed for context whenever the provider declares one,\n // present or not. It disappears from `methods` the moment a stored OAuth\n // grant wins (`applyApiKeyEnv` clears the var so the refresh path reads the\n // file), and a row that vanishes on selection reads as a bug.\n if (provider.envKey) {\n const envMethod = provider.methods.find(m => m.source === 'env')\n out.push({\n kind: 'source',\n providerKey: provider.key,\n method: envMethod ?? { source: 'env', detail: provider.envKey, active: false },\n })\n }\n }\n return out\n}\n\n/**\n * Provider key a row \"belongs to\" — its own for a provider header, the parent's\n * for a source row.\n *\n * @param row - A visible row.\n */\nexport function parentProviderKey(row: VisibleAuthRow): string {\n return row.kind === 'provider' ? row.provider.key : row.providerKey\n}\n\n/**\n * Index in `rows` of the header for the given provider key, or `-1`.\n *\n * Collapse handlers snap the cursor up to the parent BEFORE the row list\n * shrinks; without that the cursor keeps its flat index and silently lands on\n * whichever sibling row slid into that slot.\n *\n * @param rows - The visible rows.\n * @param providerKey - Key of the provider to find.\n */\nexport function indexOfProviderRow(rows: readonly VisibleAuthRow[], providerKey: string): number {\n return rows.findIndex(r => r.kind === 'provider' && r.provider.key === providerKey)\n}\n","/**\n * The words for what the agent did, shared by the GUI's compact fold and\n * the TUI's: one overview line per tool call (`Ran bun test`, `Edited\n * Timeline.tsx +12 −3`, `Read select-stops.ts`), and the settled summary\n * of a batch (`Read a file, ran a command +3`).\n *\n * An overview says WHAT happened, not the payload; the payload stays one\n * click away and in `title`.\n */\nimport type { EditPayload } from './types'\nimport { readFileInputPaths } from '../tools/read-file-targets'\nimport { computeLineDiff } from './edit-diff'\nimport { descriptionLabel } from './tool-formatters'\n\n// ---------------------------------------------------------------------------\n// Shell commands → a gist\n// ---------------------------------------------------------------------------\n\n/** Programs whose first argument is the thing they do (`git status`, `bun test`). */\nconst SUBCOMMAND_PROGRAMS = new Set([\n 'git',\n 'gh',\n 'bun',\n 'npm',\n 'pnpm',\n 'yarn',\n 'npx',\n 'bunx',\n 'cargo',\n 'go',\n 'docker',\n 'kubectl',\n 'make',\n 'uv',\n 'pip',\n 'pip3',\n 'brew',\n 'deno',\n 'node',\n 'playwright',\n 'vitest',\n 'jest',\n 'tsc',\n 'eslint',\n 'prettier',\n])\n/** Wrappers that only change how the next program runs. */\nconst WRAPPERS = new Set(['sudo', 'time', 'nice', 'nohup', 'exec', 'command', 'caffeinate'])\n/** Setup steps that carry no meaning of their own. */\nconst SETUP = new Set(['cd', 'pushd', 'popd', 'export', 'set', 'source', '.', 'unset', 'true', 'mkdir'])\n\n/** Split on `&&`, `||`, `;`, `|` and newlines outside quotes. */\nfunction splitSegments(command: string): string[] {\n const out: string[] = []\n let cur = ''\n let quote: '\"' | '\\'' | null = null\n for (let i = 0; i < command.length; i++) {\n const ch = command[i]!\n if (quote) {\n if (ch === quote)\n quote = null\n cur += ch\n continue\n }\n if (ch === '\"' || ch === '\\'') {\n quote = ch\n cur += ch\n continue\n }\n const two = command.slice(i, i + 2)\n if (two === '&&' || two === '||') {\n out.push(cur)\n cur = ''\n i++\n continue\n }\n if (ch === ';' || ch === '|' || ch === '\\n') {\n out.push(cur)\n cur = ''\n continue\n }\n cur += ch\n }\n out.push(cur)\n return out.map(s => s.trim()).filter(Boolean)\n}\n\n/** Words of a segment, quotes kept as one word (unquoted). */\nfunction words(segment: string): string[] {\n const out: string[] = []\n const re = /\"([^\"]*)\"|'([^']*)'|(\\S+)/g\n for (const m of segment.matchAll(re))\n out.push(m[1] ?? m[2] ?? m[3] ?? '')\n return out\n}\n\n/** The gist of one segment (`bun run build`, `python3`), or null for setup noise. */\nfunction segmentGist(segment: string): string | null {\n let w = words(segment)\n // Leading env assignments (`FOO=1 cmd`), then wrappers (`sudo`, `env -u X`, `timeout 30`).\n for (;;) {\n if (w.length === 0)\n return null\n const head = w[0]!\n if (/^[A-Z_]\\w*=/i.test(head)) {\n w = w.slice(1)\n }\n else if (WRAPPERS.has(head)) {\n w = w.slice(1)\n }\n else if (head === 'env') {\n w = w.slice(1)\n while (w[0] && (w[0].startsWith('-') || /^[A-Z_]\\w*=/i.test(w[0]))) {\n const flag = w[0]\n w = w.slice(1)\n if (flag === '-u' && w[0])\n w = w.slice(1)\n }\n }\n else if (head === 'timeout' && w[1] && /^\\d/.test(w[1])) {\n w = w.slice(2)\n }\n else {\n break\n }\n }\n const program = w[0]!.split('/').pop()!\n if (SETUP.has(program))\n return null\n if (!SUBCOMMAND_PROGRAMS.has(program))\n return program\n const rest = w.slice(1).filter(arg => !arg.startsWith('-'))\n let sub: string | undefined = rest[0]\n // `npx tsc`, `bunx playwright test`: the tool after the runner, and its own subcommand.\n if ((program === 'npx' || program === 'bunx') && sub) {\n const tool = sub.split('/').pop()!\n const next = rest[1]\n return SUBCOMMAND_PROGRAMS.has(tool) && next && !next.includes('/') && !next.includes('.')\n ? `${tool} ${next}`\n : tool\n }\n // `bun run build`: the script name is the subcommand's point.\n if ((sub === 'run' || sub === 'exec') && rest[1] && ['bun', 'npm', 'pnpm', 'yarn'].includes(program)) {\n return `${program} ${sub} ${rest[1]}`\n }\n // A path or file is an argument, not a subcommand (`node script.js` → `node`).\n if (sub && (sub.includes('/') || /\\.[a-z]+$/i.test(sub)))\n sub = undefined\n return sub ? `${program} ${sub}` : program\n}\n\n/**\n * `Ran <gist>` for a shell command: heredoc bodies dropped, setup steps\n * (`cd`, `export`, `set -e`) skipped, env and wrappers peeled off, program\n * plus subcommand kept. Further meaningful steps read as `+N`.\n *\n * @param command - Shell command text, possibly several steps.\n */\nexport function commandGist(command: string): { gist: string, more: number } {\n // eslint-disable-next-line regexp/no-super-linear-backtracking -- bounded by one command's text\n const withoutHeredocs = command.replace(/<<-?\\s*(['\"]?)(\\w+)\\1[\\s\\S]*?(?:\\n\\2\\b|$)/g, '')\n const gists = splitSegments(withoutHeredocs)\n .map(segmentGist)\n .filter((g): g is string => g !== null)\n if (gists.length === 0)\n return { gist: 'a command', more: 0 }\n return { gist: gists[0]!, more: gists.length - 1 }\n}\n\n// ---------------------------------------------------------------------------\n// One tool call → its overview\n// ---------------------------------------------------------------------------\n\n/** What a tool call is, independent of how a surface stores it. */\nexport interface ToolOverviewInput {\n /** Tool name, such as `shell` or `read_file`. */\n name: string\n /** Name shown to the user for the tool. */\n displayName: string\n /** The call's input arguments. */\n input?: Record<string, unknown>\n /** The formatted target (`tool-formatters`), when there is one. */\n target?: string\n /** The call's result text, once it has one. */\n result?: string | null\n /** `null` while running. */\n ok?: boolean | null\n /** Edit payload, when the call changed a file. */\n edit?: EditPayload\n}\n\n/** One-line description of a tool call, built by {@link toolOverview}. */\nexport interface ToolOverview {\n /** What the call did, such as `Ran bun test`. */\n label: string\n /** Quiet context after the label: a file's directory, `+2` chained commands. */\n hint?: string\n /** Lines added, for edits. */\n added?: number\n /** Lines removed, for edits. */\n removed?: number\n /** The full payload (the whole command, the full path). */\n title?: string\n}\n\nfunction splitPath(path: string): { name: string, dir: string } {\n const clean = path.replace(/\\/+$/, '')\n const i = clean.lastIndexOf('/')\n return i < 0 ? { name: clean, dir: '' } : { name: clean.slice(i + 1), dir: clean.slice(0, i) }\n}\n\nfunction str(input: Record<string, unknown> | undefined, key: string): string | undefined {\n const v = input?.[key]\n return typeof v === 'string' && v.trim() !== '' ? v : undefined\n}\n\n/** Line counts exactly as the diff in the details shows them. */\nfunction editCounts(edit: EditPayload | undefined): { added: number, removed: number } | null {\n if (!edit)\n return null\n let added = 0\n let removed = 0\n for (const h of edit.hunks) {\n for (const d of computeLineDiff(h.oldString, h.newString)) {\n if (d.op === 'add')\n added++\n else if (d.op === 'remove')\n removed++\n }\n }\n return { added, removed }\n}\n\nfunction shortUrl(url: string): string {\n const short = url.replace(/^https?:\\/\\//, '').replace(/\\/$/, '')\n return short.length > 48 ? `${short.slice(0, 47)}…` : short\n}\n\n/**\n * The dev browser in words: where it went and what it did. Clicks and typing\n * read their result's first line (`Clicked \"Save\"`), which names the element;\n * the ref the model used (`e12`) means nothing to a person.\n */\nfunction browserOverview(tool: ToolOverviewInput): ToolOverview | null {\n const input = tool.input\n const url = str(input, 'url')\n const head = typeof tool.result === 'string' && tool.ok\n ? tool.result.split('\\n')[0]!.replace(/\\. No navigation, dialog or error\\.$|\\.$/, '')\n : ''\n switch (tool.name) {\n case 'browser_open':\n return url ? { label: `Opened ${shortUrl(url)}`, title: url } : { label: 'Opened the browser' }\n case 'browser_navigate': {\n const action = str(input, 'action')\n if (action === 'back')\n return { label: 'Went back' }\n if (action === 'forward')\n return { label: 'Went forward' }\n if (action === 'reload')\n return { label: 'Reloaded the page' }\n return url ? { label: `Went to ${shortUrl(url)}`, title: url } : { label: 'Navigated' }\n }\n case 'browser_snapshot':\n return { label: 'Read the page' }\n case 'browser_screenshot':\n return { label: 'Took a screenshot' }\n case 'browser_click':\n return { label: head.startsWith('Clicked') ? head : `Clicked ${tool.target ?? 'the page'}` }\n case 'browser_type':\n return { label: head.startsWith('Typed') ? head : 'Typed in the page' }\n case 'browser_press':\n return { label: head.startsWith('Pressed') ? head : `Pressed ${str(input, 'key') ?? 'a key'}` }\n case 'browser_scroll':\n return { label: 'Scrolled the page' }\n case 'browser_wait_for': {\n const what = str(input, 'text') ?? str(input, 'selector') ?? str(input, 'urlIncludes')\n return { label: what ? `Waited for “${what.length > 40 ? `${what.slice(0, 39)}…` : what}”` : 'Waited' }\n }\n case 'browser_evaluate': {\n const expression = str(input, 'expression') ?? ''\n return { label: 'Ran a script in the page', ...(expression ? { title: expression.slice(0, 600) } : {}) }\n }\n case 'browser_console':\n return { label: 'Read the console' }\n default:\n return null\n }\n}\n\n/**\n * The overview line for one tool call.\n *\n * @param tool - Tool call with its name, input, target, result, and edit payload.\n */\nexport function toolOverview(tool: ToolOverviewInput): ToolOverview {\n const input = tool.input\n if (tool.name.startsWith('browser_')) {\n const browser = browserOverview(tool)\n if (browser)\n return browser\n }\n switch (tool.name) {\n case 'shell':\n case 'bash': {\n const command = str(input, 'command') ?? tool.target ?? ''\n // The model's description says what the call does (\"Run the GUI\n // typecheck\"); the command is behind it (title, and the opened input).\n const description = descriptionLabel(input)\n if (description)\n return { label: description, title: command.slice(0, 600) }\n const { gist, more } = commandGist(command)\n return { label: `Ran ${gist}`, ...(more > 0 ? { hint: `+${more}` } : {}), title: command.slice(0, 600) }\n }\n case 'read_file': {\n const batch = str(input, 'path') ? [] : readFileInputPaths(input)\n if (batch.length > 1)\n return { label: `Read ${splitPath(batch[0]).name} +${batch.length - 1}`, title: batch.join('\\n') }\n const path = str(input, 'path') ?? batch[0] ?? tool.target ?? ''\n const { name, dir } = splitPath(path)\n return { label: `Read ${name || 'a file'}`, ...(dir ? { hint: dir } : {}), title: path }\n }\n case 'edit':\n case 'multi_edit':\n case 'write_file': {\n const path = str(input, 'path') ?? tool.edit?.path ?? tool.target ?? ''\n const { name, dir } = splitPath(path)\n const counts = editCounts(tool.edit)\n const verb = tool.name === 'write_file' ? 'Wrote' : 'Edited'\n return {\n label: `${verb} ${name || 'a file'}`,\n ...(dir ? { hint: dir } : {}),\n ...(counts && (counts.added > 0 || counts.removed > 0) ? counts : {}),\n title: path,\n }\n }\n case 'grep': {\n const pattern = str(input, 'pattern') ?? tool.target ?? ''\n const where = str(input, 'path')\n return {\n label: pattern ? `Searched for “${pattern.length > 48 ? `${pattern.slice(0, 47)}…` : pattern}”` : 'Searched',\n ...(where ? { hint: where } : {}),\n title: pattern,\n }\n }\n case 'glob': {\n const pattern = str(input, 'pattern') ?? tool.target ?? ''\n return { label: pattern ? `Found files ${pattern}` : 'Found files', title: pattern }\n }\n case 'spawn': {\n // The worker is named by what it was asked to do; the full task sits behind it.\n const task = str(input, 'task') ?? tool.target ?? ''\n const first = task.split('\\n').find(line => line.trim()) ?? ''\n return { label: 'Agent', ...(first ? { hint: first.length > 80 ? `${first.slice(0, 79)}…` : first } : {}), ...(task ? { title: task.slice(0, 600) } : {}) }\n }\n case 'present_plan': {\n const title = str(input, 'title')\n return { label: 'Presented a plan', ...(title ? { hint: title, title } : {}) }\n }\n case 'ask_user': {\n const n = Array.isArray(input?.questions) ? input.questions.length : 0\n return { label: n > 0 ? `Asked ${n} question${n === 1 ? '' : 's'}` : 'Asked a question' }\n }\n case 'todowrite': {\n const todos = Array.isArray(input?.todos) ? (input.todos as { status?: unknown }[]) : []\n const done = todos.filter(t => t.status === 'completed').length\n return { label: 'Updated todos', ...(todos.length > 0 ? { hint: `${done} of ${todos.length} done` } : {}) }\n }\n case 'list_files': {\n const path = str(input, 'path') ?? tool.target ?? '.'\n return { label: `Listed ${path}`, title: path }\n }\n default: {\n const target = tool.target\n const short = target && target.length > 60 ? `${target.slice(0, 59)}…` : target\n return { label: short ? `${tool.displayName} ${short}` : tool.displayName, ...(target ? { title: target } : {}) }\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Many calls → one summary\n// ---------------------------------------------------------------------------\n\n/**\n * Verb phrase per canonical tool name for a batch summary. Unknown tools\n * derive one from their display name, so MCP and host tools read cleanly.\n */\nconst BATCH_VERB_PHRASE: Record<string, string> = {\n shell: 'ran a command',\n read_file: 'read a file',\n grep: 'searched',\n glob: 'searched for files',\n list_files: 'listed files',\n edit: 'edited a file',\n multi_edit: 'edited a file',\n write_file: 'created a file',\n spawn: 'spawned a subagent',\n tool_search: 'searched for tools',\n skills_use: 'activated a skill',\n skills_read: 'read a skill',\n skills_run_script: 'ran a skill script',\n ask_user: 'asked a question',\n present_plan: 'presented a plan',\n browser_open: 'opened the browser',\n browser_navigate: 'navigated',\n browser_snapshot: 'read the page',\n browser_screenshot: 'took a screenshot',\n browser_click: 'clicked',\n browser_type: 'typed',\n browser_press: 'pressed a key',\n browser_scroll: 'scrolled',\n browser_wait_for: 'waited',\n browser_evaluate: 'ran a script in the page',\n browser_console: 'read the console',\n terminal_list: 'listed terminals',\n terminal_read: 'read a terminal',\n terminal_write: 'typed in a terminal',\n}\n\n/**\n * Returns the lowercase verb phrase for a tool in a batch summary, such as `read a file`.\n *\n * @param name - Tool name.\n * @param displayName - Name shown to the user, used for tools without a known phrase.\n */\nexport function toolPhrase(name: string, displayName: string): string {\n return BATCH_VERB_PHRASE[name] ?? `used ${displayName.toLowerCase()}`\n}\n\n/**\n * Cap on phrases shown in a summary: a 40-call exchange reads \"Ran a\n * command, searched, read a file, edited a file +23\", where +N counts the\n * calls the shown phrases do not cover.\n */\nconst MAX_SUMMARY_PHRASES = 4\n\n/**\n * \"Ran a command, read a file +2\" for a run of calls. Adjacent identical\n * phrases merge, so three reads in a row say \"read a file\" once.\n * `overflow: false` leaves the +N off, for a header that counts its calls\n * another way.\n *\n * @param tools - Tool calls in run order.\n * @param options - Set `overflow` to `false` to leave the `+N` count off. Defaults to showing it.\n */\nexport function summarizeTools(tools: ReadonlyArray<{ name: string, displayName: string }>, options: { overflow?: boolean } = {}): string {\n const phrases: Array<{ phrase: string, calls: number }> = []\n for (const t of tools) {\n const phrase = toolPhrase(t.name, t.displayName)\n const last = phrases[phrases.length - 1]\n if (last && last.phrase === phrase)\n last.calls += 1\n else\n phrases.push({ phrase, calls: 1 })\n }\n if (phrases.length === 0)\n return 'Ran tools'\n const shown = phrases.slice(0, MAX_SUMMARY_PHRASES)\n const shownCalls = shown.reduce((n, p) => n + p.calls, 0)\n const rest = tools.length - shownCalls\n const joined = shown.map(p => p.phrase).join(', ')\n const capped = rest > 0 && options.overflow !== false ? `${joined} +${rest}` : joined\n return capped.charAt(0).toUpperCase() + capped.slice(1)\n}\n\n/**\n * A message as a person skims it: its words, markdown syntax and code\n * blocks dropped, whitespace folded. For the compact stacks of earlier\n * messages.\n *\n * @param text - Message text, usually markdown.\n */\nexport function messagePreview(text: string): string {\n return text\n .replace(/```[\\s\\S]*?(?:```|$)/g, ' ')\n .replace(/`([^`]*)`/g, '$1')\n .replace(/!?\\[([^\\]]*)\\]\\([^)]*\\)/g, '$1')\n .replace(/^\\s{0,3}(?:#{1,6}\\s+|>\\s?|[-*+]\\s+|\\d+[.)]\\s+)/gm, '')\n .replace(/(\\*\\*|__|\\*|_|~~)(\\S(?:.*?\\S)?)\\1/g, '$2')\n .replace(/\\s+/g, ' ')\n .trim()\n}\n","/**\n * Compact density's fold, one set of rules for both transcripts: what folds\n * into an exchange's one row (`foldsInCompactShape`), the steps the opened\n * fold lists and the counts its header reads (`planFold`), and the header's\n * words (`foldSummary`). The TUI maps its stream events onto these\n * (`src/tui/transcript/partition.ts`), the desktop app its rows\n * (`ui/src/chat/headless/transcript/fold.ts`, `fold-actions.ts`); each only\n * draws the steps in its own way.\n */\nimport type { StreamEvent } from './types'\nimport { summarizeTools } from './fold-actions'\nimport { describeSpawnEnd, previewLine, spawnStartParts } from './format'\nimport { spawnLaneResolver } from './spawn-tree'\n\n/** What decides whether an item folds: its kind and owner, and two facts only its surface knows. */\nexport interface FoldShape {\n /** The item's kind (`thinking`, `tool`, `info`, …). */\n kind: string\n /** Set when the item is a notice: an `info` notice stays out of the fold. */\n notice?: unknown\n /** The worker session that produced it; absent on the main session. */\n childId?: string\n /** Worker nesting depth; `0` or absent on the main session. */\n depth?: number\n /** The user's own `!` run: they ran it to see it. */\n userBash?: boolean\n /** The transcript's \"N earlier events\" marker: its top, not part of an exchange. */\n earlierMarker?: boolean\n}\n\n/**\n * Compact density: does this item fold into its exchange's one row?\n * Thinking, tool traffic, worker lifecycle, a `/` command's details and\n * everything a worker produced fold; the prompt, the assistant's prose,\n * errors, notices, the user's own `!` runs and session events stay.\n *\n * @param shape - The item's kind, owner and notice.\n */\nexport function foldsInCompactShape(shape: FoldShape): boolean {\n // Everything a worker session produced belongs to the parent's work.\n if ((shape.depth ?? 0) > 0 || shape.childId)\n return true\n switch (shape.kind) {\n case 'thinking':\n case 'thinking-batch':\n case 'spawn-start':\n case 'spawn-end':\n case 'spawn-queued':\n case 'command-detail':\n return true\n case 'tool':\n case 'tool-result':\n case 'tool-batch':\n return !shape.userBash\n case 'info':\n return shape.notice === undefined && !shape.earlierMarker\n default:\n return false\n }\n}\n\n/** A step's progress: `waiting` is a `spawn` call every worker slot is taken for. */\nexport type FoldStepState = 'waiting' | 'running' | 'ok' | 'err'\n\n/** One folded item, as the planner reads it. `item` is the surface's own object, handed back in the steps. */\nexport type FoldUnit<T> = {\n item: T\n childId?: string\n depth?: number\n /** Lifecycle metadata of a worker marker (its call, task, parent worker, structured end). */\n spawn?: StreamEvent['spawn']\n} & (\n | { kind: 'thought', live?: boolean, ms?: number }\n | {\n kind: 'call'\n name: string\n displayName: string\n callId?: string\n /** The call that made this one (a codemode script's `tools.*`). */\n parentId?: string\n state: FoldStepState\n waitingFor?: { active: number, max: number }\n /** A `spawn` call's task, to pair it with a worker whose marker names no call. */\n task?: string\n ms?: number\n }\n | { kind: 'result', callId: string, failed: boolean }\n | { kind: 'spawn-start' | 'spawn-end', text: string }\n | { kind: 'note' }\n | { kind: 'other' }\n)\n\n/** One line of an opened fold: a tool call, consecutive thoughts, a worker, or a command's note. */\nexport interface FoldStep<T> {\n /** What the line shows: a tool call, consecutive thoughts, a worker, or a command's note. */\n kind: 'tool' | 'thought' | 'worker' | 'note'\n /** Its progress; a worker's is its own end, not its call's result. */\n state: FoldStepState\n /** How many steps came before it when it started: a stable index for ids. */\n at: number\n /** Tool: the call and its results. Thought: its thinking items. Worker: every item of its lane. Note: the note. */\n items: T[]\n /** A tool step's call, or the `spawn` call that started a worker. */\n call?: T\n /** A tool step's call id. */\n callId?: string\n /** The call that made this one (a codemode script's `tools.*`). */\n parentId?: string\n /** A `waiting` spawn call: the worker slots taken and the limit. */\n waitingFor?: { active: number, max: number }\n /** A thought still streaming. */\n live?: boolean\n /** A worker's lane (its `childId`, or the worker that started it). */\n lane?: string\n /** A worker no call started: the task its marker carries. */\n task?: string\n}\n\n/** What the header reads. Worker-owned calls and thoughts count under the worker, not here. */\nexport interface FoldStats {\n /** The exchange's own calls (a script's nested calls ride their script's). */\n tools: number\n /** The exchange's own thinking items. */\n thoughts: number\n /** Distinct workers; one a worker started counts under its spawner. */\n workers: number\n /** Own calls that failed. */\n failed: number\n /** Own calls (nested ones included) with no result yet. */\n pending: number\n /** Known time of the own calls and thoughts; absent when nothing carries timing. */\n durationMs?: number\n}\n\n/** {@link planFold}'s result. */\nexport interface FoldPlan<T> {\n /** The opened fold's lines, in order. */\n steps: FoldStep<T>[]\n /** The counts the header reads. */\n stats: FoldStats\n /** The exchange's own top-level calls, in order, for {@link foldSummary}. */\n calls: Array<{ name: string, displayName: string }>\n}\n\nfunction isWorkerOwned(unit: { childId?: string, depth?: number }): boolean {\n return unit.childId !== undefined || (unit.depth ?? 0) > 0\n}\n\n/**\n * A `/` command's details line: its label, capitalised, or \"Details\".\n *\n * @param label - The command's notice label, if any.\n */\nexport function noteLabel(label: string | undefined): string {\n return label ? label.charAt(0).toUpperCase() + label.slice(1) : 'Details'\n}\n\n/**\n * A thought's line: \"Thinking\" while it streams, \"Thought\" once settled.\n *\n * @param live - Whether the thought is still streaming.\n */\nexport function thoughtLabel(live: boolean): string {\n return live ? 'Thinking' : 'Thought'\n}\n\n/**\n * The steps of one exchange in order, and its counts. Consecutive thoughts\n * are one step; each worker is one step holding its lane's items, merged\n * with the `spawn` call that started it (the call's line opens onto the\n * worker's progress). A worker's state is its own structured end: failed\n * only when it errored (core `describeSpawnEnd`), stopped reads done.\n *\n * @param units - The exchange's folded items, oldest first.\n */\nexport function planFold<T>(units: readonly FoldUnit<T>[]): FoldPlan<T> {\n const steps: FoldStep<T>[] = []\n const stats: FoldStats = { tools: 0, thoughts: 0, workers: 0, failed: 0, pending: 0 }\n const plan: FoldPlan<T> = { steps, stats, calls: [] }\n const calls = new Map<string, FoldStep<T>>()\n // An own call's outcome is its own, even once its step became the worker it started.\n const own = new Map<FoldStep<T>, FoldStepState>()\n const workers = new Map<string, FoldStep<T>>()\n const spawnCalls: Array<{ step: FoldStep<T>, task?: string }> = []\n const open = new Set<string>()\n const laneOf = spawnLaneResolver(units)\n let ms = 0\n let timed = false\n const time = (unitMs: number | undefined) => {\n if (unitMs === undefined)\n return\n ms += unitMs\n timed = true\n }\n let thought: FoldStep<T> | null = null\n\n for (const unit of units) {\n if (isWorkerOwned(unit)) {\n thought = null\n const lane = unit.childId !== undefined ? laneOf(unit.childId) : ''\n let worker = workers.get(lane)\n if (!worker) {\n worker = claimSpawnCall(spawnCalls, unit) ?? newWorker(steps, unit, lane)\n worker.kind = 'worker'\n worker.state = 'running'\n worker.lane = lane\n worker.items = []\n delete worker.waitingFor\n workers.set(lane, worker)\n }\n worker.items.push(unit.item)\n // The worker's own end only: a nested worker's ending rides along.\n if (unit.kind === 'spawn-end' && unit.childId === lane)\n worker.state = describeSpawnEnd({ text: unit.text, spawn: unit.spawn }).failed ? 'err' : 'ok'\n continue\n }\n if (unit.kind === 'thought') {\n if (!thought) {\n thought = { kind: 'thought', state: 'ok', at: steps.length, items: [] }\n steps.push(thought)\n }\n thought.items.push(unit.item)\n if (unit.live) {\n thought.live = true\n thought.state = 'running'\n }\n stats.thoughts += 1\n time(unit.ms)\n continue\n }\n thought = null\n if (unit.kind === 'call') {\n const step: FoldStep<T> = { kind: 'tool', state: unit.state, at: steps.length, items: [unit.item], call: unit.item }\n if (unit.callId !== undefined)\n step.callId = unit.callId\n if (unit.parentId !== undefined)\n step.parentId = unit.parentId\n if (unit.waitingFor)\n step.waitingFor = unit.waitingFor\n steps.push(step)\n if (unit.callId !== undefined) {\n calls.set(unit.callId, step)\n if (unit.state === 'running' || unit.state === 'waiting')\n open.add(unit.callId)\n }\n if (unit.name === 'spawn')\n spawnCalls.push({ step, ...(unit.task !== undefined ? { task: unit.task } : {}) })\n if (unit.parentId === undefined) {\n own.set(step, unit.state)\n plan.calls.push({ name: unit.name, displayName: unit.displayName })\n time(unit.ms)\n }\n continue\n }\n if (unit.kind === 'result') {\n open.delete(unit.callId)\n const step = calls.get(unit.callId)\n if (step && own.has(step))\n own.set(step, unit.failed ? 'err' : 'ok')\n // A worker's step ends with the worker, not with its call's result.\n if (step && step.kind === 'tool') {\n step.items.push(unit.item)\n step.state = unit.failed ? 'err' : 'ok'\n }\n continue\n }\n if (unit.kind === 'note')\n steps.push({ kind: 'note', state: 'ok', at: steps.length, items: [unit.item] })\n }\n\n for (const state of own.values()) {\n stats.tools += 1\n if (state === 'err')\n stats.failed += 1\n }\n const lanes = new Set<string>()\n for (const unit of units) {\n if (unit.childId !== undefined)\n lanes.add(laneOf(unit.childId))\n }\n stats.workers = lanes.size\n stats.pending = open.size\n if (timed)\n stats.durationMs = ms\n return plan\n}\n\n/**\n * The `spawn` call a worker's first item belongs to, among the calls no\n * worker claimed yet. The start marker names its call; markers recorded\n * before that pair by task text, never with a call that ran no worker.\n */\nfunction claimSpawnCall<T>(spawnCalls: Array<{ step: FoldStep<T>, task?: string }>, unit: FoldUnit<T>): FoldStep<T> | undefined {\n const open = spawnCalls.filter(({ step }) => step.kind === 'tool')\n const callId = unit.kind === 'spawn-start' ? unit.spawn?.callId : undefined\n if (callId)\n return open.find(({ step }) => step.callId === callId)?.step\n const candidates = open.filter(({ step }) => step.state !== 'err')\n const preview = unit.kind === 'spawn-start' ? spawnStartParts({ text: unit.text, spawn: unit.spawn }).task : undefined\n const byTask = preview ? candidates.find(({ task }) => previewLine(task ?? '', 80) === preview) : undefined\n return (byTask ?? candidates[0])?.step\n}\n\nfunction newWorker<T>(steps: FoldStep<T>[], unit: FoldUnit<T>, lane: string): FoldStep<T> {\n const task = unit.spawn?.task ?? (unit.kind === 'spawn-start' || unit.kind === 'spawn-end' ? unit.text : undefined)\n const step: FoldStep<T> = { kind: 'worker', state: 'running', at: steps.length, items: [], lane, ...(task ? { task } : {}) }\n steps.push(step)\n return step\n}\n\n/**\n * A settled fold's header: its own calls in the shared words (`Read a file,\n * ran a command +2`), with the workers after them when no `spawn` call\n * already says so (`, 1 worker`: a script started it). Exchanges without\n * calls say what they did: `Delegated to a worker`, `Thought`, `Worked`.\n *\n * @param plan - The fold's plan.\n * @param options - Header options.\n * @param options.overflow - `false` leaves the `+N` off (a surface that shows the counts beside it).\n */\nexport function foldSummary(plan: Pick<FoldPlan<unknown>, 'stats' | 'calls'>, options: { overflow?: boolean } = {}): string {\n const { stats, calls } = plan\n const workers = stats.workers > 0 && !calls.some(c => c.name === 'spawn') ? `${stats.workers} worker${stats.workers === 1 ? '' : 's'}` : ''\n if (calls.length > 0)\n return [summarizeTools(calls, options), workers].filter(Boolean).join(', ')\n if (stats.workers > 0)\n return stats.workers === 1 ? 'Delegated to a worker' : `Delegated to ${stats.workers} workers`\n return stats.thoughts > 0 ? 'Thought' : 'Worked'\n}\n","/**\n * Intensity levels of an activity heatmap (a panel's `heatmap` item, the\n * usage block): quartiles of the values above 0. A linear scale would\n * flatline every normal day next to one 500M-token outlier.\n */\n\n/** 0 = no activity … 4 = the top quartile of active days. */\nexport type HeatmapLevel = 0 | 1 | 2 | 3 | 4\n\n/** The three quartile bounds a value is placed against. */\nexport interface HeatmapThresholds {\n /** Upper bound of level 1 (the first quartile). */\n q1: number\n /** Upper bound of level 2 (the median). */\n q2: number\n /** Upper bound of level 3 (the third quartile). */\n q3: number\n}\n\n/**\n * The quartile bounds of the values above 0.\n *\n * @param values - Every day's value (zeros are ignored).\n */\nexport function heatmapThresholds(values: Iterable<number>): HeatmapThresholds {\n const nonZero = [...values].filter(v => v > 0).sort((a, b) => a - b)\n // `ceil(q·n)-1` keeps the maximum ABOVE q3 so level 4 is reachable\n // (a floor-based index puts the max at q3 and caps everything at 3).\n const quartile = (q: number): number => nonZero[Math.max(0, Math.ceil(q * nonZero.length) - 1)] ?? 0\n return { q1: quartile(0.25), q2: quartile(0.5), q3: quartile(0.75) }\n}\n\n/**\n * A value's level against {@link heatmapThresholds}.\n *\n * @param value - The day's value.\n * @param t - The bounds.\n * @param active - The day had activity even at a value of 0 (a message without tokens).\n */\nexport function heatmapLevel(value: number, t: HeatmapThresholds, active = false): HeatmapLevel {\n if (value <= 0)\n return active ? 1 : 0\n return value <= t.q1 ? 1 : value <= t.q2 ? 2 : value <= t.q3 ? 3 : 4\n}\n\n/**\n * Local `YYYY-MM-DD` of a date. Matches SQLite's `date(…, 'localtime')`.\n *\n * @param d - The date.\n */\nfunction localDay(d: Date): string {\n return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`\n}\n\n/**\n * The `count` days ending at `end` (inclusive), oldest first, as local `YYYY-MM-DD`.\n *\n * @param count - How many days.\n * @param end - The last day (local `YYYY-MM-DD`); default today.\n */\nexport function daysEndingAt(count: number, end?: string): string[] {\n const [y, m, d] = (end ?? localDay(new Date())).split('-').map(Number)\n const last = new Date(y!, m! - 1, d!)\n const out: string[] = []\n for (let i = count - 1; i >= 0; i--)\n out.push(localDay(new Date(last.getFullYear(), last.getMonth(), last.getDate() - i)))\n return out\n}\n","/**\n * Renderer-agnostic visible-row model for the Settings → Instructions tab.\n *\n * Simpler than the MCP / extension row models next door: a segment's expanded\n * TEXT is rendered inside its own row box rather than as sibling rows, so the\n * cursor walks one slot per segment no matter how long the text is. Expanding a\n * 1500-line AGENTS.md must not turn ↓ into 1500 keypresses.\n *\n * Pure (no OpenTUI / React) so the filtering + preview clamping is\n * unit-testable.\n */\n\nimport type { ContextSegment } from './context-segments'\n\n/**\n * Upper bound on preview lines rendered for one expanded segment. Same idea as\n * the Logs tab's `LOGS_RENDER_CAP`: the scrollbox can hold arbitrary height, but pasting a\n * runaway 64KB instruction file into the layout pass is a waste of a frame.\n * File-backed segments have `$EDITOR` as the escape hatch for the remainder.\n */\nexport const INSTRUCTION_PREVIEW_LINE_CAP = 400\n\n/** One selectable row: a context segment, plus its resolved open state. */\nexport interface VisibleInstructionRow {\n /** Context segment shown in the row. */\n segment: ContextSegment\n /** Whether the row is open. */\n expanded: boolean\n}\n\n/** Options for {@link buildVisibleInstructionRows}. */\nexport interface BuildVisibleInstructionRowsOptions {\n /** Segments to list, in display order. */\n segments: readonly ContextSegment[]\n /** Segment ids the user has expanded. */\n expanded: ReadonlySet<string>\n /** True when a search query is active. */\n queryActive: boolean\n /** Whether a segment matches the query. Ignored when `queryActive` is false. */\n matchSegment: (segment: ContextSegment) => boolean\n}\n\n/**\n * Filter segments by the active query and resolve each one's expanded state.\n *\n * Deliberately does NOT auto-expand matches the way the Extensions tab does:\n * the search corpus includes each segment's full text, so a query typically\n * matches deep inside a long document — auto-expanding every hit would dump\n * thousands of lines into the viewport on a keystroke. The user expands the row\n * they care about.\n *\n * @param opts - Segments, expanded ids, and the active search state.\n */\nexport function buildVisibleInstructionRows(\n opts: BuildVisibleInstructionRowsOptions,\n): VisibleInstructionRow[] {\n const { segments, expanded, queryActive, matchSegment } = opts\n const out: VisibleInstructionRow[] = []\n for (const segment of segments) {\n if (queryActive && !matchSegment(segment))\n continue\n out.push({ segment, expanded: expanded.has(segment.id) })\n }\n return out\n}\n\n/**\n * Split a segment's text into renderable preview lines, clamped to\n * {@link INSTRUCTION_PREVIEW_LINE_CAP}.\n *\n * `hidden` is how many lines were dropped off the tail, so the view can render\n * an honest \"+N more lines\" marker instead of silently truncating. Tabs are\n * expanded to two spaces because the terminal text renderable doesn't\n * interpret `\\t`, and `\\r` is stripped so CRLF files don't leave artefacts at\n * every line end.\n *\n * @param text - Segment text to preview.\n */\nexport function instructionPreviewLines(text: string): { lines: string[], hidden: number } {\n const all = text.replace(/\\r\\n?/g, '\\n').replace(/\\t/g, ' ').split('\\n')\n // Trailing blank lines carry no information in a preview and would render as\n // dead space under the last line of a file that ends with a newline.\n while (all.length > 0 && all[all.length - 1]!.trim() === '')\n all.pop()\n if (all.length <= INSTRUCTION_PREVIEW_LINE_CAP)\n return { lines: all, hidden: 0 }\n return {\n lines: all.slice(0, INSTRUCTION_PREVIEW_LINE_CAP),\n hidden: all.length - INSTRUCTION_PREVIEW_LINE_CAP,\n }\n}\n\n/**\n * Short badge for a segment's origin — the \"where does this come from\" column.\n * `'file'` is intentionally the only one that reads like a location, since it's\n * the only origin the user can act on.\n *\n * @param segment - Segment whose `origin` is labeled.\n */\nexport function instructionOriginBadge(segment: ContextSegment): string {\n switch (segment.origin) {\n case 'file':\n return 'file'\n case 'generated':\n return 'generated'\n case 'mcp':\n return 'mcp server'\n case 'built-in':\n return 'built-in'\n }\n}\n","/**\n * What clients show about machines (`docs/MACHINES.md` § Client UI), shared\n * by the TUI and the GUI renderer (node-free, re-exported by\n * `zidane/chat/pure`): the \"waiting for <machine>…\" state of a session, a\n * machine's folders as a folder-picker listing, environment kinds grouped\n * by machine, and the words for a link's state.\n */\nimport type { MachineLinkState } from './machine-protocol'\nimport { parseMachineKind } from './machine-protocol'\n\n/** The `label` of the notices a host emits about a session's machine. */\nexport const MACHINE_NOTICE_LABEL = 'machine'\n\nconst WAITING_RE = /^waiting for (\\S+?)…/\nconst BACK_RE = /^\\S+ is back\\./\nconst GAVE_UP_RE = /^\\S+ stayed offline for /\n\n/**\n * The machine a session's run is paused on, from its notices (`waiting for\n * laptop…` until `laptop is back.` or `laptop stayed offline … run stopped`),\n * `null` when none. `online`: machines known to be back since (a\n * `machine:status` the window saw), which clear the wait at once.\n *\n * @param events - A session's events, oldest first.\n * @param online - Machine names known to be back online.\n */\nexport function machineWaiting(events: readonly { text?: string, notice?: { label?: string } }[], online: ReadonlySet<string> = new Set()): string | null {\n for (let i = events.length - 1; i >= 0; i--) {\n const event = events[i]!\n if (event.notice?.label !== MACHINE_NOTICE_LABEL || typeof event.text !== 'string')\n continue\n if (BACK_RE.test(event.text) || GAVE_UP_RE.test(event.text))\n return null\n const waiting = WAITING_RE.exec(event.text)?.[1]\n if (waiting)\n return online.has(waiting) ? null : waiting\n }\n return null\n}\n\n/** A folder listing a folder picker renders (the shape of `fs.listDirs`). */\nexport interface MachineDirListing {\n /** Folders the picker may start from. */\n roots: string[]\n /** The folder being listed. */\n path: string\n /** Parent folder, or `null` when `path` is a root. */\n parent: string | null\n /** Folders under `path`. `isGitRepo` is always `false` here. */\n entries: { path: string, name: string, isGitRepo: boolean }[]\n}\n\nfunction dirname(path: string): string {\n const trimmed = path.replace(/\\/+$/, '')\n const at = trimmed.lastIndexOf('/')\n return at <= 0 ? '/' : trimmed.slice(0, at)\n}\n\nfunction basename(path: string): string {\n const trimmed = path.replace(/\\/+$/, '')\n return trimmed.slice(trimmed.lastIndexOf('/') + 1) || trimmed\n}\n\n/**\n * `machines.listDirs` as a folder listing: the parent stops at the root the folder is in.\n *\n * @param result - Directory names, the listed path and the allowed roots from `machines.listDirs`.\n */\nexport function machineDirListing(result: { path: string, dirs: string[], roots: string[] }): MachineDirListing {\n const { path } = result\n return {\n roots: result.roots,\n path,\n parent: result.roots.includes(path) ? null : dirname(path),\n entries: result.dirs.map(dir => ({ path: dir, name: basename(dir), isGitRepo: false })),\n }\n}\n\n/**\n * Environment kinds in picker order: this host's own first, then each\n * machine's together (`local@` before `worktree@`), machines by name.\n *\n * @param descriptors - Environment kind descriptors.\n */\nexport function orderByMachine<T extends { kind: string, machine?: { name: string } }>(descriptors: readonly T[]): T[] {\n const rank = (d: T): [number, string, number] => {\n const parsed = parseMachineKind(d.kind)\n return parsed ? [1, parsed.name, parsed.base === 'local' ? 0 : 1] : [0, '', 0]\n }\n return descriptors\n .map((d, i) => ({ d, i, r: rank(d) }))\n .sort((a, b) => a.r[0] - b.r[0] || a.r[1].localeCompare(b.r[1]) || a.r[2] - b.r[2] || a.i - b.i)\n .map(entry => entry.d)\n}\n\n/**\n * Why a machine kind can't be picked now (its machine is offline), else `undefined`.\n *\n * @param descriptor - Environment kind descriptor with its machine and the machine's status.\n */\nexport function machineBlockedReason(descriptor: { machine?: { name: string, status: 'online' | 'offline' } }): string | undefined {\n return descriptor.machine?.status === 'offline' ? `${descriptor.machine.name} is offline` : undefined\n}\n\n/**\n * The isolation a kind gives, named without its machine (the picker names the\n * place apart): `In the folder` for local kinds, `New worktree` for worktree\n * kinds, else the kind's own label.\n *\n * @param descriptor - Environment kind descriptor: its kind and label.\n */\nexport function isolationLabel(descriptor: { kind: string, label: string }): string {\n const base = parseMachineKind(descriptor.kind)?.base ?? descriptor.kind\n if (base === 'local')\n return 'In the folder'\n if (base === 'worktree')\n return 'New worktree'\n return descriptor.label\n}\n\n/**\n * The machine names of the saved servers a local host uses as machines\n * (`machines.links.status` `uses`): pickers list those servers once, as\n * servers, not again as `local@<server>`.\n *\n * @param links - The local host's links, or nothing when it can't say.\n * @param links.uses - The saved servers it uses as machines.\n */\nexport function lentServerMachines(links: { uses: readonly { machineName?: string }[] } | null | undefined): Set<string> {\n return new Set((links?.uses ?? []).flatMap(use => (use.machineName ? [use.machineName] : [])))\n}\n\n/**\n * A session's environment as its header shows it: `local@laptop`, `worktree@laptop ⎇ feat`, `⎇ feat`, or the kind.\n *\n * @param environment - The session environment: its kind and optional branch.\n */\nexport function environmentLabel(environment: { kind: string, branch?: string }): string {\n if (parseMachineKind(environment.kind))\n return environment.branch ? `${environment.kind} ⎇ ${environment.branch}` : environment.kind\n return environment.branch ? `⎇ ${environment.branch}` : environment.kind\n}\n\n/** Display text for each {@link MachineLinkState}. */\nexport const MACHINE_LINK_STATE_TEXT: Record<MachineLinkState, string> = {\n 'connecting': 'connecting…',\n 'connected': 'connected',\n 'reconnecting': 'reconnecting…',\n 'offline': 'offline',\n 'auth-refused': 'refused',\n 'identity': 'another server answers there',\n 'version-mismatch': 'another protocol version (upgrade one side)',\n 'refused': 'refused',\n}\n\n/**\n * \"seen 5 min ago\" for a machine's `lastSeen`.\n *\n * @param lastSeen - Epoch milliseconds the machine was last seen, or `undefined` if never.\n * @param now - Epoch milliseconds to measure from.\n */\nexport function lastSeenText(lastSeen: number | undefined, now: number): string {\n if (lastSeen === undefined)\n return 'never seen'\n const minutes = Math.max(0, Math.round((now - lastSeen) / 60_000))\n if (minutes < 1)\n return 'seen just now'\n if (minutes < 60)\n return `seen ${minutes} min ago`\n const hours = Math.round(minutes / 60)\n return hours < 48 ? `seen ${hours} h ago` : `seen ${Math.round(hours / 24)} d ago`\n}\n\nconst MONTHS = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']\n\n/**\n * \"14:05\", local time, 24-hour.\n *\n * @param at - Epoch milliseconds.\n */\nexport function clockText(at: number): string {\n const date = new Date(at)\n return `${String(date.getHours()).padStart(2, '0')}:${String(date.getMinutes()).padStart(2, '0')}`\n}\n\n/**\n * \"14:05\" when `at` falls on `now`'s day, \"Oct 12\" in the same year, else \"Oct 12, 2025\".\n *\n * @param at - Epoch milliseconds to show.\n * @param now - Epoch milliseconds of today.\n */\nexport function clockOrDateText(at: number, now: number): string {\n const date = new Date(at)\n const today = new Date(now)\n if (date.toDateString() === today.toDateString())\n return clockText(at)\n const day = `${MONTHS[date.getMonth()]} ${date.getDate()}`\n return date.getFullYear() === today.getFullYear() ? day : `${day}, ${date.getFullYear()}`\n}\n\n/**\n * \"offline since 14:05\" (a date when not today) for an offline machine's `lastSeen`; \"offline\" when never seen.\n *\n * @param lastSeen - Epoch milliseconds the machine was last seen.\n * @param now - Epoch milliseconds of today.\n */\nexport function offlineSinceText(lastSeen: number | undefined, now: number): string {\n return lastSeen === undefined ? 'offline' : `offline since ${clockOrDateText(lastSeen, now)}`\n}\n\n/**\n * Whether a machine runs another zidane version than its main server. `false` when either is unknown.\n *\n * @param version - The machine's version.\n * @param serverVersion - The main server's version.\n */\nexport function machineVersionDiffers(version: string | undefined, serverVersion: string | undefined): boolean {\n return !!version && !!serverVersion && version.replace(/^v/, '') !== serverVersion.replace(/^v/, '')\n}\n\n/**\n * The command a machine runs to join a main server with a join string (`formatJoinString`).\n *\n * @param join - `<server url>#<join code>`.\n */\nexport function machineSetupCommand(join: string): string {\n return `zidane machine setup --join ${join}`\n}\n","/**\n * Add-MCP form model — values, validation, and the two tokenizers it depends\n * on. Renderer-agnostic and node-free.\n *\n * Lives in `chat/` because BOTH clients render this form (the TUI's\n * `settings-form-dialog`, the kit's `McpAddForm`). Validation is the one place\n * a divergence between two copies would matter, because it decides which MCP\n * configs each surface accepts. One implementation means the same `mcps.json`\n * entry is accepted or rejected identically everywhere.\n */\nimport type { McpOAuthClientConfig, McpServerConfig } from '../types'\n\n/** Where a written MCP entry lands. */\nexport type InstallScopeChoice = 'user' | 'project'\n\n/** Transport an MCP server is reached over. */\nexport type McpTransport = 'stdio' | 'streamable-http' | 'sse'\n\n/** Every {@link McpTransport} in the order a form lists them. */\nexport const MCP_TRANSPORTS: readonly McpTransport[] = ['stdio', 'streamable-http', 'sse']\n\n/** Raw field values of the add-MCP-server form. */\nexport interface McpFormValues {\n /** Server name. Letters, digits, dots, hyphens and underscores. */\n name: string\n /** Transport the server uses. */\n transport: McpTransport\n /** stdio: full command line (first token = command, rest = args). */\n commandLine: string\n /** http/sse: server URL. */\n url: string\n /** One `KEY=VALUE` per line — stdio only. Values may contain spaces. */\n env: string\n /** One `Name: value` (or `Name=value`) per line — http/sse only. */\n headers: string\n /** Whether to write the entry to the user or the project config. */\n scope: InstallScopeChoice\n /**\n * Advanced OAuth (http/sse only): a pre-registered client for auth\n * servers without dynamic client registration. Optional so forms that\n * don't render the section keep compiling.\n */\n oauthClientId?: string\n /** Secret of the pre-registered client, when it has one. */\n oauthClientSecret?: string\n /** Raw field text; validated to an unprivileged port. */\n oauthCallbackPort?: string\n /** Space- or comma-separated OAuth scopes to request. */\n oauthScope?: string\n}\n\n/** A validated form: the config entry to write and where to write it. */\nexport interface McpFormResult {\n /** Normalized server config. */\n entry: McpServerConfig\n /** Where the entry should be written. */\n scope: InstallScopeChoice\n /**\n * Client secret from the Advanced OAuth section. Deliberately NOT in\n * `entry`: hosts keep it in the MCP credential store, out of `mcps.json`.\n */\n clientSecret?: string\n}\n\n/**\n * Validate + normalize the raw field values into a config entry.\n * Returns the first problem in row order so the dialog can surface it.\n *\n * @param values - Raw form field values.\n */\nexport function validateMcpForm(values: McpFormValues): { ok: true, result: McpFormResult } | { ok: false, error: string } {\n const name = values.name.trim()\n if (name.length === 0)\n return { ok: false, error: 'name is required' }\n if (!/^[\\w.-]+$/.test(name))\n return { ok: false, error: 'name must be alphanumerics, dots, hyphens, underscores' }\n\n if (values.transport === 'stdio') {\n const tokens = splitCommandLine(values.commandLine)\n if (tokens.length === 0)\n return { ok: false, error: 'command is required for stdio servers' }\n const env = parseKeyValueLines(values.env, { label: 'env', separators: ['='] })\n if (!env.ok)\n return { ok: false, error: env.error }\n const entry: McpServerConfig = {\n name,\n transport: 'stdio',\n command: tokens[0] as string,\n ...(tokens.length > 1 ? { args: tokens.slice(1) } : {}),\n ...(Object.keys(env.pairs).length > 0 ? { env: env.pairs } : {}),\n }\n return { ok: true, result: { entry, scope: values.scope } }\n }\n\n const url = values.url.trim()\n if (url.length === 0)\n return { ok: false, error: 'url is required for http/sse servers' }\n if (!/^https?:\\/\\//.test(url))\n return { ok: false, error: 'url must start with http:// or https://' }\n const headers = parseKeyValueLines(values.headers, { label: 'headers', separators: [':', '='] })\n if (!headers.ok)\n return { ok: false, error: headers.error }\n const oauth = validateOAuthFields(values)\n if (!oauth.ok)\n return { ok: false, error: oauth.error }\n return {\n ok: true,\n result: {\n entry: {\n name,\n transport: values.transport,\n url,\n ...(Object.keys(headers.pairs).length > 0 ? { headers: headers.pairs } : {}),\n ...(oauth.config ? { auth: 'oauth' as const, oauth: oauth.config } : {}),\n },\n scope: values.scope,\n ...(oauth.clientSecret ? { clientSecret: oauth.clientSecret } : {}),\n },\n }\n}\n\nfunction validateOAuthFields(values: McpFormValues):\n | { ok: true, config?: McpOAuthClientConfig, clientSecret?: string }\n | { ok: false, error: string } {\n const clientId = values.oauthClientId?.trim() ?? ''\n const clientSecret = values.oauthClientSecret?.trim() ?? ''\n const portText = values.oauthCallbackPort?.trim() ?? ''\n const scope = values.oauthScope?.trim().split(/[\\s,]+/).filter(Boolean).join(' ') ?? ''\n if (clientId === '') {\n if (clientSecret !== '' || portText !== '' || scope !== '')\n return { ok: false, error: 'client ID is required for advanced OAuth' }\n return { ok: true }\n }\n let callbackPort: number | undefined\n if (portText !== '') {\n callbackPort = /^\\d+$/.test(portText) ? Number(portText) : Number.NaN\n if (!Number.isInteger(callbackPort) || callbackPort < 1024 || callbackPort > 65535)\n return { ok: false, error: 'callback port must be a number from 1024 to 65535' }\n }\n return {\n ok: true,\n config: {\n clientId,\n ...(callbackPort !== undefined ? { callbackPort } : {}),\n ...(scope !== '' ? { scope } : {}),\n },\n ...(clientSecret !== '' ? { clientSecret } : {}),\n }\n}\n\n/**\n * Split a command line into tokens, honoring single/double quotes so\n * `npx -y my-server --root \"/path with spaces\"` round-trips. No escape\n * processing beyond quote grouping — this is a form field, not a shell.\n *\n * @param line - Command line text.\n */\nexport function splitCommandLine(line: string): string[] {\n const out: string[] = []\n const re = /\"([^\"]*)\"|'([^']*)'|(\\S+)/g\n for (let m = re.exec(line); m !== null; m = re.exec(line))\n out.push((m[1] ?? m[2] ?? m[3]) as string)\n return out\n}\n\n/**\n * Parse one key/value pair PER LINE. Line-based (not whitespace-split)\n * because values legitimately contain spaces — `Authorization: Bearer\n * abc123` is the canonical headers case, and env values like\n * `GREETING=hello world` are equally valid. The first separator found\n * (the separator that appears first in the line) splits.\n * The rest of the line is the value, trimmed. Blank lines skipped.\n *\n * @param raw - Field text, one pair per line.\n * @param opts - A `label` for error messages and the separators to split on.\n */\nexport function parseKeyValueLines(\n raw: string,\n opts: { label: string, separators: readonly string[] },\n): { ok: true, pairs: Record<string, string> } | { ok: false, error: string } {\n const pairs: Record<string, string> = {}\n for (const line of raw.split('\\n')) {\n const trimmed = line.trim()\n if (trimmed.length === 0)\n continue\n let splitAt = -1\n for (const sep of opts.separators) {\n const idx = trimmed.indexOf(sep)\n if (idx > 0 && (splitAt === -1 || idx < splitAt))\n splitAt = idx\n }\n if (splitAt <= 0) {\n const forms = opts.separators.map(s => `KEY${s}VALUE`).join(' or ')\n return { ok: false, error: `${opts.label} entries must be ${forms}, one per line (got \"${trimmed}\")` }\n }\n const key = trimmed.slice(0, splitAt).trim()\n const value = trimmed.slice(splitAt + 1).trim()\n if (key.length === 0)\n return { ok: false, error: `${opts.label} entry has an empty key (\"${trimmed}\")` }\n pairs[key] = value\n }\n return { ok: true, pairs }\n}\n","/**\n * Presentation constants for structured transcript notices (`StreamEvent.notice`).\n *\n * Shared by the TUI transcript and the GUI timeline so a `warn` notice reads\n * with the same glyph on both, and so the label vocabulary (`model fallback`,\n * `output limit`, `repeat guard`, …) is recognisably the same row across\n * surfaces. Pure; re-exported from `zidane/chat/pure`.\n */\nimport type { StreamEvent } from './types'\n\n/** Severity of a transcript notice. */\nexport type NoticeSeverity = NonNullable<StreamEvent['notice']>['severity']\n\n/** Leading glyph per severity. `info` is deliberately quiet: a plain `i`, single-width in every terminal. */\nexport const NOTICE_GLYPH: Readonly<Record<NoticeSeverity, string>> = {\n info: 'i',\n warn: '!',\n error: '✗',\n}\n","/**\n * Side-panel catalog and open state. Renderer-agnostic: the TUI rail and\n * the GUI side panel both read the same catalog (built-ins first, then\n * extension panels in load order) and drive the same state machine.\n *\n * The one behavioural rule worth spelling out: `openProactive`. Agent- or\n * extension-driven opens (a PR was created, a badge flipped) must never\n * yank the panel away from a tab the user chose. So a proactive request\n * is honoured only while the user has not picked a tab since the previous\n * proactive open; the moment they click a tab, proactive opens are ignored\n * until the next user pick resets the gate.\n */\nimport type { ExtensionPanelEntry, PanelIcon } from '../extensions/panels'\nimport { panelOnSurface, panelShowsIn } from '../extensions/panels'\n\n/** Id of the inbox panel. */\nexport const INBOX_PANEL_ID = 'inbox'\n/** Id of the todos panel. */\nexport const TODOS_PANEL_ID = 'todos'\n/** Id of the queue panel: messages sent during a run, waiting for it to end (the desktop app only). */\nexport const QUEUE_PANEL_ID = 'queue'\n/** Id of the artifacts panel. */\nexport const ARTIFACTS_PANEL_ID = 'artifacts'\n/** Id of the diffs panel. */\nexport const DIFFS_PANEL_ID = 'diffs'\n/** Id of the files panel. */\nexport const FILES_PANEL_ID = 'files'\n/** Id of the browser panel. */\nexport const BROWSER_PANEL_ID = 'browser'\n/** Id of the terminal panel. */\nexport const TERMINAL_PANEL_ID = 'terminal'\n/** A `/side` chat about the session (the desktop app only). */\nexport const SIDE_PANEL_ID = 'side'\n\n/** Built-in tabs the hosts render with their own components. */\nexport type BuiltinPanelId\n = | typeof INBOX_PANEL_ID\n | typeof TODOS_PANEL_ID\n | typeof QUEUE_PANEL_ID\n | typeof ARTIFACTS_PANEL_ID\n | typeof DIFFS_PANEL_ID\n | typeof FILES_PANEL_ID\n | typeof BROWSER_PANEL_ID\n | typeof TERMINAL_PANEL_ID\n | typeof SIDE_PANEL_ID\n\n/** A tab for a panel the host renders itself. */\nexport interface BuiltinPanelTab {\n /** Built-in panel id. */\n id: BuiltinPanelId\n /** Tab label. */\n label: string\n /** Icon for each renderer. */\n icon: PanelIcon\n /** Discriminant that marks a built-in tab. */\n builtin: true\n}\n\n/** A tab for a panel an extension registered. */\nexport interface ExtensionPanelTab {\n /** Panel id. */\n id: string\n /** Tab label. */\n label: string\n /** Icon for each renderer, when the extension set one. */\n icon?: PanelIcon\n /** Discriminant that marks an extension tab. */\n builtin: false\n /** Name of the extension that registered the panel. */\n owner: string\n}\n\n/** A built-in or extension panel tab. */\nexport type PanelTab = BuiltinPanelTab | ExtensionPanelTab\n\n/** Built-in panel tabs in display order. */\nexport const BUILTIN_PANEL_TABS: readonly BuiltinPanelTab[] = [\n // Agent-facing surfaces first: what is waiting on the user, then the plan.\n { id: INBOX_PANEL_ID, label: 'Inbox', icon: { gui: 'i-ph-tray', tui: '✉' }, builtin: true },\n { id: TODOS_PANEL_ID, label: 'Todos', icon: { gui: 'i-ph-list-checks', tui: '▣' }, builtin: true },\n { id: QUEUE_PANEL_ID, label: 'Queue', icon: { gui: 'i-ph-queue', tui: '❯' }, builtin: true },\n { id: ARTIFACTS_PANEL_ID, label: 'Artifacts', icon: { gui: 'i-ph-cube', tui: '◆' }, builtin: true },\n { id: DIFFS_PANEL_ID, label: 'Diffs', icon: { gui: 'i-ph-git-diff', tui: '±' }, builtin: true },\n { id: FILES_PANEL_ID, label: 'Files', icon: { gui: 'i-ph-tree-structure', tui: '▤' }, builtin: true },\n { id: BROWSER_PANEL_ID, label: 'Browser', icon: { gui: 'i-ph-globe-simple', tui: '◎' }, builtin: true },\n { id: TERMINAL_PANEL_ID, label: 'Terminal', icon: { gui: 'i-ph-terminal-window', tui: '❯' }, builtin: true },\n { id: SIDE_PANEL_ID, label: 'Side', icon: { gui: 'i-ph-chats-circle', tui: '◇' }, builtin: true },\n]\n\n/** Options for {@link buildPanelCatalog}. */\nexport interface PanelCatalogOptions {\n /** Hide the artifacts tab (the user's `artifacts: false` setting). */\n showArtifacts?: boolean\n /** Built-in ids the host does not render (the TUI keeps only the artifacts tab). */\n omitBuiltins?: readonly BuiltinPanelId[]\n /**\n * No session is bound (only a folder is open): keep just the extension\n * panels that opted in (`scope: 'project' | 'both'`). Bound (the\n * default), `scope: 'project'` panels are dropped. Built-ins are not\n * filtered here; hosts drop session-only ones via `omitBuiltins`.\n */\n unbound?: boolean\n}\n\n/**\n * Built-ins first, then extension panels in registry (load) order.\n *\n * @param extensionPanels - Panels registered by extensions.\n * @param options - Catalog filters.\n */\nexport function buildPanelCatalog(\n extensionPanels: readonly Pick<ExtensionPanelEntry, 'id' | 'label' | 'icon' | 'owner' | 'scope' | 'surfaces'>[],\n options: PanelCatalogOptions = {},\n): PanelTab[] {\n const tabs: PanelTab[] = []\n for (const tab of BUILTIN_PANEL_TABS) {\n if (tab.id === ARTIFACTS_PANEL_ID && options.showArtifacts === false)\n continue\n if (options.omitBuiltins?.includes(tab.id))\n continue\n tabs.push(tab)\n }\n const seen = new Set(tabs.map(t => t.id))\n for (const p of extensionPanels) {\n if (seen.has(p.id))\n continue\n // A block for the project home only is not a side tab.\n if (!panelOnSurface(p, 'side'))\n continue\n if (!panelShowsIn(p.scope, options.unbound ? 'project' : 'session'))\n continue\n seen.add(p.id)\n tabs.push({ id: p.id, label: p.label, builtin: false, owner: p.owner, ...(p.icon ? { icon: p.icon } : {}) })\n }\n return tabs\n}\n\n// ---------------------------------------------------------------------------\n// State\n// ---------------------------------------------------------------------------\n\n/** Open state of the side panel. */\nexport interface PanelState {\n /** Whether the side panel is open. */\n open: boolean\n /** Active tab id; `null` when nothing has been chosen yet (hosts pick the first tab). */\n activeId: string | null\n /** Monotonic counter bumped on every user pick; gates proactive opens. */\n userPicks: number\n /** `userPicks` value at the last proactive open that was honoured. */\n proactiveAt: number\n}\n\n/** Panel state at startup: closed, no active tab, no user picks. */\nexport const INITIAL_PANEL_STATE: PanelState = { open: false, activeId: null, userPicks: 0, proactiveAt: 0 }\n\n/**\n * Add a tab to the host's pinned strip (idempotent, keeps order).\n *\n * @param pinned - The host's pinned tab ids in order.\n * @param id - Id of the tab to pin.\n */\nexport function pinTab(pinned: readonly string[], id: string): readonly string[] {\n return pinned.includes(id) ? pinned : [...pinned, id]\n}\n\n/**\n * Apply a user reorder of the VISIBLE strip to the pinned list. `pinned` can\n * hold ids the catalog no longer shows (an extension disabled for this cwd);\n * they keep their slots, and the visible ids fill the remaining slots in the\n * new order, so re-enabling the extension brings its tab back where it was.\n * Ids in `visible` that aren't pinned are ignored. Returns `pinned` itself\n * when nothing moved.\n *\n * @param pinned - The host's pinned tab ids in order.\n * @param visible - Ids of the tabs currently shown, in their new order.\n */\nexport function reorderTabs(pinned: readonly string[], visible: readonly string[]): readonly string[] {\n const shown = new Set(visible.filter(id => pinned.includes(id)))\n const order = visible.filter(id => shown.has(id))\n let next = 0\n const out = pinned.map(id => (shown.has(id) ? order[next++]! : id))\n return out.every((id, i) => id === pinned[i]) ? pinned : out\n}\n\n/**\n * Move one visible tab `delta` slots within the visible strip (keyboard\n * reorder), clamped at the ends. Hidden pinned ids keep their slots.\n *\n * @param pinned - The host's pinned tab ids in order.\n * @param visible - Ids of the tabs currently shown, in display order.\n * @param id - Id of the tab to move.\n * @param delta - Positions to move by. Negative moves earlier. Clamped to the visible range.\n */\nexport function moveTab(\n pinned: readonly string[],\n visible: readonly string[],\n id: string,\n delta: number,\n): readonly string[] {\n const from = visible.indexOf(id)\n if (from < 0)\n return pinned\n const to = Math.max(0, Math.min(visible.length - 1, from + delta))\n if (to === from)\n return pinned\n const order = [...visible]\n order.splice(from, 1)\n order.splice(to, 0, id)\n return reorderTabs(pinned, order)\n}\n\n/**\n * The user clicked a tab (or a keybinding cycled to it). Always honoured, always opens.\n *\n * @param state - The current panel state.\n * @param id - Id of the chosen tab.\n */\nexport function pickTab(state: PanelState, id: string): PanelState {\n return { ...state, open: true, activeId: id, userPicks: state.userPicks + 1 }\n}\n\n/**\n * Opens the panel when closed and closes it when open.\n *\n * @param state - The current panel state.\n */\nexport function togglePanel(state: PanelState): PanelState {\n return { ...state, open: !state.open }\n}\n\n/**\n * Closes the panel and keeps the active tab.\n *\n * @param state - The current panel state.\n */\nexport function closePanel(state: PanelState): PanelState {\n return { ...state, open: false }\n}\n\n/**\n * Agent / extension asked to show a tab. Honoured only until the user has\n * picked a tab themselves (a badge that flipped must never steal the tab);\n * otherwise the request is dropped and the state returned unchanged.\n *\n * @param state - The current panel state.\n * @param id - Id of the tab to show.\n */\nexport function openProactive(state: PanelState, id: string): PanelState {\n if (state.userPicks !== state.proactiveAt)\n return state\n return { ...state, open: true, activeId: id }\n}\n\n/**\n * The agent is blocked on the user (a plan to approve, a question to\n * answer): show the tab regardless of earlier picks. Costs at most a tab\n * switch, and nothing in that tab decides implicitly. Not a user pick, so\n * it does not lock out later proactive opens.\n *\n * @param state - The current panel state.\n * @param id - Id of the tab that needs attention.\n */\nexport function openForAttention(state: PanelState, id: string): PanelState {\n if (state.open && state.activeId === id)\n return state\n return { ...state, open: true, activeId: id }\n}\n\n/**\n * Resolve the tab to render: the active one when it still exists, else the\n * first tab, else `null` (empty catalog). Keeps state stable when an\n * extension is disabled and its tab vanishes.\n *\n * @param state - The current panel state.\n * @param catalog - Tabs in display order.\n */\nexport function resolveActiveTab(state: PanelState, catalog: readonly PanelTab[]): PanelTab | null {\n if (catalog.length === 0)\n return null\n return catalog.find(t => t.id === state.activeId) ?? catalog[0]\n}\n\n/**\n * Cycle to the next / previous tab (wraps). Counts as a user pick.\n *\n * @param state - The current panel state.\n * @param catalog - Tabs in display order.\n * @param direction - `1` for the next tab, `-1` for the previous.\n */\nexport function cycleTab(state: PanelState, catalog: readonly PanelTab[], direction: 1 | -1): PanelState {\n if (catalog.length === 0)\n return state\n const current = resolveActiveTab(state, catalog)\n const idx = current ? catalog.findIndex(t => t.id === current.id) : 0\n const next = catalog[(idx + direction + catalog.length) % catalog.length]\n return pickTab(state, next.id)\n}\n","/**\n * Display form of a stored prompt. Prompts sent before the composer kept one\n * newline per line break carry a markdown paragraph gap after every line\n * (`a\\n\\nb`, and `a\\n\\n\\n\\nb` for one blank line): shown as plain text, that\n * spread a short message over a whole screen. Runs of three or more newlines\n * collapse to one blank line; chip spans are remapped onto the result.\n */\nimport type { PromptSegmentRef } from './prompt-segments'\n\n/**\n * Collapses runs of three or more newlines to one blank line, trims trailing whitespace and remaps the chip spans.\n *\n * @param text - Stored prompt text.\n * @param refs - Chip spans over `text`.\n */\nexport function tidyPromptText(\n text: string,\n refs: readonly PromptSegmentRef[],\n): { text: string, refs: PromptSegmentRef[] } {\n const trimmed = text.trimEnd()\n if (!/\\n{3,}/.test(trimmed))\n return { text: trimmed, refs: refs.filter(r => r.end <= trimmed.length) }\n // map[i] = index in the output of input index i (and map[len] = output length).\n const map: number[] = Array.from({ length: trimmed.length + 1 })\n let out = ''\n for (let i = 0; i < trimmed.length;) {\n const run = /^\\n{3,}/.exec(trimmed.slice(i, i + 64))\n if (run && trimmed[i] === '\\n') {\n let end = i\n while (trimmed[end] === '\\n') end++\n for (let k = i; k < end; k++) map[k] = out.length + Math.min(k - i, 2)\n out += '\\n\\n'\n i = end\n continue\n }\n map[i] = out.length\n out += trimmed[i]\n i++\n }\n map[trimmed.length] = out.length\n const remapped = refs\n .filter(r => r.end <= trimmed.length)\n .map(r => ({ ...r, start: map[r.start]!, end: map[r.end]! }))\n return { text: out, refs: remapped }\n}\n","/**\n * A run that ended early (failed, or stopped by the user) reads as ONE quiet\n * line in a transcript, never as a `[✗ …]` / `[⏹ …]` reply. The loop persists\n * those markers in the assistant turn for the model; this pass splits them off\n * the reply, merges them with the run-ending error (live from `run:end`, on\n * replay from the run record) and lets one item speak for the stop.\n *\n * The one classifier both surfaces use: the TUI over stream events\n * (`src/tui/run-stops.ts` tags them), the GUI over transcript rows\n * (`ui/src/chat/headless/transcript/run-failures.ts` mints rows with a\n * `failure`). Each supplies only how to copy and mark its items.\n */\nimport { mayHaveStreamFailure, splitStreamFailure } from './stream-failure'\n\n/** How a run ended early and how to pick it back up. */\nexport interface RunStop {\n /** `aborted` when the user stopped the run, `error` when it failed. */\n cause: 'error' | 'aborted'\n /** `continue` when the run had done work, `retry` (resend `prompt`) when not. */\n resume: 'continue' | 'retry'\n /** The prompt to resend, set only with `resume: 'retry'`. */\n prompt?: string\n}\n\n/** What the classifier reads off an item: stream events and the GUI's rows both carry it. */\nexport interface RunStopItem {\n /** The item's kind (`markdown`, `error`, `user-prompt`, `tool`, …). */\n kind: string\n /** Its text: a reply's markdown, an error's message, a prompt. */\n text?: string\n /** A reply still streaming: its marker, if any, is not final yet. */\n streaming?: boolean\n /** The worker session that produced it; absent on the main session. */\n childId?: string\n /** Worker nesting depth; `0` or absent on the main session. */\n depth?: number\n /** The tool an error belongs to: not the run's own error. */\n tool?: string\n /** The call an error belongs to: not the run's own error. */\n callId?: string\n /** Set when the item is a notice; `label` names its source (`run`, `repeat guard`, …). */\n notice?: { label?: string }\n}\n\n/** How one surface copies and marks its items. */\nexport interface RunStopAdapter<T extends RunStopItem> {\n /** The item already speaks for a stop (an earlier pass's output fed back in). */\n isMarked: (item: T) => boolean\n /** The reply with its marker split off. */\n withText: (reply: T, text: string) => T\n /** The stop line a marker becomes when no run error closes the exchange. */\n mint: (reply: T, text: string, stop: RunStop) => T\n /** The run's own error, now speaking for the stop with `text`. */\n mark: (error: T, text: string, stop: RunStop) => T\n}\n\nconst WORK_KINDS = new Set(['tool', 'tool-result', 'tool-batch', 'thinking', 'thinking-batch', 'user-bash', 'spawn-start', 'spawn-end', 'command-detail'])\n\n/** The run had done something: a tool call, a thought, a worker, a command's output, or a reply with words. */\nfunction isRunWork(item: RunStopItem): boolean {\n return WORK_KINDS.has(item.kind) || (item.kind === 'markdown' && (item.text ?? '').trim() !== '')\n}\n\n/** Belongs to the main session, not to a worker. */\nfunction isTopLevel(item: RunStopItem): boolean {\n return !item.childId && (item.depth ?? 0) === 0\n}\n\n/** Receipts and turn boundaries come after a run's end: the search for it looks past them. */\nfunction isSkippable(item: RunStopItem): boolean {\n return item.kind === 'run-summary' || item.kind === 'separator'\n}\n\n/**\n * Notices that end a run: older sessions persisted the run's error as a `run`\n * notice, and the repeat guard stops a run with one. Any other notice (a `/`\n * command's error, a failed auto-compaction) is not the run failing.\n */\nconst RUN_ENDING_NOTICES = new Set(['run', 'repeat guard'])\n\n/** A run's own error: not a tool's, not a `/` command's. */\nfunction isRunError(item: RunStopItem): boolean {\n return item.kind === 'error' && isTopLevel(item) && !item.tool && !item.callId\n && (!item.notice || RUN_ENDING_NOTICES.has(item.notice.label ?? ''))\n}\n\n/**\n * The run-stop pass for one surface. It returns its input itself when no run\n * stopped early, so memoised consumers stay put.\n *\n * It runs on every stream drain tick, where only the tail changes. Items are\n * immutable, so both caches key on identity: the failure scan reads each\n * reply once, and a segment whose items are unchanged hands back its previous\n * output (without that, a session with one old failed run minted fresh stop\n * items every tick, so they re-rendered on every streamed token).\n *\n * @param adapter - How the surface copies and marks its items.\n */\nexport function createRunStopMarker<T extends RunStopItem>(adapter: RunStopAdapter<T>): (items: readonly T[]) => readonly T[] {\n const failureScans = new WeakMap<T, boolean>()\n const segments = new WeakMap<T, { input: T[], output: T[] | null }>()\n\n const mayMarkStop = (item: T): boolean => {\n if (item.kind === 'error')\n return isTopLevel(item)\n if (item.kind !== 'markdown')\n return false\n let hit = failureScans.get(item)\n if (hit === undefined) {\n hit = mayHaveStreamFailure(item.text ?? '')\n failureScans.set(item, hit)\n }\n return hit\n }\n\n /** `markSegment` over `items[start, end)`, or `null` when it left the segment as is. */\n const markSegmentCached = (items: readonly T[], start: number, end: number): T[] | null => {\n const first = items[start]\n const cached = first ? segments.get(first) : undefined\n if (cached && cached.input.length === end - start) {\n let same = true\n for (let k = 1; k < cached.input.length && same; k++)\n same = cached.input[k] === items[start + k]\n if (same)\n return cached.output\n }\n const input = items.slice(start, end)\n const marked = markSegment(input, adapter)\n const output = marked === input ? null : marked\n if (first)\n segments.set(first, { input, output })\n return output\n }\n\n return (items) => {\n if (!items.some(mayMarkStop))\n return items\n const out: T[] = []\n let changed = false\n let start = 0\n // A segment is one exchange: a top-level prompt and everything up to the next one.\n for (let i = 0; i <= items.length; i++) {\n if (i < items.length && !(items[i]!.kind === 'user-prompt' && isTopLevel(items[i]!) && i > start))\n continue\n const next = markSegmentCached(items, start, i)\n if (next) {\n changed = true\n out.push(...next)\n }\n else {\n for (let k = start; k < i; k++)\n out.push(items[k]!)\n }\n start = i\n }\n return changed ? out : items\n }\n}\n\nfunction markSegment<T extends RunStopItem>(segment: T[], adapter: RunStopAdapter<T>): T[] {\n let marker: { index: number, message: string, aborted: boolean } | null = null\n const items = segment.map((item, index) => {\n if (item.kind !== 'markdown' || item.streaming || !isTopLevel(item))\n return item\n const split = splitStreamFailure(item.text ?? '')\n if (!split.failure)\n return item\n marker = { index, message: split.failure.message, aborted: split.failure.aborted }\n return adapter.withText(item, split.text)\n })\n\n // The run's own end: a run error closing the exchange (receipts and turn boundaries aside).\n let terminal = -1\n for (let i = items.length - 1; i >= 0; i--) {\n const item = items[i]!\n if (isSkippable(item))\n continue\n if (isRunError(item) && !adapter.isMarked(item))\n terminal = i\n break\n }\n const found = marker as { index: number, message: string, aborted: boolean } | null\n const prompt = items[0]?.kind === 'user-prompt' ? items[0] : null\n // Without a marker, only an error closing a prompted run is that run's end.\n if (!found && (terminal < 0 || !prompt))\n return segment\n\n const workEnd = terminal >= 0 ? terminal : found!.index + 1\n const didWork = items.slice(prompt ? 1 : 0, workEnd).some(isRunWork)\n // Live, a stop can arrive as the run's error alone (\"This operation was aborted\").\n const aborted = found ? found.aborted : /\\babort/i.test(items[terminal]!.text ?? '')\n const cause = aborted ? 'aborted' as const : 'error' as const\n const promptText = prompt?.text ?? ''\n const stop: RunStop = didWork || !prompt || promptText.trim() === ''\n ? { cause, resume: 'continue' }\n : { cause, resume: 'retry', prompt: promptText }\n\n const result: T[] = []\n items.forEach((item, index) => {\n if (index === found?.index) {\n // Nothing left of the reply: the stop line takes its place.\n if ((item.text ?? '').trim() !== '')\n result.push(item)\n if (terminal < 0)\n result.push(adapter.mint(item, aborted ? '' : found.message, stop))\n return\n }\n if (index === terminal) {\n // A stop the user asked for needs no reason. A failure reads the run's\n // typed error (the classifier's words, e.g. a rate limit's reset) over\n // the marker, which older sessions persisted with the raw provider body.\n result.push(adapter.mark(item, aborted ? '' : item.text || found?.message || '', stop))\n return\n }\n result.push(item)\n })\n return result\n}\n","/**\n * Output throughput for the live run readout (`41 tok/s`), from the turn's\n * `stream:progress` samples.\n *\n * `tokens / elapsed since the request` was wrong in two ways that produced\n * absurd rates: the count mid-stream is an estimate from the visible text,\n * then jumps to the provider's real figure right before the stream ends\n * (for Anthropic that includes hidden reasoning, often many times the\n * estimate), so the division reported that correction as throughput; and\n * the denominator included the time to first token, so early readings\n * swung. Here the rate is tokens GAINED per second over a short trailing\n * window of samples: a correction (the estimate→provider snap, or a count\n * that goes backwards) rebases the window instead of counting, readings\n * are smoothed, and anything no model can produce is dropped.\n */\n\n/** One `stream:progress` reading of a turn, as {@link stepStreamRate} takes it. */\nexport interface RateSample {\n /** Turn the sample belongs to. */\n turnId: string\n /** ms since the turn's request; only differences are used. */\n elapsedMs: number\n /** Output tokens counted so far in the turn. */\n outputTokens: number\n /** Whether `outputTokens` is an estimate rather than a provider-reported count. */\n estimated: boolean\n}\n\n/** Sliding-window state of the output rate of a streaming turn. */\nexport interface RateState {\n /** Turn being measured, or `null` before the first sample. */\n turnId: string | null\n /** Samples inside the window, oldest first; the first is the baseline. */\n samples: readonly { t: number, n: number }[]\n /** Whether the samples are estimates, or `null` before the first sample. */\n estimated: boolean | null\n /** Smoothed tokens/second, `null` until the window has enough span. */\n rate: number | null\n}\n\n/** Initial rate state, before any sample. */\nexport const EMPTY_RATE: RateState = { turnId: null, samples: [], estimated: null, rate: null }\n\n/** Trailing window the rate is measured over. */\nconst WINDOW_MS = 3000\n/** Minimum span before a reading counts: shorter spans are one or two ticks of noise. */\nconst MIN_SPAN_MS = 1200\n/** Faster than any served model today (the fastest wafer-scale ones run ~3k): a reading above is a glitch. */\nexport const MAX_PLAUSIBLE_RATE = 6000\n/** Weight of a new reading in the smoothed rate. */\nconst SMOOTHING = 0.35\n\n/**\n * Folds one output token reading into the rate state. Returns a new state, or\n * the same one for an out-of-order or duplicate sample.\n *\n * @param state - The current rate state.\n * @param sample - The newest output token reading.\n */\nexport function stepStreamRate(state: RateState, sample: RateSample): RateState {\n const point = { t: sample.elapsedMs, n: sample.outputTokens }\n if (state.turnId !== sample.turnId) {\n return { turnId: sample.turnId, samples: [point], estimated: sample.estimated, rate: null }\n }\n const last = state.samples[state.samples.length - 1]\n // A correction, not throughput: the provider's count replaced the estimate,\n // or the count went backwards. Rebase on this sample, keep the last rate.\n const corrected\n = (state.estimated === true && !sample.estimated) || (last !== undefined && point.n < last.n) || !last\n if (corrected) {\n return { ...state, samples: [point], estimated: sample.estimated }\n }\n if (point.t <= last.t)\n return state // out-of-order or duplicate tick\n\n // Keep the window, plus the newest sample older than it as the baseline.\n const kept = [...state.samples, point]\n let start = 0\n while (start < kept.length - 2 && kept[start + 1]!.t <= point.t - WINDOW_MS)\n start++\n const samples = kept.slice(start)\n\n const base = samples[0]!\n const span = point.t - base.t\n let rate = state.rate\n if (span >= MIN_SPAN_MS) {\n const reading = ((point.n - base.n) / span) * 1000\n if (reading >= 0 && reading <= MAX_PLAUSIBLE_RATE) {\n rate = rate === null ? reading : rate + SMOOTHING * (reading - rate)\n }\n }\n return { turnId: state.turnId, samples, estimated: sample.estimated, rate }\n}\n\n/**\n * Whole tokens per second for display, or `null` when there is no honest reading.\n *\n * @param state - The current rate state.\n */\nexport function streamRateValue(state: RateState): number | null {\n if (state.rate === null)\n return null\n const rounded = Math.round(state.rate)\n return rounded > 0 ? rounded : null\n}\n","/**\n * User-initiated todo-list edits — pure transforms over `TodoItem[]`.\n *\n * The todo list is normally MODEL-owned: `todowrite` passes the full array on\n * every call, so a checkpoint replaces whatever was there. These transforms let\n * the TUI's `ctrl+t` panel and the GUI todos tab edit the same list, with one consequence the UI must\n * surface rather than hide: **a user edit made during a live run is overwritten\n * by the agent's next checkpoint**. Nothing here can prevent that — it is the\n * tool's contract — so the modal warns while a run is in flight instead of\n * pretending the edit is durable.\n *\n * Kept pure and renderer-agnostic (no React, no node) so the reducers are\n * unit-testable and both the TUI and the GUI drive the same edits.\n */\n\nimport type { TodoItem, TodoStatus } from './todos'\n\n/**\n * Prefix for ids minted here, distinguishing user-authored rows from the\n * model's own ids in a session file. Purely diagnostic — nothing branches on\n * it — but it makes \"who added this\" answerable after the fact.\n */\nconst USER_TODO_ID_PREFIX = 'user-'\n\n/**\n * Mint an id that cannot collide with an existing row.\n *\n * Counter-based rather than random: a stable, readable id keeps session diffs\n * legible, and the collision check makes it safe against ids the model already\n * used (including previous `user-*` ones after a reload).\n *\n * @param items - The current todo list.\n */\nexport function nextTodoId(items: readonly TodoItem[]): string {\n const taken = new Set(items.map(i => i.id))\n for (let n = 1; ; n++) {\n const id = `${USER_TODO_ID_PREFIX}${n}`\n if (!taken.has(id))\n return id\n }\n}\n\n/**\n * Append a todo. Returns the list unchanged when `content` is blank — an empty\n * row is never what the user meant, and rejecting it here means every caller\n * (keyboard, click, GUI) gets the same guard.\n *\n * @param items - The current todo list.\n * @param content - Text of the new todo. Blank text adds nothing.\n */\nexport function addTodo(items: readonly TodoItem[], content: string): TodoItem[] {\n const trimmed = content.trim()\n if (!trimmed)\n return [...items]\n return [...items, { id: nextTodoId(items), content: trimmed, status: 'pending' }]\n}\n\n/**\n * Replace one todo's text. Blank content is rejected (see {@link addTodo}); an\n * unknown id is a no-op rather than an error, because the list can be replaced\n * by a `todowrite` between render and keypress.\n *\n * @param items - The current todo list.\n * @param id - Id of the todo to change.\n * @param content - New text. Blank text changes nothing.\n */\nexport function editTodo(items: readonly TodoItem[], id: string, content: string): TodoItem[] {\n const trimmed = content.trim()\n if (!trimmed)\n return [...items]\n return items.map(item => item.id === id ? { ...item, content: trimmed } : item)\n}\n\n/**\n * Drop one todo. Unknown id is a no-op, same rationale as {@link editTodo}.\n *\n * @param items - The current todo list.\n * @param id - Id of the todo to remove.\n */\nexport function removeTodo(items: readonly TodoItem[], id: string): TodoItem[] {\n return items.filter(item => item.id !== id)\n}\n\n/** Drop everything. Separate from `removeTodo` so the caller's intent is explicit at the call site. */\nexport function clearTodos(): TodoItem[] {\n return []\n}\n\n/**\n * Advance a todo's status one step: pending → in_progress → completed →\n * pending. `cancelled` also lands on `pending`, so a dropped item can be\n * revived without a dedicated key.\n *\n * Cycling INTO `in_progress` demotes any other in-progress row to `pending`:\n * the list's whole purpose is \"what is being worked on right now\", and two\n * live rows make that unanswerable — `todoProgressLabel`\n * reads the first one and would silently ignore the rest.\n *\n * @param items - The current todo list.\n * @param id - Id of the todo to advance. An unknown id changes nothing.\n */\nexport function cycleTodoStatus(items: readonly TodoItem[], id: string): TodoItem[] {\n const target = items.find(item => item.id === id)\n if (!target)\n return [...items]\n const next = nextStatus(target.status)\n return items.map((item) => {\n if (item.id === id)\n return { ...item, status: next }\n if (next === 'in_progress' && item.status === 'in_progress')\n return { ...item, status: 'pending' as TodoStatus }\n return item\n })\n}\n\nfunction nextStatus(status: TodoStatus): TodoStatus {\n switch (status) {\n case 'pending':\n return 'in_progress'\n case 'in_progress':\n return 'completed'\n case 'completed':\n case 'cancelled':\n default:\n return 'pending'\n }\n}\n\n/**\n * Steering text for a \"retry this todo\" request.\n *\n * Quotes the content so a model reading it can match the row verbatim against\n * its own list, and names the status because \"retry\" means different things\n * for a row it believes is `completed` versus one it abandoned as `cancelled`.\n * Shared by the TUI and GUI modals so both surfaces steer with byte-identical\n * text; pinned by a test rather than living inside a JSX callback.\n *\n * @param item - The todo to retry.\n */\nexport function buildTodoRetryMessage(item: TodoItem): string {\n return `Retry this todo (currently ${item.status}): \"${item.content}\"`\n}\n"],"mappings":"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"}
|
package/dist/types-DTMEhKJO.js
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
//#region src/contexts/types.ts
|
|
2
|
-
/**
|
|
3
|
-
* Effective {@link DetachedTasksCapability} of a context, with the
|
|
4
|
-
* backward-compatible inference for contexts that predate the field.
|
|
5
|
-
*
|
|
6
|
-
* @param context - Execution context to inspect.
|
|
7
|
-
*/
|
|
8
|
-
function resolveDetachedTasksCapability(context) {
|
|
9
|
-
return context.capabilities.detachedTasks ?? (context.execBackground ? "process-lifetime" : "none");
|
|
10
|
-
}
|
|
11
|
-
//#endregion
|
|
12
|
-
export { resolveDetachedTasksCapability as t };
|
|
13
|
-
|
|
14
|
-
//# sourceMappingURL=types-DTMEhKJO.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"types-DTMEhKJO.js","names":[],"sources":["../src/contexts/types.ts"],"sourcesContent":["/**\n * Execution context types.\n *\n * An execution context defines *where* and *how* an agent's tools run.\n * The agent loop and tools interact through this interface without knowing\n * whether they're running in-process, in a Docker container, or in a\n * remote sandbox.\n */\n\nimport type { Buffer } from 'node:buffer'\nimport type { IsolationPolicy } from './isolation'\n\n// ---------------------------------------------------------------------------\n// Capabilities\n// ---------------------------------------------------------------------------\n\n/**\n * Lifetime guarantee of background tasks started through\n * {@link ExecutionContext.execBackground}.\n *\n * - `'none'` — the context cannot detach tasks at all.\n * - `'process-lifetime'` — tasks live as long as the HOST process; a\n * crash/restart of the host orphans or kills them (`ProcessContext`).\n * - `'durable'` — tasks live on a remote runner and survive host process\n * death (remote execution contexts driven by durable runtimes).\n *\n * Durable-execution runtimes consult this to decide whether backgrounding\n * is safe to expose (`disableBackgroundTasks: 'non-durable'`, the default\n * in replay mode): a `'durable'` context keeps its tasks across worker\n * crashes, so there is no reason to strip the capability from the model.\n */\nexport type DetachedTasksCapability = 'none' | 'process-lifetime' | 'durable'\n\n/** Features an execution context supports. Consumers check these before relying on a feature. */\nexport interface ContextCapabilities {\n /** Can execute shell commands */\n shell: boolean\n /** Can read/write files in a workspace */\n filesystem: boolean\n /** Can enumerate glob matches through `ExecutionContext.listFiles(..., { glob: true })`. */\n glob?: boolean\n /** Can make outbound network requests */\n network: boolean\n /** Has GPU access */\n gpu: boolean\n /**\n * Can open a bidirectional byte stream to a long-lived process through\n * {@link ExecutionContext.execStream}. Absent / `false` = the context\n * only supports the buffered {@link ExecutionContext.exec} and (maybe)\n * the write-to-a-log-file {@link ExecutionContext.execBackground}.\n *\n * Consumers that NEED live stdin (stdio MCP servers routed into the\n * context) must check this before calling; the seam is optional so\n * contexts backed by a request/response-only API stay valid.\n */\n stream?: boolean\n /**\n * Shell commands run under an ENFORCED OS-level sandbox (macOS Seatbelt /\n * Linux bwrap) — see `SpawnConfig.isolation`. `false` when isolation was\n * not requested AND when it was requested but the backend is unavailable\n * (that context fails every command closed instead). Absent / `false` =\n * commands do not run sandboxed.\n */\n isolated?: boolean\n /**\n * Background-task lifetime guarantee. Optional for backward\n * compatibility — when absent, callers infer `'process-lifetime'`\n * if the context implements `execBackground`, `'none'` otherwise\n * (see {@link resolveDetachedTasksCapability}).\n */\n detachedTasks?: DetachedTasksCapability\n}\n\n/**\n * Effective {@link DetachedTasksCapability} of a context, with the\n * backward-compatible inference for contexts that predate the field.\n *\n * @param context - Execution context to inspect.\n */\nexport function resolveDetachedTasksCapability(context: ExecutionContext): DetachedTasksCapability {\n return context.capabilities.detachedTasks\n ?? (context.execBackground ? 'process-lifetime' : 'none')\n}\n\n// ---------------------------------------------------------------------------\n// Execution handle\n// ---------------------------------------------------------------------------\n\n/** Opaque handle to a running execution context instance */\nexport interface ExecutionHandle {\n /** Identifier of the spawned instance, unique within its context. */\n id: string\n /** Type of the context that created the handle. */\n type: ContextType\n /** Working directory within the context */\n cwd: string\n}\n\n// ---------------------------------------------------------------------------\n// Exec result\n// ---------------------------------------------------------------------------\n\n/** Result of a buffered command. */\nexport interface ExecResult {\n /** Captured standard output. */\n stdout: string\n /** Captured standard error. */\n stderr: string\n /** Process exit code. `0` means success. */\n exitCode: number\n}\n\n/** What a path is: a file (a symlink counts as one, never followed) or a folder. */\nexport type EntryKind = 'file' | 'dir'\n\n/**\n * The few file operations every entry action is built from\n * (`createEntryOps`, `zidane/chat`), paths resolved like the context's\n * other file methods. None of them overwrites: a target is checked missing\n * first, and the operations refuse one that appeared since.\n */\nexport interface EntryPort {\n /** What `path` is, `null` when nothing is there. Never follows a final symlink. */\n stat: (path: string) => Promise<EntryKind | null>\n /** The names in folder `path`. */\n list: (path: string) => Promise<string[]>\n /** Creates folder `path` and its missing parents. */\n mkdir: (path: string) => Promise<void>\n /** Writes a new file (its folder exists). */\n write: (path: string, bytes: Uint8Array) => Promise<void>\n /** Renames `from` to `to` (missing; its folder exists). */\n move: (from: string, to: string) => Promise<void>\n /** Copies `from` (a folder whole, symlinks as links) to `to` (missing; its folder exists). */\n copy: (from: string, to: string) => Promise<void>\n /** Removes `path` (a folder whole). */\n remove: (path: string) => Promise<void>\n /** Empty folders under folder `path` (`.git` and `node_modules` skipped), relative to it, at most `limit`. */\n emptyDirs: (path: string, limit: number) => Promise<string[]>\n}\n\n/** A listed file with optional metadata. */\nexport interface ListFileMetadata {\n /** Path of the file. */\n path: string\n /** Size in bytes. */\n size?: number\n /** Last modification time, in milliseconds since the epoch. */\n mtimeMs?: number\n}\n\n/** One listing entry: a plain path, or a {@link ListFileMetadata} object when metadata was requested. */\nexport type ListFilesEntry = string | ListFileMetadata\n\n/** Options for {@link ExecutionContext.listFiles}. */\nexport interface ListFilesOptions {\n /** Treat `path` as a glob match pattern instead of a literal directory path. */\n glob?: boolean\n /** Maximum number of entries to return. */\n limit?: number\n /** Return {@link ListFileMetadata} objects instead of plain paths. */\n metadata?: boolean\n /**\n * Skip git-ignored files when globbing. Default `true`. Contexts that can\n * resolve git's ignore rules (e.g. the local process context) honor it; the\n * rest treat it as a no-op. Set `false` to match every file, ignored or not.\n */\n gitignore?: boolean\n /** Abort the listing early — forwarded from the calling tool's `ctx.signal`. */\n signal?: AbortSignal\n}\n\n// ---------------------------------------------------------------------------\n// Spawn config\n// ---------------------------------------------------------------------------\n\n/** Configuration for {@link ExecutionContext.spawn}. Not every context honors every field. */\nexport interface SpawnConfig {\n /** Working directory (created if it doesn't exist) */\n cwd?: string\n /**\n * Optional workspace-containment root for the file methods (`readFile`,\n * `writeFile`, `listFiles`) of the process context.\n *\n * When set, a resolved path that escapes this root (via absolute path,\n * `..`, or a symlink pointing outside) is rejected before any I/O. Default\n * unset = no containment (back-compat; the agent can read/write anywhere\n * the host process can). Set this for untrusted workloads to confine file\n * tools to a directory. Shell commands are not covered — use a sandbox /\n * docker context for full isolation.\n */\n workspaceRoot?: string\n /** Environment variables */\n env?: Record<string, string>\n /**\n * Whether spawned shells inherit the parent `process.env` (process context).\n *\n * Default `true` (preserves existing behavior — children see the parent\n * environment including anything Bun auto-loaded from `.env`). Set `false`\n * for untrusted workloads so secrets in the parent environment aren't\n * readable by tool commands; only `env` / per-call env plus a minimal base\n * (`PATH`, `HOME`, `SHELL`, `LANG`, `LC_ALL`, `USER`, `TERM`, `TMPDIR`) are\n * passed through.\n */\n inheritEnv?: boolean\n /**\n * OS-level sandboxing of shell commands (process context only). When set,\n * every `exec` / `execStream` / `execBackground` runs `/bin/sh -c` under\n * macOS `sandbox-exec` or Linux `bwrap`: filesystem writes are limited to\n * `writableRoots`, credential directories are hidden, and network is\n * `allow`ed or `deny`ed as a whole. `writeFile` applies the same\n * `writableRoots` check in-process (reads are unrestricted — this is the\n * Claude Code / Codex boundary, not a full jail; use `workspaceRoot` for\n * read containment).\n *\n * Fails closed: when the backend is unavailable on the host, every command\n * returns exit 127 with the reason instead of running unsandboxed.\n *\n * Build the policy with `resolveWritableRoots` from `contexts/isolation`.\n */\n isolation?: IsolationPolicy\n /**\n * The session this context runs commands for (process context only): each\n * command it starts (`exec`, `execStream`, `execBackground`) is recorded in\n * the session-process registry (`listSessionProcesses`) while it runs.\n */\n sessionId?: string\n /** Docker image (only for 'docker' context) */\n image?: string\n /** Docker container name prefix (only for 'docker' context) */\n name?: string\n /** Host paths mounted into the context (only for 'docker' context today) */\n mounts?: ContextMount[]\n /** Resource limits */\n limits?: {\n /** Memory limit in MB */\n memory?: number\n /** CPU limit (e.g. '1.0' = 1 core) */\n cpu?: string\n /**\n * Timeout in seconds. The process and docker contexts use it as the\n * default for each `exec` call that passes no `timeout`. The e2b\n * context uses it as the sandbox lifetime.\n */\n timeout?: number\n }\n /** Sandbox provider config (only for 'sandbox' context) */\n sandbox?: {\n provider: string\n apiKey?: string\n /**\n * Attach to a pre-existing sandbox by id rather than creating one\n * (provider-specific; E2B maps it to `Sandbox.connect`). The provider\n * leaves a connected sandbox running on teardown.\n */\n sandboxId?: string\n [key: string]: unknown\n }\n\n /**\n * How long `destroy()` waits for a SIGTERM'd background task to settle\n * before escalating to SIGKILL and abandoning the wait (process context\n * only). Bounds `agent.destroy()` against tasks that trap SIGTERM or\n * whose stdio pipes are held open by escaped grandchildren.\n *\n * Default: `5000`.\n */\n destroyGraceMs?: number\n\n /**\n * Publish container ports on the host (docker context only).\n *\n * Each entry maps a container port to either an explicit host port or\n * (when `host` is omitted) a Docker-assigned random port. Retrieve the\n * actual host port at runtime via `getMappedPort(handle, containerPort)`\n * on the docker context.\n */\n ports?: Array<{ container: number, host?: number, proto?: 'tcp' | 'udp' }>\n\n /**\n * UID/GID the container should run as (docker context only).\n *\n * Accepts the same forms Docker's `--user` does: `uid`, `uid:gid`, or a\n * named user that exists in the image. Default is the image's default\n * user (typically root). Setting this to the host user's `uid:gid`\n * avoids the EACCES-on-cleanup problem when sharing a workspace via\n * a `shared` mount.\n */\n user?: string\n\n /**\n * User-defined Docker network to join (docker context only).\n *\n * Defaults to Docker's default bridge. Use a user network when you\n * need multiple sibling containers (e.g. agent + database + dev\n * server) to discover each other by name.\n */\n network?: string\n\n /**\n * Docker labels to attach to the container (docker context only).\n *\n * Useful for ownership tracking — callers can sweep abandoned\n * containers (e.g. from a crashed parent process) by filtering on\n * a label they own: `docker ps -aq --filter label=my-app=true`.\n */\n labels?: Record<string, string>\n\n /**\n * Container hardening options (docker context only).\n *\n * All fields are opt-in and OFF by default to preserve existing behavior\n * (containers run with the image's default user/capabilities). Enable them\n * for untrusted workloads. `dropAllCapabilities` and a non-root `user`\n * (see {@link SpawnConfig.user}) can break images that expect root or\n * specific capabilities, so they are not applied unless requested.\n */\n hardening?: ContextHardening\n}\n\n/**\n * Opt-in container hardening for the docker context. Every field defaults to\n * \"unset\" so an omitted `hardening` (or omitted field) leaves the container\n * unrestricted.\n */\nexport interface ContextHardening {\n /**\n * Drop all Linux capabilities (`CapDrop: ['ALL']`). Strong isolation, but\n * breaks images needing capabilities (e.g. binding low ports, `ping`).\n * Default: `false`.\n */\n dropAllCapabilities?: boolean\n /**\n * Set `no-new-privileges` so processes can't gain privileges via setuid\n * binaries. Low blast radius; safe for most workloads. Default: `false`.\n */\n noNewPrivileges?: boolean\n /**\n * Mount the container root filesystem read-only. Pair with writable mounts\n * for scratch space. Default: `false`.\n */\n readonlyRootfs?: boolean\n /**\n * Max number of processes (`PidsLimit`) — caps fork-bombs. Default: unset\n * (no limit). A few hundred is usually plenty for an agent sandbox.\n */\n pidsLimit?: number\n}\n\n/** A host directory bind-mounted into an execution context. */\nexport interface ContextMount {\n /** Absolute host path to mount. */\n source: string\n /** Absolute path inside the execution context. */\n target: string\n /** Mount read-only. Defaults to false for Docker's native bind behavior. */\n readonly?: boolean\n /**\n * Apply the SELinux shared label (`:z`) so the host user and the container\n * user can both read/write the mount (docker context only). No-op on\n * non-SELinux hosts. Combine with `SpawnConfig.user` to avoid root-owned\n * files leaking onto the host. Mutually exclusive with `readonly`.\n */\n shared?: boolean\n}\n\n// ---------------------------------------------------------------------------\n// Execution context interface\n// ---------------------------------------------------------------------------\n\n/** Kind of execution context: `process`, `docker` or `sandbox`. */\nexport type ContextType = 'process' | 'docker' | 'sandbox'\n\n/** An environment where an agent runs commands and reads and writes files: the host process, a Docker container or a remote sandbox. */\nexport interface ExecutionContext {\n /** Context type identifier */\n readonly type: ContextType\n\n /** What this context supports */\n readonly capabilities: ContextCapabilities\n\n /** Spawn a new execution environment */\n spawn: (config?: SpawnConfig) => Promise<ExecutionHandle>\n\n /**\n * Execute a shell command in the context.\n *\n * `signal` propagates abort all the way down to the underlying child\n * process — the implementation is expected to wire it into whatever\n * spawn primitive it uses so the OS receives a SIGTERM (or equivalent)\n * when the caller aborts. Without it, a cancelled tool returns its\n * cancellation marker to the model but the underlying process keeps\n * running in the background, orphaning compute / locks / IO. Pass\n * `ctx.signal` from a tool body to inherit the per-call + run-level\n * abort union; pass a freshly-built one for a host-driven kill.\n *\n * Implementations are free to ignore `signal` (the contract degrades\n * gracefully — the process simply won't be killed), but the process\n * context honors it.\n *\n * `timeout` is in SECONDS (default 30) — every\n * implementation converts internally (process ×1000 to ms, docker wraps\n * with coreutils `timeout`, sandbox SDKs take seconds/ms per their API).\n * Documented here because the unit is invisible at call sites and a\n * caller assuming milliseconds would set an instant-kill timeout.\n */\n exec: (handle: ExecutionHandle, command: string, options?: { cwd?: string, env?: Record<string, string>, timeout?: number, signal?: AbortSignal }) => Promise<ExecResult>\n\n /**\n * Start a process in the background. Settles as soon as `spawn` returns\n * — does NOT wait for the child to exit. Stdout + stderr stream\n * interleaved to the file at the returned `outputPath`. The caller\n * (typically the agent) reads incremental output via the regular\n * {@link ExecutionContext.readFile} seam.\n *\n * Optional — contexts without background support (some remote sandboxes)\n * just don't implement it. The shell tool surfaces a clean\n * \"background mode is not supported in this execution context\" error\n * when this is undefined.\n *\n * `onExit` is called once when the child terminates (natural, killed,\n * or error). The same instance that called `execBackground` is the\n * exclusive owner of the callback — it's not a multi-cast bus. Hosts\n * wire this to the agent's pending-notification queue so the model\n * gets a `<task-notification>` on its next turn.\n *\n * `onExit` is OPTIONAL: remote / durable contexts may have no legal\n * way to push a callback from a timer back into the host (a replay\n * journal, for instance, forbids out-of-band writes). Such contexts\n * record the exit in their registry; the agent loop reconciles\n * by polling {@link ExecutionContext.listBackground} at run\n * boundaries, where a host journal wrapper is legal (the\n * `background:reconcile` hook is the journalable seam).\n *\n * See `docs/RUN_IN_BACKGROUND.md` for the broader design contract\n * (file location, replay semantics, suppression rules).\n */\n execBackground?: (\n handle: ExecutionHandle,\n command: string,\n options: {\n cwd?: string\n env?: Record<string, string>\n /**\n * Absolute directory the context appends `<task-id>.log` to. The\n * agent owns this path because it carries session-shaped knowledge\n * (`<userDir>/tasks/<sessionId>/`) the context can't synthesize.\n * Must already exist OR be creatable by the context — the\n * implementation handles `mkdir -p` defensively.\n */\n outputDir: string\n /** Push-style exit callback. Optional — see the method doc. */\n onExit?: (info: TaskExitInfo) => void\n /**\n * Cap on bytes written to the output file. Beyond the cap the\n * process KEEPS RUNNING; further output is counted but dropped,\n * and a `<output-truncated bytes-dropped=\"N\"/>` marker is\n * appended when the task settles. Unset / non-positive = no cap.\n */\n maxOutputBytes?: number\n /**\n * Stall watchdog: when the task produces no output for this many\n * milliseconds, `onStall` fires ONCE (one-shot — re-arms only\n * after fresh output arrives). The process is NOT killed; the\n * consumer decides (typically by telling the model the task may\n * be stuck at an interactive prompt). Unset = no watchdog.\n */\n stallTimeoutMs?: number\n /** One-shot stall callback — see `stallTimeoutMs`. */\n onStall?: (info: TaskStallInfo) => void\n /**\n * Run the task in a terminal — see {@link BackgroundTerminalOptions}.\n * Contexts without terminal support ignore it and use pipes; check\n * {@link TaskHandle.terminal} to know which one happened.\n */\n terminal?: BackgroundTerminalOptions\n },\n ) => Promise<TaskHandle>\n\n /**\n * Open a LIVE bidirectional byte stream to a long-lived process in the\n * context. The third execution mode, alongside the buffered `exec`\n * (request/response) and `execBackground` (fire-and-forget into a log\n * file): neither of those can carry a protocol that interleaves reads\n * and writes over the child's lifetime.\n *\n * Motivating consumer: stdio MCP servers. An MCP server is an ordinary\n * process doing `fs.readFileSync` / `fs.writeFile` against whatever\n * filesystem it was spawned on. Spawned on the host (the default — see\n * `McpServerConfig.scope`) it sees the HOST filesystem while the agent's\n * own tools see the context's, so the two disagree about what a path\n * means. Routing the server through this seam puts both on the same\n * filesystem.\n *\n * Optional — a context backed by a request/response-only API can't\n * implement it. Advertise support via `capabilities.stream`; callers\n * check that (or `execStream !== undefined`) and degrade with a clear\n * error rather than silently falling back to a host spawn, which would\n * reintroduce exactly the split this seam exists to close.\n *\n * IMPLEMENTOR CONTRACT — the shape is deliberately the SUPERSET of what\n * the backing APIs can do, because they do not agree:\n *\n * - `stdout` / `stderr` are byte streams, never pre-decoded strings.\n * A provider SDK that hands back `string` has already destroyed any\n * multibyte codepoint split across a chunk boundary; the caller\n * needs the raw bytes to run its own streaming decoder.\n * - `stderr` is OPTIONAL because a PTY-backed context physically\n * cannot separate it — one terminal, one stream. Such contexts\n * redirect the child's stderr to a file; they may then surface it\n * here out-of-band (the Daytona context polls that file back), but\n * they are not obliged to, so consumers must tolerate its absence.\n * - A PTY-backed context MUST also neutralise terminal semantics\n * before the child's first byte (echo of everything written to\n * stdin, `\\n`→`\\r\\n` rewriting, and the ~4096-byte canonical-mode\n * line cap that arbitrary protocol frames exceed). In practice:\n * launch through `stty raw -echo; exec <cmd> 2><file>`.\n * - `exited` resolves with the exit code. On a PTY the child is an\n * interactive shell that never exits on its own, so `kill()` is\n * the normal termination path, not an abnormal one.\n * - Providers that impose a default command timeout (E2B and Daytona\n * both default to 60s) MUST disable or maximise it here. A stream\n * opened by this method is expected to live for the whole session.\n */\n execStream?: (\n handle: ExecutionHandle,\n command: string,\n options?: {\n cwd?: string\n env?: Record<string, string>\n /** Aborts startup and kills the child once running. */\n signal?: AbortSignal\n },\n ) => Promise<StreamHandle>\n\n /**\n * Open an interactive terminal (a PTY running the user's login shell) in\n * the context: on the host, in the container, in the sandbox. For people,\n * not protocols: the opposite of {@link execStream}, which defeats every\n * terminal semantic this one keeps (echo, line editing, job control,\n * window size).\n *\n * Optional: a context without a PTY primitive (or a runtime without one:\n * the local contexts need Bun) leaves it undefined, and callers offer no\n * terminal rather than falling back to a host shell.\n */\n openTerminal?: (handle: ExecutionHandle, options: TerminalOptions) => Promise<TerminalProcess>\n\n /**\n * Re-attach to a terminal opened earlier, by its {@link TerminalProcess.id},\n * after the host lost the connection (daemon restart, paused sandbox).\n * Resolves `null` when it is gone. Only contexts whose terminals outlive\n * the host (remote sandboxes) implement it.\n */\n reconnectTerminal?: (handle: ExecutionHandle, id: string, options: TerminalOptions) => Promise<TerminalProcess | null>\n\n /**\n * SIGTERM the whole process group of a running background task.\n * Idempotent — second call returns `null` (or the cached exit info).\n * Resolves once the process has exited AND its output stream has\n * been flushed + closed.\n *\n * `null` return on miss (unknown id, already cleaned up) so the\n * shell_kill tool can surface a clean \"no such task\" message\n * without throwing.\n */\n killBackground?: (\n handle: ExecutionHandle,\n taskId: string,\n ) => Promise<TaskExitInfo | null>\n\n /**\n * Snapshot of every task in the context's registry — running AND\n * terminated (entries remain until the next context destroy, so\n * the model can still read output of exited tasks).\n */\n listBackground?: (\n handle: ExecutionHandle,\n ) => Promise<readonly TaskEntry[]>\n\n /**\n * Block until a background task terminates, then resolve with its\n * exit info. Resolves immediately for already-terminated tasks.\n *\n * Returns `null` when:\n * - the task id is unknown (or owned by another handle — same\n * isolation contract as `killBackground`), OR\n * - `timeoutMs` elapsed / `signal` aborted before the task exited.\n *\n * Callers that need to distinguish \"unknown\" from \"still running\"\n * should consult `listBackground` first (the `wait_task` tool does).\n *\n * This is the injectable wait seam for the `wait_task` tool:\n * in-process contexts implement it on the existing `onExit`\n * machinery; durable hosts implement it as an awakeable park\n * (runner fires task-exit over their bridge → resolveAwakeable).\n */\n waitBackground?: (\n handle: ExecutionHandle,\n taskId: string,\n options?: { timeoutMs?: number, signal?: AbortSignal },\n ) => Promise<TaskExitInfo | null>\n\n /**\n * Transfer ownership of every still-running task from `fromHandle`\n * to `toHandle`. Used by the spawn tool to \"promote\" a subagent's\n * background tasks up to the parent's handle so they outlive the\n * subagent's destroy() — matching shell semantics, where a `&`-ed\n * command outlives the parent process.\n *\n * With `fromHandle === toHandle` ownership stays put and only the\n * callbacks are rebound: a host that keeps one handle across agent\n * rebuilds (`chat/execution-cache.ts`) hands the running tasks to the\n * freshly built agent this way.\n *\n * Side effects:\n * - The task's `handleId` is rewritten, so subsequent\n * `listBackground(toHandle)` / `killBackground(toHandle, …)` /\n * `destroy(toHandle)` see it (and `fromHandle`-scoped operations\n * don't).\n * - When `newOnExit` / `newOnStall` are provided, the task's OWNER\n * callbacks are REPLACED with them. Critical: they were captured\n * against the spawning agent's hook bus, which is about to be\n * destroyed; without rewiring, the new owner never learns when the\n * task terminates or stalls. Pass closures that fire the new owner's\n * `background:exit` / `background:stall` hooks. In-flight\n * `killBackground` / `waitBackground` resolvers are not owner\n * callbacks and keep firing.\n *\n * Returns the entries that were actually reassigned (running tasks\n * only; terminated ones stay where they are). Implementations that\n * don't support reassignment can leave this undefined; the caller\n * (spawn.ts) falls back to the current behavior of killing child\n * tasks at subagent shutdown.\n */\n reassignBackgroundTasks?: (\n fromHandle: ExecutionHandle,\n toHandle: ExecutionHandle,\n newOnExit?: (info: TaskExitInfo) => void,\n newOnStall?: (info: TaskStallInfo) => void,\n ) => Promise<readonly TaskEntry[]>\n\n /** Read a file from the context's filesystem */\n readFile: (handle: ExecutionHandle, path: string) => Promise<string>\n\n /**\n * Read a file from the context's filesystem as raw bytes.\n *\n * Used by `read_file` to dispatch image / binary files into the multimodal\n * `ToolResultContent[]` route. Optional — when not implemented, the tool\n * falls back to `base64 < path` via the `exec` seam, which works in any\n * shell-capable context. Implementations that already have a native\n * binary read (in-process `fs.readFile` without encoding, container API,\n * sandbox SDK) should override for the latency win.\n */\n readFileBinary?: (handle: ExecutionHandle, path: string) => Promise<Uint8Array>\n\n /**\n * Cheap size probe for a file in the context's filesystem, in bytes.\n * `null` = unknowable (missing file, not a regular file, probe failed,\n * or containment rejected the path — a probe must not leak even the\n * size of files outside the workspace root).\n *\n * Exists because `readFile` has no partial-read form: tools that must\n * materialize a whole file (read_file's text path, edit/multi_edit,\n * grep's no-rg fallback) consult this first to refuse multi-GB targets\n * instead of OOMing the HOST — the read lands in host memory no matter\n * where the file lives. Per-context posture:\n *\n * - `process` — implements it (local stat, µs).\n * - `docker` — implements it via `wc -c` through its exec; its\n * `readFile` gets transport headroom above the tool ceiling so\n * the probe (tool policy), not the 10MB exec cap, decides read\n * limits — same experience as every other context.\n * - `sandbox` (and the e2b / daytona providers behind it) —\n * implements it via `wc -c` through the provider's exec: one extra\n * round-trip per whole-read tool call, paid so a multi-GB sandbox\n * file is refused BEFORE the SDK transfers it into host memory.\n *\n * KNOWN RESIDUAL (sandbox providers): this guards the `readFile` path\n * only. Their `exec` output is buffered inside the provider SDKs\n * (e2b `commands.run`, daytona `executeCommand`), which we cannot cap\n * from this side — a command that streams GBs to stdout within its\n * timeout window can still balloon host memory. Docker doesn't share\n * the residual (we own its transport; see `output-cap.ts`). A shell\n * wrapper (`| head -c`) was considered and rejected: preserving exit\n * codes, stderr separation, and timeout semantics through a pipe for\n * EVERY command is fragile, and the timeout already time-bounds the\n * exposure.\n */\n fileSize?: (handle: ExecutionHandle, path: string) => Promise<number | null>\n\n /**\n * Write a file to the context's filesystem.\n *\n * `encoding` applies only when `content` is a string (how its bytes are\n * produced; defaults to utf-8) and is ignored for a Buffer, which is\n * written verbatim.\n */\n writeFile: (handle: ExecutionHandle, path: string, content: string | Buffer, encoding?: BufferEncoding) => Promise<void>\n\n /**\n * List files in the context filesystem.\n *\n * Plain paths list immediate directory entries. Paths that\n * contain glob metacharacters (`*`, `?`, `[]`, `{}`) request matched file\n * enumeration inside the target context. Contexts that cannot support\n * globbing should throw a clear error rather than silently returning no\n * matches. `metadata` is best-effort and only required when the context can\n * provide it without expensive per-file shell calls.\n */\n listFiles: (handle: ExecutionHandle, path: string, options?: ListFilesOptions) => Promise<ListFilesEntry[]>\n\n /**\n * The context's own entry operations (create, move, copy, remove) for\n * `handle`, with paths resolved like every other file method. Optional:\n * without it, `entryPortOf` (`./entries`) runs POSIX commands through\n * `exec` (`mkdir -p`, `mv`, `cp -RP`, `rm -rf`), which every shell\n * context can do. Implement it where a native call is cheaper or safer\n * (in-process fs, a machine link).\n */\n entries?: (handle: ExecutionHandle) => EntryPort\n\n /**\n * Resolve the host-side port that a container port was published on\n * (docker context only, and only when the matching entry was created\n * with `host` omitted in `SpawnConfig.ports`).\n *\n * Resolves to `null` if the container port isn't published. Other\n * contexts (process, sandbox) don't implement this; they don't have\n * a port-mapping concept.\n */\n getMappedPort?: (handle: ExecutionHandle, containerPort: number) => Promise<number | null>\n\n /** Destroy the execution environment and clean up resources */\n destroy: (handle: ExecutionHandle) => Promise<void>\n}\n\n// ---------------------------------------------------------------------------\n// Background task types\n// ---------------------------------------------------------------------------\n\n/** Options for {@link ExecutionContext.openTerminal} and {@link ExecutionContext.reconnectTerminal}. */\nexport interface TerminalOptions {\n /** Working directory; defaults to the handle's cwd. */\n cwd?: string\n /** Terminal width in columns. */\n cols: number\n /** Terminal height in rows. */\n rows: number\n /** Extra environment on top of what the context's commands get. */\n env?: Record<string, string>\n /** Variables to drop from the inherited environment (local contexts). */\n unsetEnv?: readonly string[]\n /** Raw terminal output. Called synchronously; never slowed by the consumer. */\n onData: (data: Uint8Array) => void\n}\n\n/** An interactive terminal opened by {@link ExecutionContext.openTerminal}. */\nexport interface TerminalProcess {\n /** Opaque id for {@link ExecutionContext.reconnectTerminal}. */\n id: string\n /** Whether {@link ExecutionContext.reconnectTerminal} can find it again later. */\n reconnectable: boolean\n /** Host pid of the shell, when it runs on this machine (for labels). */\n localPid?: number\n write: (data: string | Uint8Array) => void\n resize: (cols: number, rows: number) => void\n /** End the shell and everything it started. Idempotent. */\n kill: () => Promise<void>\n /** Let go without ending it (a remote PTY keeps running for a reconnect). */\n detach: () => Promise<void>\n /** Resolves once with the exit code; `-1` when the connection was lost instead. */\n exited: Promise<number>\n}\n\n/**\n * Terminal mode for {@link ExecutionContext.execBackground}: run the task in\n * a PTY instead of pipes, so it behaves as it would for a person (colors,\n * progress, tools that insist on a TTY) and can be watched and typed into.\n * The log file still receives the output, with terminal control sequences\n * removed, and the registry (kill, wait, list, reassign) is unchanged.\n */\nexport interface BackgroundTerminalOptions {\n cols: number\n rows: number\n /** Raw output as it arrives (the log gets the stripped text). */\n onData: (data: Uint8Array) => void\n /** Receives the functions to type into and resize the task's terminal. */\n onReady?: (io: { write: (data: string | Uint8Array) => void, resize: (cols: number, rows: number) => void }) => void\n}\n\n/**\n * Lifecycle status of a background task.\n *\n * - `'running'` — process is still live; `exitCode` / `signal` unset.\n * - `'exited'` — process terminated on its own (clean or non-zero exit).\n * - `'killed'` — the host issued `killBackground` (SIGTERM to the group).\n *\n * The status is a coarse-grained signal; the exit code carries the\n * fine-grained detail (e.g. `143 = SIGTERM` for `'killed'`).\n */\nexport type BackgroundTaskStatus = 'running' | 'exited' | 'killed'\n\n/**\n * Returned by `execBackground` once the process has spawned — the handle the model and\n * the framework use to refer to the task until it terminates.\n *\n * `outputPath` is an absolute path to the log file the context is\n * appending stdout + stderr to (interleaved by emit order). The model\n * reads it via the normal `read_file` tool; no special tool is required.\n */\nexport interface TaskHandle {\n /**\n * Stable id minted by the context — typically `bash_<n>` for\n * `ProcessContext`. Sequential within a single context instance,\n * resets when a new context is constructed. Forwarded to `killBackground` /\n * `listBackground` and stamped into every `<task-notification>` block.\n */\n taskId: string\n /** OS pid of the spawned shell wrapper (process-group leader on POSIX). */\n pid: number\n /** Absolute path to the log file the context is streaming output into. */\n outputPath: string\n /** True when the task runs in a terminal (`execBackground`'s `terminal` option was honored). */\n terminal?: boolean\n}\n\n/**\n * A live bidirectional stream to a process in the context. Returned by\n * {@link ExecutionContext.execStream}; see that method for the full\n * implementor contract (why the streams are bytes, why `stderr` is\n * optional, what PTY-backed contexts must do before the first byte).\n *\n * Ownership: the caller owns the lifetime. Nothing reaps this handle\n * automatically, so `kill()` belongs in the consumer's teardown path —\n * for MCP that is the transport's `close()`, reached via the agent's\n * `mcpConnection.close()` during `destroy()`.\n */\nexport interface StreamHandle {\n /** Process id inside the context — NOT meaningful on the host. */\n pid: number\n /**\n * Child's stdout as raw byte chunks, in emit order.\n *\n * CONSUMER OBLIGATION: drain this (and {@link stderr}) for the stream's\n * lifetime. Nothing here is bounded, and the consequence of ignoring it\n * varies by backend and by host runtime, none of it good:\n *\n * - `process` / `docker` hand back real OS pipes. Under Node an unread\n * stream stops draining the fd and the child BLOCKS once the pipe\n * fills (~64 KiB) — a deadlock, not a slowdown. Under Bun the runtime\n * buffers eagerly instead, so it presents as unbounded host memory\n * (measured: 32 MiB of unread stderr never blocked the child).\n * - `e2b` / `daytona` buffer in a `StreamQueue`, which grows without\n * limit. It cannot do otherwise: both SDKs push output through a\n * synchronous `(data) => void` callback, so there is no channel to\n * apply backpressure, and dropping bytes would desynchronise a framed\n * protocol permanently. The queue logs a one-shot warning once the\n * unread backlog passes 8 MiB so a stalled consumer is diagnosable.\n *\n * `createContextStdioTransport` satisfies this for both streams.\n */\n stdout: AsyncIterable<Uint8Array>\n /**\n * Child's stderr, when the implementation can provide it separately.\n * Present on pipe-backed contexts. A PTY-backed context cannot split it\n * from the terminal stream, so it redirects stderr to a file and either\n * surfaces it here out-of-band or leaves this unset — expect a lower\n * latency guarantee there than on stdout.\n */\n stderr?: AsyncIterable<Uint8Array>\n /** Write to the child's stdin. Resolves once the bytes are handed off. */\n write: (data: Uint8Array) => Promise<void>\n /** Terminate the child. Idempotent — killing a dead child is a no-op. */\n kill: () => Promise<void>\n /**\n * Resolves with the exit code when the child terminates, including\n * termination via {@link kill}. Never rejects.\n */\n exited: Promise<number>\n}\n\n/**\n * Fired exactly once per task when the child process terminates, via\n * `execBackground`'s `onExit` callback. The agent layer translates this\n * into a queued `<task-notification>` for the next turn.\n *\n * `signal` is set when the child was terminated by a signal (e.g.\n * SIGTERM from our own kill-tree, SIGKILL from oom-killer); absent on\n * natural exit. `exitCode` is `128 + signal-number` on signal-killed\n * children, matching POSIX shell conventions — `143` for SIGTERM, etc.\n */\nexport interface TaskExitInfo {\n /** Id of the task, as in {@link TaskHandle.taskId}. */\n taskId: string\n /** How the task ended. */\n status: Exclude<BackgroundTaskStatus, 'running'>\n /** Exit code of the process. */\n exitCode: number\n /** Signal that terminated the process, when there was one. */\n signal?: NodeJS.Signals\n /** Absolute path of the log file holding the task output. */\n outputPath: string\n /** `Date.now()` delta between spawn and exit. */\n durationMs: number\n /** The original command string the model invoked — useful for telemetry / banner summary. */\n command: string\n}\n\n/**\n * One row in `listBackground`'s snapshot. Living entries (status `'running'`)\n * have `exitCode` / `signal` / `endedAt` unset; terminated entries carry the\n * same data `TaskExitInfo` returned at exit time.\n */\nexport interface TaskEntry {\n /** Id of the task, as in {@link TaskHandle.taskId}. */\n taskId: string\n /** Process id. */\n pid: number\n /** Command the task runs. */\n command: string\n /** Working directory of the task. */\n cwd: string\n /** Start time, in milliseconds since the epoch. */\n startedAt: number\n /**\n * Set when the task terminated. Lets pull-based consumers (the agent's\n * run-boundary reconcile) derive `durationMs = endedAt - startedAt`\n * without depending on when the snapshot was taken.\n */\n endedAt?: number\n /** Absolute path of the log file holding the task output. */\n outputPath: string\n /** Current state of the task. */\n status: BackgroundTaskStatus\n /** Exit code. Set once the task terminated. */\n exitCode?: number\n /** Signal that terminated the process, when there was one. */\n signal?: NodeJS.Signals\n /** Total bytes written to the output file so far — useful for \"task X has produced N KB\" UX hints. */\n bytesWritten: number\n}\n\n/**\n * Fired by the optional stall watchdog (see `execBackground`'s\n * `stallTimeoutMs`) when a running task has produced no output for the\n * configured window. The process is still alive — this is a signal, not\n * a state transition.\n */\nexport interface TaskStallInfo {\n /** Id of the stalled task. */\n taskId: string\n /** Command the task runs. */\n command: string\n /** Absolute path of the log file holding the task output. */\n outputPath: string\n /** Milliseconds since the last output chunk (>= the configured window). */\n stalledForMs: number\n /** Total bytes the task has written so far. */\n bytesWritten: number\n}\n"],"mappings":";;;;;;;AA+EA,SAAgB,+BAA+B,SAAoD;CACjG,OAAO,QAAQ,aAAa,kBACtB,QAAQ,iBAAiB,qBAAqB;AACtD"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"types-bDQagoiL.d.ts","names":[],"sources":["../src/contexts/isolation.ts","../src/contexts/types.ts"],"mappings":"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"}
|