zidane 9.1.1 → 9.1.3
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-CeCavNlg.js} +7 -7
- package/dist/{acp-Di9WvMDF.js.map → acp-CeCavNlg.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-BKpjlJ8a.js} +2 -2
- package/dist/{auth-store-port-DFgf22oo.js.map → auth-store-port-BKpjlJ8a.js.map} +1 -1
- package/dist/{auto-update-restart-BFB7Ek87.js → auto-update-restart-CQJtndMG.js} +277 -41
- package/dist/auto-update-restart-CQJtndMG.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-DeRHgYvl.js} +4 -4
- package/dist/{cli-shared-CabruH8Z.js.map → cli-shared-DeRHgYvl.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-Bqg-qNBM.js} +2 -2
- package/dist/{credentials-wwETW8rI.js.map → credentials-Bqg-qNBM.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-CX7nbMCn.js} +4 -4
- package/dist/{discovery-DycXFxdA.js.map → discovery-CX7nbMCn.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-CxBGgU94.js} +6 -6
- package/dist/{engine-VQ86XGdG.js.map → engine-CxBGgU94.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-j_LFRBwS.js} +4 -4
- package/dist/{executor-C7RQrkEq.js.map → executor-j_LFRBwS.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-ADlhBQ_1.js} +8 -8
- package/dist/{extensions-BCx4QuGB.js.map → extensions-ADlhBQ_1.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-B-Dhmzzf.js} +2 -2
- package/dist/{google-Crva32sk.js.map → google-B-Dhmzzf.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-wO_6GW0y.js → host-C61ntFBC.js} +276 -103
- package/dist/host-C61ntFBC.js.map +1 -0
- 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-Cb2TlGtN.js} +5 -5
- package/dist/{host-signals-Jsjd_-4g.js.map → host-signals-Cb2TlGtN.js.map} +1 -1
- package/dist/{host-version-CNAr9pov.js → host-version-BIx4CuBM.js} +2 -2
- package/dist/{host-version-CNAr9pov.js.map → host-version-BIx4CuBM.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-DiH_P-wr.js} +4 -4
- package/dist/{ipc-BzWhIybr.js.map → ipc-DiH_P-wr.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-BbC_lOnn.js} +9 -9
- package/dist/{links-CJG_rFvf.js.map → links-BbC_lOnn.js.map} +1 -1
- package/dist/{loaded-entry-DTURJo_R.js → loaded-entry-C0vkCVNQ.js} +2 -2
- package/dist/{loaded-entry-DTURJo_R.js.map → loaded-entry-C0vkCVNQ.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-C3w8nO8f.js} +132 -31
- package/dist/memory-C3w8nO8f.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-DRAEpKOU.js} +3 -3
- package/dist/{path-display-COVV71Yu.js.map → path-display-DRAEpKOU.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-CpXV_uLE.js} +5 -5
- package/dist/providers-CpXV_uLE.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-CJHvmvaP.js} +2 -2
- package/dist/{registry-BKjeBnoy.js.map → registry-CJHvmvaP.js.map} +1 -1
- package/dist/{registry-B6Ww76iW.js → registry-CN6JlZKj.js} +2 -2
- package/dist/{registry-B6Ww76iW.js.map → registry-CN6JlZKj.js.map} +1 -1
- package/dist/{registry-B9INJwJR.js → registry-CnnKaY9s.js} +324 -39
- package/dist/registry-CnnKaY9s.js.map +1 -0
- package/dist/{remote-hosts-BMWoHCWO.js → remote-hosts-DoO9CJUQ.js} +4 -4
- package/dist/{remote-hosts-BMWoHCWO.js.map → remote-hosts-DoO9CJUQ.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-D_FpKFMw.js} +6 -6
- package/dist/{setting-BQBSyUq0.js.map → setting-D_FpKFMw.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-CW2UgHgb.js} +3 -3
- package/dist/{settings-keys-iI_Y-7MC.js.map → settings-keys-CW2UgHgb.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-XgDPIwQS.js} +3 -3
- package/dist/{system-freeze-m5o1sGIM.js.map → system-freeze-XgDPIwQS.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-szdW1Od9.js} +2 -2
- package/dist/{version-DqqqvHDP.js.map → version-szdW1Od9.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-C3l9jl9x.js} +2 -2
- package/dist/{wire-CLm2rMK0.js.map → wire-C3l9jl9x.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-CEHi0CiB.js} +4 -4
- package/dist/{ws-DfGGYQ4W.js.map → ws-CEHi0CiB.js.map} +1 -1
- package/dist/{ws-client-CFMbhsNq.js → ws-client-t8XNWxcq.js} +2 -2
- package/dist/{ws-client-CFMbhsNq.js.map → ws-client-t8XNWxcq.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":"browser-BcoCCB_n.js","names":[],"sources":["../src/ipc/extension-paths.ts","../src/ipc/scopes.ts","../src/ipc/browser-pair.ts","../src/ipc/extensions-client.ts","../src/ipc/machine/join.ts","../src/ipc/browser.ts"],"sourcesContent":["/**\n * The HTTP paths a zidane-server serves extension assets on:\n * browser-safe constants, shared by the server routes\n * (`server/extension-assets`), the daemon's bundle store and the clients\n * (`zidane/ipc/browser`).\n */\n\n/** Where the `ui` bundles are listed (`GET ?cwd=`) and served (`GET /<hash>.js`). */\nexport const SERVER_EXTENSIONS_UI_PATH = '/zidane/extensions/ui'\n\n/** Where webview URLs are minted (`POST ?cwd=&id=`) and their files served (`/<ticket>/…`). */\nexport const SERVER_EXTENSIONS_WEBVIEW_PATH = '/zidane/extensions/webview'\n","/**\n * What a client may call: every method of {@link IpcMethods} declares the\n * lowest client scope allowed to call it, and a zidane-server refuses a call\n * its connection's token doesn't reach (`daemon/dispatcher.ts`).\n *\n * chat read sessions and settings, run and steer the agent, answer its\n * questions and plans, manage the session list, and browse,\n * search, create folders in and clone repositories into the\n * workspace roots (a server can turn the last two off:\n * `allowCreateFolders`, `allowClone`). What a person chatting\n * with the agent needs.\n * approve chat, and decide the agent's tool approvals (safe mode).\n * admin approve, and configure the host: credentials, settings,\n * installs, MCP servers, machines, sync, tokens, updates, and a\n * direct shell (terminals, workspace exec and writes).\n *\n * The scopes nest (admin ⊇ approve ⊇ chat). A local connection (the desktop\n * app's own host, the daemon over its socket) carries no scope: it is the\n * user's own computer. `machine` tokens are another kind of connection\n * (`docs/MACHINES.md`), not a client scope.\n *\n * Node-free and React-free: browser clients read it to show only what their\n * token allows. `METHOD_SCOPES` is typed over every method, so a method added\n * to the protocol without a scope fails the typecheck.\n */\nimport type { IpcMethodName } from './protocol'\n\n/** A client token's reach, from the narrowest. */\nexport const CLIENT_SCOPES = ['chat', 'approve', 'admin'] as const\n/** A client token's reach: {@link CLIENT_SCOPES}. */\nexport type ClientScope = typeof CLIENT_SCOPES[number]\n\n/**\n * Whether a string is a {@link ClientScope}.\n *\n * @param value - The value to check (a CLI flag, a stored token's scope).\n */\nexport function isClientScope(value: unknown): value is ClientScope {\n return typeof value === 'string' && (CLIENT_SCOPES as readonly string[]).includes(value)\n}\n\n/**\n * Whether a connection granted `granted` may call a method that needs `required`.\n *\n * @param granted - The connection's scope.\n * @param required - The method's scope ({@link METHOD_SCOPES}).\n */\nexport function scopeAllows(granted: ClientScope, required: ClientScope): boolean {\n return CLIENT_SCOPES.indexOf(granted) >= CLIENT_SCOPES.indexOf(required)\n}\n\n/** The lowest client scope that may call each method. */\nexport const METHOD_SCOPES: { readonly [M in IpcMethodName]: ClientScope } = {\n 'agents.list': 'chat',\n 'approvals.resolve': 'approve',\n 'approvals.denyAll': 'approve',\n 'approvals.listPending': 'chat',\n 'safelist.list': 'chat',\n 'safelist.remove': 'approve',\n 'artifacts.list': 'chat',\n 'artifacts.delete': 'chat',\n 'artifacts.upsert': 'chat',\n 'artifacts.refresh': 'chat',\n 'artifacts.badges': 'chat',\n 'auth.status': 'chat',\n 'auth.setApiKey': 'admin',\n 'auth.remove': 'admin',\n 'auth.configure': 'admin',\n 'auth.setPreferred': 'admin',\n 'auth.rename': 'admin',\n 'auth.oauth.begin': 'admin',\n 'auth.oauth.complete': 'admin',\n 'auth.oauth.respond': 'admin',\n 'auth.oauth.cancel': 'admin',\n 'badges.actions': 'chat',\n 'badges.run': 'chat',\n 'panels.list': 'chat',\n 'panels.load': 'chat',\n 'panels.action': 'chat',\n 'panels.watch': 'chat',\n 'panels.unwatch': 'chat',\n 'palette.list': 'chat',\n 'palette.run': 'chat',\n 'palette.watch': 'chat',\n 'palette.unwatch': 'chat',\n 'browser.registerHost': 'chat',\n 'browser.unregisterHost': 'chat',\n 'browser.respond': 'chat',\n 'catalog.skills': 'chat',\n 'catalog.mcps': 'chat',\n 'catalog.extensions': 'chat',\n 'catalog.plugins': 'chat',\n 'catalog.install': 'admin',\n 'catalog.remove': 'admin',\n 'catalog.update': 'admin',\n 'chat.send': 'chat',\n 'chat.interrupt': 'chat',\n 'chat.steer': 'chat',\n 'chat.followUp': 'chat',\n 'chat.pushQueued': 'chat',\n 'chat.isRunning': 'chat',\n 'chat.rebuildAgent': 'chat',\n 'chat.listWork': 'chat',\n 'chat.cancelWork': 'chat',\n 'claudeImport.detect': 'admin',\n 'claudeImport.preview': 'admin',\n 'claudeImport.run': 'admin',\n 'commands.list': 'chat',\n 'commands.completeArgs': 'chat',\n 'completions.providers': 'chat',\n 'completions.suggest': 'chat',\n 'completions.submit': 'chat',\n 'daemon.info': 'chat',\n 'daemon.ownedProcesses': 'chat',\n 'daemon.sessionProcesses': 'chat',\n 'daemon.shutdown': 'admin',\n 'decisions.test': 'chat',\n 'drafts.get': 'chat',\n 'drafts.set': 'chat',\n 'drafts.setAttachments': 'chat',\n 'environments.list': 'chat',\n 'environments.update': 'admin',\n 'environments.verify': 'chat',\n 'extensions.configSchema': 'chat',\n 'extensions.actions': 'chat',\n 'extensions.actionStatuses': 'chat',\n // Each action declares its own scope (`ActionSetting.scope`, default admin); the handler checks it.\n 'extensions.runAction': 'chat',\n 'extensions.create': 'admin',\n 'rpc.call': 'chat',\n 'rpc.cancel': 'chat',\n 'extensions.ui.list': 'chat',\n 'extensions.entries': 'chat',\n 'extensions.ui.invoke': 'chat',\n 'extensions.links.open': 'chat',\n 'ui.client.announce': 'chat',\n 'ui.client.reply': 'chat',\n 'ui.dialog.answer': 'chat',\n 'ui.dialog.validate': 'chat',\n 'extensions.storage.load': 'chat',\n // Chat-writable on purpose: web clients persist extension UI stores with a chat token. An extension must not keep\n // anything it trusts (allowlists, tokens, flags) in storage; trusted values go in settings (admin).\n 'extensions.storage.set': 'chat',\n 'extensions.settings': 'chat',\n 'extensions.settings.set': 'admin',\n 'extensions.commands': 'chat',\n 'extensions.command.run': 'chat',\n 'extensions.keymap.push': 'chat',\n 'extensions.keymap.pop': 'chat',\n 'extensions.keymap.list': 'chat',\n 'extensions.integrations.list': 'chat',\n 'extensions.integrations.connectKey': 'admin',\n 'extensions.integrations.start': 'admin',\n 'extensions.integrations.flowInput': 'admin',\n 'extensions.integrations.disconnect': 'admin',\n 'extensions.integrations.setDefault': 'admin',\n 'extensions.catalogs.provenance': 'chat',\n 'files.search': 'chat',\n 'files.resolvePaths': 'chat',\n 'files.list': 'chat',\n 'files.location': 'chat',\n 'files.diagnostics': 'admin',\n 'files.diagnosticsInvalidate': 'chat',\n 'files.diagnosticsTools': 'chat',\n 'files.mediaTicket': 'chat',\n 'fs.roots': 'chat',\n 'fs.listDirs': 'chat',\n 'fs.mkdir': 'chat',\n 'fs.searchDirs': 'chat',\n 'git.status': 'chat',\n 'git.branches': 'chat',\n 'git.pullRequests': 'chat',\n 'git.branchPullRequest': 'chat',\n 'git.commit': 'chat',\n 'git.fileStatus': 'chat',\n 'git.diff': 'chat',\n 'git.checkout': 'admin',\n 'git.createBranch': 'admin',\n 'git.sync': 'admin',\n 'git.clone': 'chat',\n 'git.cloneCancel': 'chat',\n 'git.watch': 'chat',\n 'git.unwatch': 'chat',\n 'history.searchSession': 'chat',\n 'history.searchAll': 'chat',\n 'host.capabilities': 'chat',\n 'usage.summary': 'chat',\n 'usage.providers': 'chat',\n 'usage.github': 'chat',\n 'integrations.register': 'chat',\n 'integrations.update': 'chat',\n 'integrations.list': 'chat',\n 'interactions.list': 'chat',\n 'interactions.respond': 'chat',\n 'interactions.cancel': 'chat',\n 'interactions.rehydrate': 'chat',\n 'interactions.rehydrateSessions': 'chat',\n 'machine.attach': 'admin',\n 'machine.call': 'admin',\n 'machine.detach': 'admin',\n 'machines.list': 'chat',\n 'machines.forget': 'admin',\n 'machines.listDirs': 'chat',\n 'machines.share.start': 'admin',\n 'machines.share.stop': 'admin',\n 'machines.useServer': 'admin',\n 'machines.links.status': 'chat',\n 'mcp.upsert': 'admin',\n 'mcp.remove': 'admin',\n 'mcp.test': 'chat',\n 'mcp.signOut': 'admin',\n 'mcp.instances': 'chat',\n 'mcp.restart': 'admin',\n 'models.list': 'chat',\n 'models.test': 'chat',\n 'onboarding.detect': 'chat',\n 'onboarding.providers': 'chat',\n 'onboarding.complete': 'admin',\n 'orchestration.main': 'chat',\n 'orchestration.createWorker': 'chat',\n 'orchestration.list': 'chat',\n 'orchestration.read': 'chat',\n 'orchestration.send': 'chat',\n 'orchestration.steer': 'chat',\n 'orchestration.cancel': 'chat',\n 'orchestration.transcript': 'chat',\n 'orchestration.wait': 'chat',\n 'orchestration.events': 'chat',\n 'orchestration.pending': 'chat',\n 'orchestration.answer': 'chat',\n 'orchestration.approve': 'approve',\n 'prefs.get': 'chat',\n 'prefs.set': 'chat',\n 'presence.list': 'chat',\n 'presence.watch': 'chat',\n 'queue.list': 'chat',\n 'queue.add': 'chat',\n 'queue.remove': 'chat',\n 'queue.update': 'chat',\n 'queue.attachments': 'chat',\n 'queue.pushNow': 'chat',\n 'references.providers': 'chat',\n 'references.resolve': 'chat',\n 'runtime.reload': 'admin',\n 'search.set': 'chat',\n 'server.update.status': 'chat',\n 'server.update.configure': 'admin',\n 'server.update.check': 'admin',\n 'server.update.install': 'admin',\n 'logs.list': 'admin',\n 'logs.watch': 'admin',\n 'logs.unwatch': 'admin',\n 'perf.watch': 'admin',\n 'perf.unwatch': 'admin',\n 'perf.history': 'admin',\n 'perf.threads': 'admin',\n 'sessions.setLaunchOverrides': 'admin',\n 'sessions.list': 'chat',\n 'sessions.listMeta': 'chat',\n 'sessions.getMeta': 'chat',\n 'sessions.get': 'chat',\n 'sessions.getTurns': 'chat',\n 'sessions.getToolResult': 'chat',\n 'sessions.getHeader': 'chat',\n 'sessions.setExtensionState': 'chat',\n 'sessions.create': 'chat',\n 'sessions.delete': 'chat',\n 'sessions.sideSession': 'chat',\n 'sessions.retryEnvironment': 'chat',\n 'sessions.moveEnvironment': 'chat',\n 'sessions.environmentActions': 'chat',\n 'sessions.runEnvironmentAction': 'admin',\n 'sessions.workspaceExec': 'admin',\n 'sessions.workspaceExecStream': 'admin',\n 'sessions.workspaceExecCancel': 'admin',\n 'sessions.workspaceReadFile': 'chat',\n 'sessions.workspaceWriteFile': 'admin',\n 'sessions.workspaceListFiles': 'chat',\n 'sessions.workspaceFileSize': 'chat',\n 'sessions.workspaceCreate': 'admin',\n 'sessions.workspaceMove': 'admin',\n 'sessions.workspaceCopy': 'admin',\n 'sessions.workspaceRemove': 'admin',\n 'sessions.workspaceEmptyDirs': 'chat',\n 'sessions.setTitle': 'chat',\n 'sessions.generateTitle': 'chat',\n 'sessions.titleStatus': 'chat',\n 'sessions.setArchived': 'chat',\n 'sessions.setFavorite': 'chat',\n 'sessions.setPolicy': 'chat',\n 'sessions.setSpace': 'chat',\n 'sessions.setAgentId': 'chat',\n 'sessions.setEffort': 'chat',\n 'sessions.setModel': 'chat',\n 'sessions.setModelOptions': 'chat',\n 'sessions.loadEvents': 'chat',\n 'sessions.resume': 'chat',\n 'sessions.getTurn': 'chat',\n 'sessions.contextBreakdown': 'chat',\n 'sessions.artifacts': 'chat',\n 'sessions.touch': 'chat',\n 'sessions.fork': 'chat',\n 'sessions.deleteTurn': 'chat',\n 'sessions.editTurnText': 'chat',\n 'sessions.rewind': 'chat',\n 'sessions.setFolder': 'chat',\n 'sessions.appendTurns': 'chat',\n 'sessions.appendNote': 'chat',\n 'sessions.compact': 'chat',\n 'sessions.systemMd': 'chat',\n 'sessions.contextSegments': 'chat',\n 'sessions.cacheImpact': 'chat',\n 'sessions.cacheReport': 'chat',\n 'sessions.export': 'chat',\n 'sessions.createSystemOverride': 'admin',\n 'settings.get': 'chat',\n 'settings.set': 'admin',\n 'sidebar.getViews': 'chat',\n 'sidebar.setView': 'chat',\n 'sidebar.getSpace': 'chat',\n 'sidebar.setSpace': 'chat',\n 'skills.browse': 'admin',\n 'extensions.browse': 'admin',\n 'extensions.changeOrigin': 'admin',\n 'suggest.resolve': 'chat',\n 'sync.status': 'admin',\n 'sync.claim': 'admin',\n 'sync.push': 'admin',\n 'sync.reset': 'admin',\n 'sync.release': 'admin',\n 'terminal.state': 'admin',\n 'terminal.open': 'admin',\n 'terminal.attach': 'admin',\n 'terminal.detach': 'admin',\n 'terminal.write': 'admin',\n 'terminal.resize': 'admin',\n 'terminal.ack': 'admin',\n 'terminal.restart': 'admin',\n 'terminal.close': 'admin',\n 'terminal.setHidden': 'admin',\n 'terminal.registerViewer': 'admin',\n 'terminal.unregisterViewer': 'admin',\n 'terminal.projectState': 'admin',\n 'terminal.openInProject': 'admin',\n 'terminal.adopt': 'admin',\n 'terminal.releaseDraft': 'admin',\n 'todos.get': 'chat',\n 'todos.set': 'chat',\n 'tokens.createMachineToken': 'admin',\n 'tokens.list': 'admin',\n 'tokens.create': 'admin',\n 'tokens.revoke': 'admin',\n 'tokens.revokeSelf': 'chat',\n 'tokens.pair': 'admin',\n 'tokens.machineInvite': 'admin',\n}\n\n/**\n * The scope a method needs, or `undefined` for a name outside the protocol.\n *\n * @param method - A method name from the wire.\n */\nexport function methodScope(method: string): ClientScope | undefined {\n return Object.hasOwn(METHOD_SCOPES, method) ? METHOD_SCOPES[method as IpcMethodName] : undefined\n}\n","/**\n * Pairing a browser with a zidane-server: the one-time code `zidane-server pair`\n * (or `tokens.pair`) printed, traded at `POST /zidane/pair` for a scoped device\n * token. Browser-safe: `fetch` only. Re-exported from `zidane/ipc/browser`.\n */\nimport type { ClientScope } from './scopes'\nimport { CLIENT_SCOPES } from './scopes'\n\n/** Where a browser trades a pairing code for a device token (`POST`, JSON), relative to the server's origin. */\nexport const SERVER_PAIR_PATH = '/zidane/pair'\n\n/**\n * Why a pairing failed. The server's answers: `invalid` (no such code, or not a\n * code's shape), `expired`, `used` (spent, or burned by wrong attempts),\n * `rate-limited`, `forbidden` (an origin, proxy or transport its upgrade policy\n * refuses). And the client's: `unavailable` (the server has no pairing route:\n * too old, or running without auth) and `network` (no answer it understands).\n */\nexport type ServerPairFailure = 'invalid' | 'expired' | 'used' | 'rate-limited' | 'forbidden' | 'unavailable' | 'network'\n\n/** A refused or failed pairing, with its {@link ServerPairFailure}. */\nexport class ServerPairError extends Error {\n /** Why it failed. */\n readonly reason: ServerPairFailure\n /** The HTTP status, when the server answered. */\n readonly status?: number\n\n /**\n * @param reason - Why it failed.\n * @param status - The HTTP status, when the server answered.\n */\n constructor(reason: ServerPairFailure, status?: number) {\n super(`pairing failed: ${reason}${status === undefined ? '' : ` (HTTP ${status})`}`)\n this.name = 'ServerPairError'\n this.reason = reason\n if (status !== undefined)\n this.status = status\n }\n}\n\n/** A paired browser's device token. */\nexport interface PairedBrowser {\n /** The token, for `createServerClient({ token })`. Keep it; it is shown once. */\n token: string\n /** The token's id, the one `tokens.list` and `tokens.revoke` use. Absent from servers older than it. */\n id?: string\n /** The scope the code was issued with. */\n scope: ClientScope\n /** The server's name, when it has one (`--name`). */\n serverName?: string\n}\n\n/** Options for {@link pairBrowser}. */\nexport interface PairBrowserOptions {\n /** The fetch to use. Default: `globalThis.fetch`. */\n fetch?: (url: string, init: RequestInit) => Promise<Response>\n}\n\nconst SERVER_FAILURES: readonly ServerPairFailure[] = ['invalid', 'expired', 'used', 'rate-limited', 'forbidden']\nconst BY_STATUS: Record<number, ServerPairFailure> = { 400: 'invalid', 401: 'invalid', 403: 'forbidden', 410: 'expired', 429: 'rate-limited' }\n\n/** The pairing URL on `baseUrl` (`''`: the page's own origin). A `ws(s)://` URL is read as `http(s)://`. */\nfunction pairUrl(baseUrl: string): string {\n if (!baseUrl)\n return SERVER_PAIR_PATH\n const url = new URL(SERVER_PAIR_PATH, baseUrl.replace(/^ws(s?):/i, 'http$1:'))\n return url.toString()\n}\n\n/**\n * Trades a pairing code for a device token.\n *\n * @param baseUrl - The server's origin (`https://box.example`, or the `ws(s)://` URL the client uses). `''`: the page's own origin, for the web app the server serves.\n * @param code - The code as the user typed it (`7KQM-3XFD`; the server ignores case and separators).\n * @param name - The browser's label, used when the operator gave none: the token is named `browser: <name>`.\n * @param options - A `fetch` to use instead of the global one.\n * @returns The token, its id, scope and the server's name.\n * @throws {ServerPairError} When the server refuses the code or never answers.\n * @example\n * ```ts\n * import { createServerClient, pairBrowser, ServerPairError } from 'zidane/ipc/browser'\n *\n * try {\n * const { token } = await pairBrowser('https://box.example', '7KQM-3XFD', 'Firefox on the laptop')\n * const client = createServerClient({ url: 'wss://box.example', token })\n * }\n * catch (error) {\n * if (error instanceof ServerPairError && error.reason === 'expired')\n * console.log('Run zidane-server pair again')\n * }\n * ```\n */\nexport async function pairBrowser(baseUrl: string, code: string, name?: string, options: PairBrowserOptions = {}): Promise<PairedBrowser> {\n const doFetch = options.fetch ?? ((url: string, init: RequestInit) => globalThis.fetch(url, init))\n let response: Response\n try {\n response = await doFetch(pairUrl(baseUrl), {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ code: code.trim(), ...(name ? { name } : {}) }),\n credentials: 'same-origin',\n })\n }\n catch {\n throw new ServerPairError('network')\n }\n const body = await response.json().catch(() => null) as Record<string, unknown> | null\n if (response.ok && body && typeof body.token === 'string' && body.token) {\n const scope = (CLIENT_SCOPES as readonly unknown[]).includes(body.scope) ? body.scope as ClientScope : 'chat'\n return {\n token: body.token,\n scope,\n ...(typeof body.id === 'string' ? { id: body.id } : {}),\n ...(typeof body.serverName === 'string' ? { serverName: body.serverName } : {}),\n }\n }\n const said = body?.error\n if (typeof said === 'string' && (SERVER_FAILURES as readonly string[]).includes(said))\n throw new ServerPairError(said as ServerPairFailure, response.status)\n if (response.status === 404 || response.status === 405)\n throw new ServerPairError('unavailable', response.status)\n throw new ServerPairError(BY_STATUS[response.status] ?? 'network', response.status)\n}\n","/**\n * A typed client for the extension API surfaces of a host, over any\n * connection (the unix socket, the WebSocket, the in-process\n * transport, a browser's `ServerClient`). Browser-safe: no `node:*`. What a TUI in daemon mode, the desktop app and the\n * web app use to draw and drive extensions:\n *\n * - RPC: `rpc` rejects with {@link RpcCallError} (declared error, invalid\n * input or output, unavailable, forbidden for this token, aborted),\n * `onRpcEvent`\n * - UI items per folder (`ui.list`, `ui.onChange`) and their callbacks (`ui.invoke`)\n * - routing: `announce` what the window shows, `serve` the dialogs and\n * UI requests the host routes to it\n * - storage sync, settings with provenance, commands, the keymap and its modes, link handlers,\n * integrations with their sign-in steps, catalog provenance\n *\n * Every `on*` returns its unsubscribe.\n */\nimport type { CatalogItemProvenance, CatalogKind, DialogRequest, IntegrationFlowStep, LinkOpenParams, SettingsSetParams, UiChange, UiClientAnnounce, UiClientRequest, UiInvokeRequest, WireExtensionCommands, WireExtensionEntry, WireExtensionSettings, WireIntegration, WireKeymap, WireStorageLocation, WireStorageSetResult, WireUiList } from '../chat/host/extensions-wire'\nimport type { Json } from '../extensions/api/storage'\nimport type { RpcEventEnvelope } from '../extensions/rpc/wire'\nimport type { StorageArea, StorageSnapshot } from '../extensions/storage/port'\nimport type { HostSignal, IpcMethodName, IpcParams, IpcResult } from './protocol'\nimport { RpcCallError } from '../extensions/api/rpc'\n\ntype SignalOf<K extends HostSignal['kind']> = Extract<HostSignal, { kind: K }>\n\n/** What a window does with what the host routes to it. */\nexport interface ExtensionsUiServer {\n /**\n * Shows a dialog; resolves with the raw answer (`undefined`: cancelled).\n * `signal` aborts when the host gives up on it. A `form` dialog calls\n * `validate(key, value)` as the user edits a field and before answering,\n * and shows the message (`null`: valid) under the field. Answer only once\n * every field validates: the host checks the answer again, and an invalid\n * one makes the extension's `form` reject.\n */\n dialog: (request: DialogRequest, ctx: { dialogId: string, extensionId: string, sessionId?: string, signal: AbortSignal, validate: (key: string, value: unknown) => Promise<string | null> }) => Promise<unknown>\n /** Runs a UI request (panel, navigate, composer); resolves with its result (`boolean`, or the open panel ids). `notify` resolves nothing. */\n client: (request: UiClientRequest) => unknown | Promise<unknown>\n}\n\n/** The typed extension API client. */\nexport interface ExtensionsClient {\n /**\n * Calls an RPC method. Rejects with {@link RpcCallError} when the call\n * fails (`rpc.forbidden`: the method's `scope` is above this connection's\n * token).\n */\n rpc: <T = unknown>(contract: string, method: string, input?: unknown, opts?: { cwd?: string, signal?: AbortSignal }) => Promise<NoInfer<T>>\n /** Hears each event an extension's RPC contract emits. */\n onRpcEvent: (listener: (event: RpcEventEnvelope) => void) => () => void\n /** The extensions of a folder (status, `tui` entry, `ui` bundle), and when to list them again. */\n entries: {\n list: (cwd: string) => Promise<WireExtensionEntry[]>\n onChange: (listener: (cwd: string) => void) => () => void\n }\n /** The UI items of extensions and the callbacks they register. */\n ui: {\n /** The UI items of a folder, and each active extension's `ui` bundle (`bundles`). */\n list: (cwd: string) => Promise<WireUiList>\n /** Runs the callback of a UI item (a button, a menu entry); resolves with its result. */\n invoke: (cwd: string, request: UiInvokeRequest) => Promise<unknown>\n /** Hears each change of a folder's UI items; `reset` means list them again. */\n onChange: (listener: (cwd: string, change: UiChange | { type: 'reset' }) => void) => () => void\n /**\n * A panel would load something new (`extensions:panel`): reload it where\n * it is visible. `sessionId` set: only that session's content changed.\n */\n onPanelChanged: (listener: (change: { cwd: string, extensionId: string, panelId: string, sessionId?: string }) => void) => () => void\n }\n /** Tells the host what this window shows (send on focus and session change). */\n announce: (info: UiClientAnnounce) => Promise<void>\n /** Answers the dialogs and UI requests the host routes to this window. */\n serve: (server: ExtensionsUiServer) => () => void\n /** The extensions' synced storage. */\n storage: {\n /** Reads every entry of a storage location, with the project root it resolved to when there is one. */\n load: (cwd: string, loc: WireStorageLocation) => Promise<StorageSnapshot & { projectRoot?: string }>\n /** Writes an entry; the result says whether the host took it, and what it holds now (put `value` back when refused). */\n set: (cwd: string, loc: WireStorageLocation, area: StorageArea, key: string, value: Json | undefined) => Promise<WireStorageSetResult>\n /** Hears each write other clients and runtimes make to the storage. */\n onChange: (listener: (change: SignalOf<'extensions:storage'>) => void) => () => void\n }\n /** The extensions' settings, with where each value comes from. */\n settings: {\n /** Reads the settings of a folder, or of one session when `sessionId` is set. */\n get: (cwd: string, sessionId?: string) => Promise<WireExtensionSettings>\n /** Writes one setting. */\n set: (params: SettingsSetParams) => Promise<void>\n /**\n * The settings wire of a folder may have changed: a settings page\n * (`ctx.add(SettingsPage)`) was added, replaced or removed, or the\n * extensions loaded, reloaded or went. Call `get` again.\n */\n onChange: (listener: (cwd: string) => void) => () => void\n }\n /** The commands and keymap modes extensions register. */\n commands: {\n /** Lists the commands of a folder, or of one session when `sessionId` is set. */\n list: (cwd: string, sessionId?: string) => Promise<WireExtensionCommands>\n /** Runs a command with its argument string; resolves `true` when the command ran. */\n run: (cwd: string, id: string, opts?: { args?: string, sessionId?: string }) => Promise<boolean>\n /** Turns a keymap mode on; resolves with the handle that `popMode` takes. Higher `priority` wins. */\n pushMode: (cwd: string, mode: string, opts?: { priority?: number, sessionId?: string }) => Promise<string>\n /** Turns off the keymap mode a `pushMode` handle turned on; resolves `true` when it was on. */\n popMode: (handle: string) => Promise<boolean>\n /** Every command (built-in and extension) with its effective bindings, scope and mode, and the active modes for `sessionId` (current last). */\n keymap: (cwd: string, sessionId?: string) => Promise<WireKeymap>\n /** Commands changed (`mode` absent) or a keymap mode moved (`mode` the global one on top, possibly `undefined`). */\n onChange: (listener: (cwd: string, keymap?: { mode?: string }) => void) => () => void\n }\n /** The integrations extensions declare, and their connections. */\n integrations: {\n /** Lists the integrations of a folder with their connections. */\n list: (cwd: string) => Promise<WireIntegration[]>\n /** Connects with an API key (`methodId`: the key method to use); resolves with the updated integration. */\n connectKey: (cwd: string, integrationId: string, key: string, methodId?: string) => Promise<WireIntegration>\n /** Runs a sign-in; `onStep` gets each step to show. Answer input steps with `flowInput`. */\n start: (cwd: string, integrationId: string, methodId: string, onStep: (step: IntegrationFlowStep, flowId: string) => void) => Promise<WireIntegration>\n /** Answers an input step of a sign-in (`value` undefined cancels it); resolves `false` when no step waits for it. */\n flowInput: (flowId: string, inputId: string, value: string | undefined) => Promise<boolean>\n /** Removes the connection of `account`, or all of them. */\n disconnect: (cwd: string, integrationId: string, account?: string) => Promise<void>\n /** Makes the connection of `account` the default. */\n setDefault: (cwd: string, integrationId: string, account: string) => Promise<void>\n /** Hears each change of a folder's integrations or their connections. */\n onChange: (listener: (cwd: string) => void) => () => void\n }\n /** The extensions' link handlers. */\n links: {\n /**\n * Offers a link the user opened to the folder's link handlers. `handled:\n * false`: open it the app's way. Skip it when the user holds Alt.\n */\n open: (cwd: string, link: Omit<LinkOpenParams, 'cwd'>) => Promise<{ handled: boolean }>\n }\n /** Where each item of a catalog (`kind`) comes from, for a folder. */\n catalogProvenance: (cwd: string, kind: CatalogKind) => Promise<CatalogItemProvenance[]>\n /** Sources of extensions: what one holds, and moving an installed extension to another. */\n sources: {\n /** The extensions of a source, read from their manifests by the host (`extensions.browse`). Never rejects for an unreadable source: see `error`. */\n browse: (source: string) => Promise<IpcResult<'extensions.browse'>>\n /** Installs an installed extension again from `source`, which later updates follow (`extensions.changeOrigin`). */\n changeOrigin: (params: IpcParams<'extensions.changeOrigin'>) => Promise<IpcResult<'extensions.changeOrigin'>>\n }\n}\n\n/**\n * What the client needs of a connection: an {@link IpcClient} (`zidane/ipc`)\n * or a browser `ServerClient` (`zidane/ipc/browser`).\n */\nexport interface ExtensionsTransport {\n /** Sends an IPC request and resolves with its result. */\n request: <M extends IpcMethodName>(method: M, params: IpcParams<M>) => Promise<IpcResult<M>>\n /** Hears every signal the host sends. */\n onSignal: (listener: (signal: HostSignal) => void) => () => void\n}\n\n/** An `extensions:ui` change that adds, replaces or removes a settings page (`reset`: list again). */\nfunction touchesSettingsPage(change: UiChange | { type: 'reset' }): boolean {\n if (change.type === 'reset')\n return true\n if (change.type === 'upsert')\n return change.entry.token === 'settings-page'\n return change.type === 'remove' && change.token === 'settings-page'\n}\n\nlet flowSeq = 0\nlet callSeq = 0\n\n/**\n * Wraps a connected client.\n *\n * @param client - A connected client.\n * @returns The typed extension API client.\n */\nexport function createExtensionsClient(client: ExtensionsTransport): ExtensionsClient {\n const on = <K extends HostSignal['kind']>(kind: K, fn: (signal: SignalOf<K>) => void): (() => void) =>\n client.onSignal((signal) => {\n if (signal.kind === kind)\n fn(signal as SignalOf<K>)\n })\n\n return {\n async rpc<T>(contract: string, method: string, input?: unknown, opts: { cwd?: string, signal?: AbortSignal } = {}) {\n const callId = `call-${Date.now().toString(36)}-${++callSeq}`\n const abort = (): void => void client.request('rpc.cancel', { callId }).catch(() => undefined)\n if (opts.signal?.aborted)\n throw new RpcCallError('rpc.aborted', `the call to \"${contract}.${method}\" was aborted`)\n opts.signal?.addEventListener('abort', abort, { once: true })\n try {\n const response = await client.request('rpc.call', { contract, method, callId, ...(input !== undefined ? { input } : {}), ...(opts.cwd ? { cwd: opts.cwd } : {}) })\n if (!response.ok)\n throw new RpcCallError(response.error.type, response.error.message, response.error.data)\n return response.output as T\n }\n finally {\n opts.signal?.removeEventListener('abort', abort)\n }\n },\n onRpcEvent: listener => on('rpc.event', s => listener(s.envelope)),\n entries: {\n list: cwd => client.request('extensions.entries', { cwd }),\n onChange: listener => on('extensions:entries', s => listener(s.cwd)),\n },\n ui: {\n list: cwd => client.request('extensions.ui.list', { cwd }),\n invoke: (cwd, request) => client.request('extensions.ui.invoke', { cwd, ...request }),\n onChange: listener => on('extensions:ui', s => listener(s.cwd, s.change)),\n onPanelChanged: listener => on('extensions:panel', ({ kind: _kind, ...change }) => listener(change)),\n },\n announce: info => client.request('ui.client.announce', info),\n serve: (server) => {\n const open = new Map<string, AbortController>()\n const stopDialogs = on('ui:dialog', (s) => {\n const controller = new AbortController()\n open.set(s.dialogId, controller)\n const validate = (key: string, value: unknown): Promise<string | null> => client.request('ui.dialog.validate', { dialogId: s.dialogId, key, value })\n void Promise.resolve()\n .then(() => server.dialog(s.request, { dialogId: s.dialogId, extensionId: s.extensionId, ...(s.sessionId ? { sessionId: s.sessionId } : {}), signal: controller.signal, validate }))\n .catch(() => undefined)\n .then((answer) => {\n if (open.get(s.dialogId) !== controller)\n return\n open.delete(s.dialogId)\n return client.request('ui.dialog.answer', { dialogId: s.dialogId, ...(answer !== undefined ? { answer } : {}) })\n })\n .catch(() => undefined)\n })\n const stopClose = on('ui:dialog:close', (s) => {\n open.get(s.dialogId)?.abort()\n open.delete(s.dialogId)\n })\n const stopClient = on('ui:client', (s) => {\n void Promise.resolve()\n .then(() => server.client(s.request))\n .catch(() => undefined)\n .then(result => s.requestId ? client.request('ui.client.reply', { requestId: s.requestId, result }) : undefined)\n .catch(() => undefined)\n })\n return () => {\n stopDialogs()\n stopClose()\n stopClient()\n for (const controller of open.values())\n controller.abort()\n open.clear()\n }\n },\n storage: {\n load: (cwd, loc) => client.request('extensions.storage.load', { cwd, ...loc }),\n set: (cwd, loc, area, key, value) => client.request('extensions.storage.set', { cwd, ...loc, area, key, ...(value !== undefined ? { value } : {}) }),\n onChange: listener => on('extensions:storage', listener),\n },\n settings: {\n get: (cwd, sessionId) => client.request('extensions.settings', { cwd, ...(sessionId ? { sessionId } : {}) }),\n set: params => client.request('extensions.settings.set', params),\n onChange: (listener) => {\n const a = on('extensions:ui', (s) => {\n if (touchesSettingsPage(s.change))\n listener(s.cwd)\n })\n const b = on('extensions:entries', s => listener(s.cwd))\n return () => {\n a()\n b()\n }\n },\n },\n commands: {\n list: (cwd, sessionId) => client.request('extensions.commands', { cwd, ...(sessionId ? { sessionId } : {}) }),\n run: (cwd, id, opts = {}) => client.request('extensions.command.run', { cwd, id, ...opts }),\n pushMode: (cwd, mode, opts = {}) => client.request('extensions.keymap.push', { cwd, mode, ...opts }),\n popMode: handle => client.request('extensions.keymap.pop', { handle }),\n keymap: (cwd, sessionId) => client.request('extensions.keymap.list', { cwd, ...(sessionId ? { sessionId } : {}) }),\n onChange: (listener) => {\n const a = on('extensions:commands', s => listener(s.cwd))\n const b = on('extensions:keymap', s => listener(s.cwd, s.mode !== undefined ? { mode: s.mode } : {}))\n return () => {\n a()\n b()\n }\n },\n },\n integrations: {\n list: cwd => client.request('extensions.integrations.list', { cwd }),\n connectKey: (cwd, integrationId, key, methodId) => client.request('extensions.integrations.connectKey', { cwd, integrationId, key, ...(methodId ? { methodId } : {}) }),\n start: async (cwd, integrationId, methodId, onStep) => {\n const flowId = `flow-${Date.now().toString(36)}-${++flowSeq}`\n const stop = on('extensions:integration-flow', (s) => {\n if (s.flowId === flowId)\n onStep(s.step, flowId)\n })\n try {\n return await client.request('extensions.integrations.start', { cwd, integrationId, methodId, flowId })\n }\n finally {\n stop()\n }\n },\n flowInput: (flowId, inputId, value) => client.request('extensions.integrations.flowInput', { flowId, inputId, ...(value !== undefined ? { value } : {}) }),\n disconnect: (cwd, integrationId, account) => client.request('extensions.integrations.disconnect', { cwd, integrationId, ...(account !== undefined ? { account } : {}) }),\n setDefault: (cwd, integrationId, account) => client.request('extensions.integrations.setDefault', { cwd, integrationId, account }),\n onChange: listener => on('extensions:integrations', s => listener(s.cwd)),\n },\n links: {\n open: (cwd, link) => client.request('extensions.links.open', { cwd, ...link }),\n },\n catalogProvenance: (cwd, kind) => client.request('extensions.catalogs.provenance', { cwd, kind }),\n sources: {\n browse: source => client.request('extensions.browse', { source }),\n changeOrigin: params => client.request('extensions.changeOrigin', params),\n },\n }\n}\n","/**\n * Machine join strings: how a machine finds a main server and gets a token\n * there in one paste. An operator runs `zidane server machine invite` (or an\n * admin client calls `tokens.machineInvite`) and gets a one-time code; the\n * join string is the server's client URL and that code: `wss://box.ts.net#K7Q2-9XPM`.\n *\n * The machine posts `{ code, name }` to `<http(s) of the url>/zidane/pair`\n * and gets `{ token, id, scope: 'machine', name, serverName?, hostId? }` back\n * (`src/server/pair-http.ts`). Dependency-free: the machine side loads it\n * before anything else.\n */\n\n/** The 32 symbols a code uses (`src/server/pairing.ts`): digits 2-9 and A-Z without I and O. */\nconst CODE = /^[2-9A-HJ-NP-Z]{8}$/\n\n/**\n * `<url>#<CODE>`.\n *\n * @param url - The main server's client URL (`wss://…`).\n * @param code - The join code (`XXXX-XXXX`).\n */\nexport function formatJoinString(url: string, code: string): string {\n return `${url}#${code}`\n}\n\n/**\n * `{ url, code }` from a join string (spaces around it, any case in the\n * code, the dash optional); `null` unless the url is ws:// or wss:// with a\n * host and the code is 8 symbols of the alphabet. The code comes back as\n * `XXXX-XXXX`, the url without a trailing slash.\n *\n * @param s - The join string as pasted.\n */\nexport function parseJoinString(s: string): { url: string, code: string } | null {\n if (typeof s !== 'string' || s.length > 2048)\n return null\n const text = s.trim()\n const hash = text.lastIndexOf('#')\n if (hash <= 0)\n return null\n const url = text.slice(0, hash).replace(/\\/+$/, '')\n const code = text.slice(hash + 1).toUpperCase().replace(/[\\s-]/g, '')\n if (!CODE.test(code))\n return null\n let parsed: URL\n try {\n parsed = new URL(url)\n }\n catch {\n return null\n }\n if ((parsed.protocol !== 'ws:' && parsed.protocol !== 'wss:') || !parsed.hostname || parsed.search || parsed.hash)\n return null\n return { url, code: `${code.slice(0, 4)}-${code.slice(4)}` }\n}\n\n/**\n * Where a machine redeems the code: `ws://h:1` → `http://h:1/zidane/pair`, `wss://` → `https://`.\n *\n * @param url - The main server's client URL.\n */\nexport function joinPairUrl(url: string): string {\n return `${url.replace(/^ws/, 'http').replace(/\\/+$/, '')}/zidane/pair`\n}\n","/**\n * zidane/ipc/browser — a zidane-server client that runs wherever a\n * `WebSocket` does: browsers, workers, Node, Bun. No `node:*`, no `process`:\n * the kit's server adapter (`zidane-ui/adapters`) and any web app build on it.\n * Node and Bun clients that keep saved hosts, trust a CA or share a machine\n * use `zidane/ipc/remote`, which adds those on top.\n *\n * One WebSocket, JSON-RPC 2.0, `ipc.hello` first, with the token as the\n * `zidane.bearer.<token>` subprotocol (a browser can't set headers). It:\n *\n * - speaks the version range both sides share (`IPC_MIN_PROTOCOL_VERSION`);\n * - types every call and notification against {@link IpcMethods}, and says\n * what the connection may call ({@link ServerClient.can}: the methods the\n * host offers within the token's scope, from the hello);\n * - queues calls made while it (re)connects, and fails those in flight when\n * the connection drops (the caller decides whether to retry: a call may\n * not be safe to repeat);\n * - pings the host and drops a connection that stops answering;\n * - reconnects with backoff, and stops for good on a refusal no retry can\n * fix: a bad or revoked token, an origin or transport the server refuses,\n * a protocol it doesn't share. A browser can't read why an upgrade was\n * refused, so after a failed connect it asks the server's auth check\n * (`/zidane/auth`).\n *\n * @module\n */\nimport type { HelloParams, HelloResult, HostSignal, IpcMethodName, IpcMethods, IpcParams, IpcResult, SignalMeta } from './protocol'\nimport { IPC_MIN_PROTOCOL_VERSION, IPC_PROTOCOL_VERSION, IpcErrorCode, PING_METHOD, SIGNAL_SEQ_FIELD } from './protocol'\n\n/**\n * Where a browser client asks why it can't connect, relative to the server's origin:\n * a token's scope, or the refusal an upgrade would get.\n */\nexport const SERVER_AUTH_PATH = '/zidane/auth'\n/** The path of a zidane-server's auth check, relative to its WebSocket URL's origin (same as {@link SERVER_AUTH_PATH}). */\nexport const SERVER_AUTH_CHECK_PATH = SERVER_AUTH_PATH\n/** Where a zidane-server serves workspace media (`GET`, `files.mediaTicket`), relative to its origin. */\nexport const SERVER_MEDIA_PATH = '/zidane/media'\n/** Where a zidane-server takes a browser client's MCP sign-in back (`auth.oauth.begin`), relative to its origin. */\nexport const SERVER_OAUTH_CALLBACK_PATH = '/zidane/oauth/callback'\n\n/**\n * Why a server refused this client for good: `token` (unknown or revoked), the server's\n * admission refusals (`origin` not allowed, `insecure-transport`, `untrusted-proxy`, a\n * `scope` it may not connect with), or a `protocol` the two don't share.\n */\nexport type ServerRefusal = 'token' | 'origin' | 'insecure-transport' | 'untrusted-proxy' | 'scope' | 'protocol'\n\n/** Where a {@link ServerClient}'s connection is. */\nexport type ServerClientState\n = | { status: 'connecting', attempt: number }\n | { status: 'open', hello: HelloResult }\n /** The last attempt failed; the next one starts in `inMs`. */\n | { status: 'retrying', attempt: number, inMs: number, error: string }\n /** No retry can fix it: calls fail until a new client (another token, an upgrade). */\n | { status: 'refused', reason: ServerRefusal, message: string }\n | { status: 'closed' }\n\n/** Options for {@link createServerClient}. */\nexport interface ServerClientOptions {\n /** `ws://` or `wss://` URL of the server. */\n url: string\n /** A client token (`zidane server token create --scope chat`). Absent: a server without auth. */\n token?: string\n /** Reported in the server's logs and audit (default `'web'`). */\n appVersion?: string\n /** WebSocket constructor. Default: the global one. */\n WebSocket?: typeof WebSocket\n /** `fetch`, for the auth check after a failed connect. Default: the global one. */\n fetch?: typeof fetch\n /** First reconnect delay and its ceiling, in ms (default 500 doubling to 15 000). `false`: never reconnect. */\n reconnect?: { initialMs?: number, maxMs?: number } | false\n /** Ping interval in ms; a ping unanswered by the next one drops the connection (default 20 000; 0: off). */\n heartbeatMs?: number\n /** How long an attempt may take to open and finish its handshake before it is dropped and retried, in ms (default 10 000). */\n connectTimeoutMs?: number\n /** Called on every state change. */\n onState?: (state: ServerClientState) => void\n}\n\n/** A call the server answered with an error: its JSON-RPC `code` and `data`. */\nexport class ServerCallError extends Error {\n /** The JSON-RPC error code ({@link IpcErrorCode} names zidane's own). */\n readonly code: number\n /** The error's data, when it had some (a `Forbidden` refusal's `required` scope). */\n readonly data?: unknown\n /**\n * @param message - The server's message.\n * @param code - The JSON-RPC error code.\n * @param data - The error's data.\n */\n constructor(message: string, code: number, data?: unknown) {\n super(message)\n this.name = 'ServerCallError'\n this.code = code\n this.data = data\n }\n}\n\n/** A call that couldn't be answered: the connection dropped, or the client was refused or closed. */\nexport class ServerConnectionError extends Error {\n /** The client's state when the call failed: `refused` names why, for good. */\n readonly state: ServerClientState\n /**\n * @param message - What happened.\n * @param state - The client's state when the call failed.\n */\n constructor(message: string, state: ServerClientState) {\n super(message)\n this.name = 'ServerConnectionError'\n this.state = state\n }\n}\n\n/** A connection to a zidane-server: typed calls, signals and its state. */\nexport interface ServerClient {\n /** The connection's state now. */\n state: () => ServerClientState\n /** Called on every state change; returns its unsubscribe. */\n onState: (listener: (state: ServerClientState) => void) => () => void\n /** Resolves with the first hello; rejects when the client is refused or closed before it. */\n ready: Promise<HelloResult>\n /** The current connection's hello, `null` while not open. */\n hello: () => HelloResult | null\n /**\n * Whether this connection may call `method`: the host offers it and the token reaches it.\n * `true` against a host that predates the list. `false` while not open.\n */\n can: (method: IpcMethodName) => boolean\n /** Calls a method. Waits while (re)connecting; fails when the connection drops mid-call. */\n call: <M extends IpcMethodName>(method: M, params: IpcParams<M>) => Promise<IpcResult<M>>\n /** Sends a notification (no answer). Dropped while not open. */\n notify: <M extends IpcMethodName>(method: M, params: IpcParams<M>) => void\n /** Called with every signal the host fans out, and its position in its session; returns its unsubscribe. */\n onSignal: (listener: (signal: HostSignal, meta?: SignalMeta) => void) => () => void\n /**\n * Called after every handshake, `reconnected` after the first: re-read or resume what the\n * page shows. Returns its unsubscribe.\n */\n onOpen: (listener: (hello: HelloResult, reconnected: boolean) => void) => () => void\n /** Closes the connection and stops reconnecting. */\n close: () => void\n}\n\ninterface Pending { resolve: (value: unknown) => void, reject: (error: Error) => void }\ninterface RpcMessage { id?: number | string, result?: unknown, error?: { code: number, message: string, data?: unknown }, method?: string, params?: unknown }\n\nconst REFUSALS = new Set<ServerRefusal>(['origin', 'insecure-transport', 'untrusted-proxy', 'scope'])\n\n/** `ws(s)://host/path` → `http(s)://host/zidane/auth`. */\nfunction authCheckUrl(url: string): string {\n const u = new URL(url)\n u.protocol = u.protocol === 'wss:' ? 'https:' : 'http:'\n u.pathname = SERVER_AUTH_CHECK_PATH\n u.search = ''\n return u.toString()\n}\n\n/** After a connect that never reached the hello: a refusal to stop on, or `null` to retry. */\nasync function classifyRefusal(doFetch: typeof fetch | undefined, url: string, token: string | undefined): Promise<{ reason: ServerRefusal, message: string } | null> {\n if (!doFetch)\n return null\n try {\n const response = await doFetch(authCheckUrl(url), token ? { headers: { authorization: `Bearer ${token}` } } : {})\n if (response.status === 401)\n return { reason: 'token', message: 'The server does not accept this token (unknown or revoked).' }\n if (response.status === 403) {\n const reason = response.headers.get('x-zidane-refusal') as ServerRefusal | null\n return reason && REFUSALS.has(reason)\n ? { reason, message: `The server refuses this connection (${reason}).` }\n : { reason: 'origin', message: 'The server refuses this connection: check that it allows this origin.' }\n }\n return null\n }\n catch {\n // Unreachable, or a cross-origin refusal the page can't read: retry.\n return null\n }\n}\n\n/**\n * Routes one incoming frame: a response settles its call, a signal reaches the listeners, and\n * a request from the host (a liveness ping) is answered.\n */\nfunction routeMessage(\n data: unknown,\n pending: Map<number, Pending>,\n signalListeners: Set<(signal: HostSignal, meta?: SignalMeta) => void>,\n reply: (frame: object) => void,\n): void {\n let message: RpcMessage\n try {\n message = JSON.parse(String(data)) as RpcMessage\n }\n catch {\n return\n }\n if (typeof message.id === 'number' && pending.has(message.id) && message.method === undefined) {\n const p = pending.get(message.id)!\n pending.delete(message.id)\n if (message.error)\n p.reject(new ServerCallError(message.error.message, message.error.code, message.error.data))\n else\n p.resolve(message.result)\n return\n }\n if (message.method === 'ipc.signal' && message.params && typeof message.params === 'object') {\n const { [SIGNAL_SEQ_FIELD]: seq, ...signal } = message.params as Record<string, unknown>\n const meta = typeof seq === 'number' ? { seq } : undefined\n for (const listener of signalListeners) listener(signal as unknown as HostSignal, meta)\n return\n }\n if (message.method !== undefined && message.id !== undefined) {\n reply(message.method === PING_METHOD\n ? { jsonrpc: '2.0', id: message.id, result: {} }\n : { jsonrpc: '2.0', id: message.id, error: { code: -32601, message: `Unknown method \"${message.method}\".` } })\n }\n}\n\n/** Subscribes to a listener set; the returned function unsubscribes. */\nfunction listen<L>(set: Set<L>): (listener: L) => () => void {\n return (listener) => {\n set.add(listener)\n return () => {\n set.delete(listener)\n }\n }\n}\n\n/** Pings every `ms`; a ping still unanswered at the next tick closes `ws`. Returns its stop. */\nfunction heartbeat(ws: WebSocket, ms: number, ping: () => Promise<unknown>): () => void {\n if (ms <= 0)\n return () => undefined\n let waiting = false\n const timer = setInterval(() => {\n if (waiting) {\n ws.close(4000, 'heartbeat timeout')\n return\n }\n waiting = true\n ping().then(() => { waiting = false }, () => undefined)\n }, ms)\n return () => clearInterval(timer)\n}\n\n/**\n * Creates a client for a zidane-server and starts connecting. See the module docs for what it\n * handles; {@link ServerClient} for what it offers.\n *\n * @param options - The server's `url`, the `token`, and optional transport and retry settings.\n * @returns The client, connecting.\n * @example\n * ```ts\n * import { createServerClient } from 'zidane/ipc/browser'\n *\n * const server = createServerClient({ url: 'wss://zidane.example.com', token })\n * const hello = await server.ready\n * if (server.can('sessions.list'))\n * console.log(await server.call('sessions.list', {}), hello.scope)\n * ```\n */\nexport function createServerClient(options: ServerClientOptions): ServerClient {\n const WS = options.WebSocket ?? globalThis.WebSocket\n const doFetch = options.fetch ?? (typeof globalThis.fetch === 'function' ? globalThis.fetch.bind(globalThis) : undefined)\n const reconnect = options.reconnect === false ? null : { initialMs: options.reconnect?.initialMs ?? 500, maxMs: options.reconnect?.maxMs ?? 15_000 }\n const heartbeatMs = options.heartbeatMs ?? 20_000\n const connectTimeoutMs = options.connectTimeoutMs ?? 10_000\n const stateListeners = new Set<(state: ServerClientState) => void>()\n const signalListeners = new Set<(signal: HostSignal, meta?: SignalMeta) => void>()\n const openListeners = new Set<(hello: HelloResult, reconnected: boolean) => void>()\n const pending = new Map<number, Pending>()\n /** Calls made while not open, sent on the next handshake. */\n const queued: { method: string, params: unknown, pending: Pending }[] = []\n let state: ServerClientState = { status: 'connecting', attempt: 1 }\n let socket: WebSocket | null = null\n let current: HelloResult | null = null\n let nextId = 1\n let attempt = 1\n let opens = 0\n let retryTimer: ReturnType<typeof setTimeout> | undefined\n let connectTimer: ReturnType<typeof setTimeout> | undefined\n let stopHeartbeat = (): void => undefined\n let resolveReady!: (hello: HelloResult) => void\n let rejectReady!: (error: Error) => void\n const ready = new Promise<HelloResult>((resolve, reject) => {\n resolveReady = resolve\n rejectReady = reject\n })\n // A page that never awaits `ready` must not see an unhandled rejection.\n ready.catch(() => undefined)\n\n const setState = (next: ServerClientState): void => {\n state = next\n for (const listener of stateListeners) listener(next)\n options.onState?.(next)\n }\n\n const final = (): boolean => state.status === 'refused' || state.status === 'closed'\n\n const failAll = (error: Error): void => {\n for (const p of pending.values()) p.reject(error)\n pending.clear()\n }\n const failQueued = (error: Error): void => {\n for (const q of queued.splice(0)) q.pending.reject(error)\n }\n\n const send = (method: string, params: unknown, p?: Pending): void => {\n if (!socket || socket.readyState !== WS.OPEN) {\n p?.reject(new ServerConnectionError('Not connected.', state))\n return\n }\n if (!p) {\n socket.send(JSON.stringify({ jsonrpc: '2.0', method, params }))\n return\n }\n const id = nextId++\n pending.set(id, p)\n socket.send(JSON.stringify({ jsonrpc: '2.0', id, method, params }))\n }\n\n const request = (method: string, params: unknown): Promise<unknown> =>\n new Promise((resolve, reject) => send(method, params, { resolve, reject }))\n\n const onMessage = (event: MessageEvent): void =>\n routeMessage(event.data, pending, signalListeners, frame => socket?.send(JSON.stringify(frame)))\n\n const refuse = (reason: ServerRefusal, message: string): void => {\n const error = new ServerConnectionError(message, { status: 'refused', reason, message })\n setState({ status: 'refused', reason, message })\n failAll(error)\n failQueued(error)\n rejectReady(error)\n }\n\n const scheduleRetry = (error: string): void => {\n if (final())\n return\n if (!reconnect) {\n setState({ status: 'closed' })\n const closed = new ServerConnectionError(error, state)\n failQueued(closed)\n rejectReady(closed)\n return\n }\n const inMs = Math.min(reconnect.maxMs, reconnect.initialMs * 2 ** (attempt - 1))\n setState({ status: 'retrying', attempt, inMs, error })\n retryTimer = setTimeout(() => {\n attempt += 1\n connect()\n }, inMs)\n }\n\n const handshake = async (ws: WebSocket): Promise<void> => {\n const params: HelloParams = {\n protocolVersion: IPC_PROTOCOL_VERSION,\n minProtocolVersion: IPC_MIN_PROTOCOL_VERSION,\n appVersion: options.appVersion ?? 'web',\n pid: 0,\n buildId: 'unknown',\n }\n let hello: HelloResult\n try {\n hello = await request('ipc.hello', params) as HelloResult\n }\n catch (err) {\n if (err instanceof ServerCallError && err.code === IpcErrorCode.VersionMismatch)\n refuse('protocol', err.message)\n // Any other failed handshake ends the attempt; the close decides whether to retry.\n ws.close()\n return\n }\n clearTimeout(connectTimer)\n current = hello\n attempt = 1\n const reconnected = opens > 0\n opens += 1\n setState({ status: 'open', hello })\n stopHeartbeat = heartbeat(ws, heartbeatMs, () => request(PING_METHOD, {}))\n resolveReady(hello)\n for (const q of queued.splice(0)) send(q.method, q.params, q.pending)\n for (const listener of openListeners) listener(hello, reconnected)\n }\n\n function connect(): void {\n if (final())\n return\n setState({ status: 'connecting', attempt })\n const protocols = ['zidane', ...(options.token ? [`zidane.bearer.${options.token}`] : [])]\n let ws: WebSocket\n try {\n ws = new WS(options.url, protocols)\n }\n catch (err) {\n refuse('origin', `Cannot open ${options.url}: ${err instanceof Error ? err.message : String(err)}`)\n return\n }\n socket = ws\n let opened = false\n // An attempt that neither opens nor finishes its handshake in time (a wedged proxy, a host\n // that never answers the hello) is dropped like a failed one.\n clearTimeout(connectTimer)\n connectTimer = setTimeout(() => ws.close(), connectTimeoutMs)\n ws.addEventListener('message', onMessage)\n ws.addEventListener('open', () => {\n opened = true\n void handshake(ws)\n })\n ws.addEventListener('close', (event) => {\n if (socket !== ws)\n return\n socket = null\n clearTimeout(connectTimer)\n stopHeartbeat()\n const wasOpen = current !== null\n current = null\n failAll(new ServerConnectionError('The connection to the server closed.', state))\n if (final())\n return\n if (opened && wasOpen) {\n scheduleRetry(`connection closed (${event.code})`)\n return\n }\n void classifyRefusal(doFetch, options.url, options.token).then((refusal) => {\n if (refusal)\n refuse(refusal.reason, refusal.message)\n else\n scheduleRetry(`could not connect (${event.code})`)\n })\n })\n }\n\n connect()\n\n return {\n state: () => state,\n onState: listen(stateListeners),\n ready,\n hello: () => current,\n can: method => current !== null && (current.methods === undefined || current.methods.includes(method)),\n call: <M extends IpcMethodName>(method: M, params: IpcParams<M>) =>\n new Promise<IpcResult<M>>((resolve, reject) => {\n const p: Pending = { resolve: value => resolve(value as IpcResult<M>), reject }\n if (final())\n reject(new ServerConnectionError(state.status === 'refused' ? state.message : 'The client is closed.', state))\n else if (current && socket?.readyState === WS.OPEN)\n send(method, params, p)\n else\n queued.push({ method, params, pending: p })\n }),\n notify: <M extends IpcMethodName>(method: M, params: IpcParams<M>) => {\n if (current)\n send(method, params)\n },\n onSignal: listen(signalListeners),\n onOpen: listen(openListeners),\n close: () => {\n if (state.status === 'closed')\n return\n clearTimeout(retryTimer)\n clearTimeout(connectTimer)\n stopHeartbeat()\n setState({ status: 'closed' })\n const closed = new ServerConnectionError('The client is closed.', state)\n failAll(closed)\n failQueued(closed)\n rejectReady(closed)\n socket?.close()\n socket = null\n },\n }\n}\n\nexport type { HelloResult, HostSignal, IpcMethodName, IpcMethods, IpcParams, IpcResult, SignalMeta }\nexport { pairBrowser, type PairBrowserOptions, type PairedBrowser, SERVER_PAIR_PATH, ServerPairError, type ServerPairFailure } from './browser-pair'\nexport { SERVER_EXTENSIONS_UI_PATH, SERVER_EXTENSIONS_WEBVIEW_PATH } from './extension-paths'\nexport { createExtensionsClient, type ExtensionsClient, type ExtensionsTransport, type ExtensionsUiServer } from './extensions-client'\nexport { formatJoinString, parseJoinString } from './machine/join'\nexport { type ExtensionInstallErrorData, extensionInstallErrorData, IPC_MIN_PROTOCOL_VERSION, IPC_PROTOCOL_VERSION, IpcErrorCode } from './protocol'\nexport { CLIENT_SCOPES, type ClientScope, METHOD_SCOPES, methodScope, scopeAllows } from './scopes'\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"contexts-C72b0mMa.js","names":[],"sources":["../src/contexts/entries.ts","../src/contexts/process-background.ts","../src/contexts/process-exec.ts","../src/contexts/git-ls-files-local.ts","../src/contexts/glob.ts","../src/contexts/process-files.ts","../src/contexts/ansi-strip.ts","../src/contexts/process-shell.ts","../src/contexts/process-stream.ts","../src/contexts/process-tasks.ts","../src/contexts/process.ts"],"sourcesContent":["/**\n * The two ways to run an `EntryPort` (`./types`): node's fs (the process\n * context, a desktop app's local folders, a machine serving its host) and\n * POSIX commands through a context's `exec` (docker, e2b, daytona, a machine\n * too old to answer the `fs.*` entry calls). `entryPortOf` picks the\n * context's own port, else the commands. The rules every action follows\n * (names, conflicts, folders made in between) are not here: they are\n * `createEntryOps` (`chat/workspace/entries.ts`), written once over a port.\n */\nimport type { EntryKind, EntryPort, ExecutionContext, ExecutionHandle } from './types'\nimport { Buffer } from 'node:buffer'\nimport { cp, lstat, mkdir, readdir, rename, rm, writeFile } from 'node:fs/promises'\nimport { join, relative } from 'node:path'\n\n/** Folders an empty-folder scan never walks into (what a code browser never lists). */\nconst SKIPPED_DIRS = new Set(['.git', 'node_modules'])\n\n/** POSIX single quotes. */\nfunction q(value: string): string {\n return `'${value.replace(/'/g, `'\\\\''`)}'`\n}\n\nconst isMissing = (error: unknown): boolean => (error as NodeJS.ErrnoException)?.code === 'ENOENT'\n\n/** Options of {@link nodeEntryPort}. */\nexport interface NodeEntryPortOptions {\n /** A path as the caller names it → the absolute path to act on; throws when it is out of bounds. */\n resolve: (path: string) => Promise<string>\n /** Same, for the entry itself, its own link never followed (stat, move, remove, a target to create). Default: `resolve`. */\n entry?: (path: string) => Promise<string>\n /** Throws when the caller may not change `absolute` (a sandbox's writable roots). Default: anything goes. */\n writable?: (absolute: string, path: string) => Promise<void>\n /** Removes `absolute` recoverably (the system trash). Default: removed for good. */\n trash?: (absolute: string) => Promise<void>\n}\n\n/**\n * An {@link EntryPort} on this machine's filesystem.\n *\n * @param options - How paths resolve, what may change, and where removed entries go.\n */\nexport function nodeEntryPort(options: NodeEntryPortOptions): EntryPort {\n const { resolve: at, entry = at, writable = async () => {}, trash } = options\n const changing = async (path: string): Promise<string> => {\n const absolute = await entry(path)\n await writable(absolute, path)\n return absolute\n }\n const absent = async (absolute: string): Promise<void> => {\n if (await lstat(absolute).then(() => true, error => (isMissing(error) ? false : Promise.reject(error))))\n throw Object.assign(new Error(`${absolute} already exists.`), { code: 'EEXIST' })\n }\n return {\n async stat(path) {\n try {\n return (await lstat(await entry(path))).isDirectory() ? 'dir' : 'file'\n }\n catch (error) {\n if (isMissing(error))\n return null\n throw error\n }\n },\n list: async path => readdir(await at(path)),\n async mkdir(path) {\n await mkdir(await changing(path), { recursive: true })\n },\n async write(path, bytes) {\n // `wx`: a file that appeared since the check is refused, not replaced.\n await writeFile(await changing(path), bytes, { flag: 'wx' })\n },\n async move(from, to) {\n const source = await changing(from)\n const target = await changing(to)\n await absent(target)\n try {\n await rename(source, target)\n }\n catch (error) {\n // Another volume under the same root (a mount): copy, then remove.\n if ((error as NodeJS.ErrnoException).code !== 'EXDEV')\n throw error\n await cp(source, target, { recursive: true, errorOnExist: true, force: false, verbatimSymlinks: true })\n await rm(source, { recursive: true })\n }\n },\n async copy(from, to) {\n const source = await at(from)\n const target = await changing(to)\n await absent(target)\n await cp(source, target, { recursive: true, errorOnExist: true, force: false, verbatimSymlinks: true })\n },\n async remove(path) {\n const absolute = await changing(path)\n if (trash)\n await trash(absolute)\n else\n await rm(absolute, { recursive: true })\n },\n async emptyDirs(path, limit) {\n const root = await at(path)\n const found: string[] = []\n const walk = async (dir: string): Promise<void> => {\n if (found.length >= limit)\n return\n const entries = await readdir(dir, { withFileTypes: true }).catch(() => null)\n if (!entries)\n return\n if (entries.length === 0 && dir !== root) {\n found.push(relative(root, dir))\n return\n }\n for (const entry of entries) {\n if (entry.isDirectory() && !SKIPPED_DIRS.has(entry.name))\n await walk(join(dir, entry.name))\n }\n }\n await walk(root)\n return found\n },\n }\n}\n\n/**\n * An {@link EntryPort} over a context's `exec` (POSIX `sh`), its files written with the context's `writeFile`.\n *\n * @param context - The context: its commands and its file write.\n * @param handle - The handle to run them in.\n */\nexport function execEntryPort(context: Pick<ExecutionContext, 'exec' | 'writeFile'>, handle: ExecutionHandle): EntryPort {\n const run = async (command: string): Promise<string> => {\n const result = await context.exec(handle, command, { timeout: 120 })\n if (result.exitCode !== 0)\n throw new Error(result.stderr.trim() || `\\`${command}\\` exited with ${result.exitCode}.`)\n return result.stdout\n }\n // Refuses a target that exists (a link included) before acting: `mv` and `cp` would replace or nest into it.\n const absent = (path: string): string => `if [ -e ${q(path)} ] || [ -L ${q(path)} ]; then printf '%s already exists.\\\\n' ${q(path)} >&2; exit 17; fi`\n return {\n async stat(path) {\n const out = await run(`if [ -L ${q(path)} ] || [ -f ${q(path)} ]; then echo file; elif [ -d ${q(path)} ]; then echo dir; elif [ -e ${q(path)} ]; then echo file; else echo none; fi`)\n const kind = out.trim()\n return kind === 'none' ? null : kind as EntryKind\n },\n async list(path) {\n // A glob loop, not `ls`: names with spaces or newlines survive, NUL-separated.\n const out = await run(`cd ${q(path)} && for f in * .[!.]* ..?*; do if [ -e \"$f\" ] || [ -L \"$f\" ]; then printf '%s\\\\0' \"$f\"; fi; done`)\n return out.split('\\0').filter(Boolean)\n },\n async mkdir(path) {\n await run(`mkdir -p -- ${q(path)}`)\n },\n async write(path, bytes) {\n await run(absent(path))\n await context.writeFile(handle, path, Buffer.from(bytes.buffer, bytes.byteOffset, bytes.byteLength))\n },\n async move(from, to) {\n await run(`${absent(to)}; mv -- ${q(from)} ${q(to)}`)\n },\n async copy(from, to) {\n await run(`${absent(to)}; cp -RP -- ${q(from)} ${q(to)}`)\n },\n async remove(path) {\n await run(`rm -rf -- ${q(path)}`)\n },\n async emptyDirs(path, limit) {\n const out = await run(`cd ${q(path)} && find . \\\\( -name .git -o -name node_modules \\\\) -prune -o -type d -empty -print | head -n ${Math.max(0, Math.floor(limit))}`)\n return out.split('\\n').map(line => line.replace(/^\\.\\//, '')).filter(line => line && line !== '.')\n },\n }\n}\n\n/**\n * The context's own entry port for `handle`, else one over its commands.\n *\n * @param context - The execution context.\n * @param handle - The handle the operations run in.\n */\nexport function entryPortOf(context: ExecutionContext, handle: ExecutionHandle): EntryPort {\n const own = context.entries?.(handle)\n if (own)\n return own\n if (!context.capabilities.shell)\n throw new Error(`The ${context.type} context can't create, move or remove files.`)\n return execEntryPort(context, handle)\n}\n","/**\n * `execBackground` (background task spawn + settle) of the in-process\n * execution context. Internal module.\n */\n\nimport type { Buffer } from 'node:buffer'\nimport type { WriteStream } from 'node:fs'\nimport type { ProcessShell } from './process-shell'\nimport type { ProcessContextState, TaskState } from './process-state'\nimport type { BackgroundTerminalOptions, ExecutionContext, ExecutionHandle, TaskExitInfo, TaskHandle, TaskStallInfo } from './types'\nimport { constants, createWriteStream, openSync } from 'node:fs'\nimport { mkdir } from 'node:fs/promises'\nimport { resolve } from 'node:path'\nimport { hasLocalPty } from './local-terminal'\nimport { assertSafeTaskId, EXIT_PIPE_DRAIN_GRACE_MS, loadSpawn, stateToTaskExitInfo, SUPPORTS_PROCESS_GROUPS, TERMINAL_TASK_ENV } from './process-state'\n\nconst NO_FOLLOW = constants.O_NOFOLLOW ?? 0\n\n/**\n * Finished tasks a context keeps for `listBackground` / `waitBackground` /\n * `killBackground` (and `wait_task`'s \"no such task\" check): past this, the\n * oldest finished go first. Running tasks are never dropped.\n */\nexport const MAX_FINISHED_TASKS = 256\n\n/**\n * Tasks whose exit callbacks already ran. `settled` flips before the output\n * stream flushes, so it alone would let a task be dropped while its waiters\n * are still to be told.\n */\nconst exitNotified = new WeakSet<TaskState>()\n\n/**\n * After a task's exit callbacks fired (once, never again): let go of the\n * owner's closures (its hook bus), and drop the oldest finished tasks past\n * {@link MAX_FINISHED_TASKS}. `tasks` is in finish order (`settle`\n * re-inserts), running tasks still in spawn order among them.\n */\nfunction releaseFinishedTask(tasks: Map<string, TaskState>, settled: TaskState): void {\n settled.onExit = undefined\n settled.onStall = undefined\n exitNotified.add(settled)\n let finished = 0\n for (const state of tasks.values()) {\n if (exitNotified.has(state))\n finished++\n }\n for (const [taskId, state] of tasks) {\n if (finished <= MAX_FINISHED_TASKS)\n break\n if (!exitNotified.has(state))\n continue\n tasks.delete(taskId)\n finished--\n }\n}\n\n/**\n * The log's fd: a new file (exclusive), never through a symlink planted at\n * its path. A name collision keeps the old append behavior on the existing\n * regular file (still not following a link), as the comment at the call says.\n */\nfunction openTaskLog(path: string): number {\n const write = constants.O_WRONLY | constants.O_APPEND | NO_FOLLOW\n try {\n return openSync(path, write | constants.O_CREAT | constants.O_EXCL, 0o600)\n }\n catch (err) {\n if ((err as NodeJS.ErrnoException).code !== 'EEXIST')\n throw err\n return openSync(path, write)\n }\n}\n\n/**\n * Same pipe-hostage hazard as foreground `exec`: a grandchild that inherited\n * the pipes blocks `close` forever, leaving the task `running` (and any\n * waiter parked) long after the command exited. Settle after a short drain\n * grace. Not armed once `close` already settled the task; `settle` clears it\n * when `close` comes first.\n */\nfunction settleAfterExitGrace(child: NonNullable<TaskState['child']>, state: TaskState, settleNow: () => void): NodeJS.Timeout | undefined {\n if (state.settled)\n return undefined\n const timer = setTimeout(() => {\n if (state.settled)\n return\n child.stdout?.destroy()\n child.stderr?.destroy()\n settleNow()\n }, EXIT_PIPE_DRAIN_GRACE_MS)\n timer.unref?.()\n return timer\n}\n\nexport function processBackgroundMethods(s: ProcessContextState, sh: ProcessShell): Required<Pick<ExecutionContext, 'execBackground'>> {\n const { baseEnv, defaultEnv, tasks, contextTimestamp, registerExitHandler, trackSession } = s\n const { shellCommand, isolationBlocker, spawnTerminalTask } = sh\n\n return {\n async execBackground(\n handle: ExecutionHandle,\n command: string,\n options: {\n cwd?: string\n env?: Record<string, string>\n outputDir: string\n onExit?: (info: TaskExitInfo) => void\n maxOutputBytes?: number\n stallTimeoutMs?: number\n onStall?: (info: TaskStallInfo) => void\n terminal?: BackgroundTerminalOptions\n },\n ): Promise<TaskHandle> {\n const cwd = options.cwd ? resolve(handle.cwd, options.cwd) : handle.cwd\n\n // Resolve the subprocess primitive up front (see `loadSpawn`) so a runtime\n // without `node:child_process` fails BEFORE we allocate the log dir +\n // output stream — no orphaned fd / log file on an unsupported host.\n const spawnChild = await loadSpawn()\n const blocked = isolationBlocker()\n if (blocked)\n throw new Error(blocked.stderr)\n\n await mkdir(options.outputDir, { recursive: true })\n\n // Mint id + path. The id is sequential per context (model-facing,\n // short, ergonomic for `shell_kill`). The log FILENAME embeds the\n // context's start timestamp so two contexts sharing an `outputDir`\n // (TUI restart on the same session, concurrent zidane instances,\n // …) never resolve to the same file — we open with `flags: 'a'`\n // and a name collision would interleave their output. Path\n // validation is defensive — we mint our own ids so it never trips\n // today, but it pins the invariant for forks / third parties.\n const taskId = `bash_${++s.taskCounter}`\n assertSafeTaskId(taskId)\n const outputPath = resolve(options.outputDir, `${taskId}.${contextTimestamp}.log`)\n\n // Install the orphan reaper on first task. See `exitHandler`'s\n // JSDoc for the kill-on-shutdown rationale.\n registerExitHandler()\n\n // Open the output file. The timestamped path is unique per context\n // so a brand-new file is the expected outcome; `flags: 'a'` is kept\n // as the safe default (preserves bytes if the path collides for any\n // reason — same-millisecond context creation, manual pre-population,\n // etc.) rather than blindly truncating. Streams are opened BEFORE\n // the spawn to avoid a race where the child writes before the stream\n // is ready — `child_process` buffers stdio until the consumer\n // attaches, but the FS handle has to exist either way for our pipe.\n const outputStream: WriteStream = createWriteStream(outputPath, { fd: openTaskLog(outputPath) })\n // Surface FS errors (ENOSPC, EACCES on a remounted FS, etc.)\n // under ZIDANE_DEBUG instead of crashing the host via an\n // unhandled 'error' event. Without a listener Node escalates\n // any stream-level error to an uncaughtException and the whole\n // process exits — the model and the user would lose every\n // unrelated in-flight piece of work to one bad task's disk\n // hiccup. Swallow + log is the safer default for a fire-and-\n // forget log writer; the task's exit code still reports.\n outputStream.on('error', (err) => {\n if (process.env.ZIDANE_DEBUG)\n process.stderr.write(`[zidane/contexts] task ${taskId} log stream error: ${err.message}\\n`)\n })\n\n // Spawn as a NEW process group leader so we can kill the whole\n // subtree on demand. Same primitive `exec` uses for foreground\n // shells — see the long comment in that method for the\n // process-group rationale.\n const shell = shellCommand(command)\n // Terminal mode: same registry, a PTY instead of pipes. The log gets\n // plain text (control sequences stripped, redraws collapsed); the raw\n // bytes go to whoever shows the terminal.\n const tty = options.terminal && hasLocalPty() ? options.terminal : undefined\n const child = tty\n ? spawnTerminalTask([shell.file, ...shell.args], cwd, { ...TERMINAL_TASK_ENV, ...options.env }, tty)\n : spawnChild(shell.file, shell.args, {\n cwd,\n env: { ...baseEnv, ...defaultEnv, ...options.env },\n stdio: ['ignore', 'pipe', 'pipe'],\n detached: SUPPORTS_PROCESS_GROUPS,\n })\n\n const state: TaskState = {\n taskId,\n handleId: handle.id,\n pid: child.pid ?? -1,\n command,\n cwd,\n startedAt: Date.now(),\n outputPath,\n outputStream,\n child,\n status: 'running',\n bytesWritten: 0,\n settled: false,\n onExit: options.onExit,\n onStall: options.onStall,\n exitWatchers: [],\n }\n tasks.set(taskId, state)\n const untrack = trackSession(child.pid)\n\n // Output cap (optional). Beyond the cap the process keeps\n // running — head-priority retention: bytes already on disk stay,\n // subsequent bytes are counted but dropped, and a structured\n // truncation marker is appended at settle so the model can\n // pattern-match the loss. Killing on overflow (what the\n // foreground `exec` does) would be wrong here: long-running\n // servers legitimately log forever.\n const maxOutputBytes = typeof options.maxOutputBytes === 'number' && options.maxOutputBytes > 0\n ? options.maxOutputBytes\n : undefined\n let droppedBytes = 0\n // Latched on the first overflowing chunk. Without it, a codepoint-\n // boundary backoff (below) leaves a few bytes of \"room\" that later\n // chunks would dribble into — appending disjoint fragments from\n // much-later output right after the cut point.\n let capExhausted = false\n\n // Stall watchdog (optional). One-shot per quiet period: fires\n // `onStall` after `stallTimeoutMs` of no output, then stays quiet\n // until fresh output re-arms it. `unref()` so a pending timer\n // never holds the host process open.\n const stallTimeoutMs = typeof options.stallTimeoutMs === 'number' && options.stallTimeoutMs > 0\n ? options.stallTimeoutMs\n : undefined\n let stallTimer: NodeJS.Timeout | undefined\n let lastOutputAt = Date.now()\n const armStallTimer = (): void => {\n // Read through `state` (not a captured option) so a rebind via\n // `reassignBackgroundTasks` redirects later stalls too.\n if (!stallTimeoutMs || !state.onStall)\n return\n if (stallTimer)\n clearTimeout(stallTimer)\n stallTimer = setTimeout(() => {\n stallTimer = undefined\n if (state.settled)\n return\n try {\n state.onStall?.({\n taskId,\n command,\n outputPath,\n stalledForMs: Date.now() - lastOutputAt,\n bytesWritten: state.bytesWritten,\n })\n }\n catch (err) {\n if (process.env.ZIDANE_DEBUG)\n process.stderr.write(`[zidane/contexts] task ${taskId} onStall threw: ${err instanceof Error ? err.message : String(err)}\\n`)\n }\n }, stallTimeoutMs)\n stallTimer.unref?.()\n }\n const clearStallTimer = (): void => {\n if (stallTimer) {\n clearTimeout(stallTimer)\n stallTimer = undefined\n }\n }\n armStallTimer()\n\n // Pipe both streams into the same file. Order between stdout and\n // stderr is preserved per-stream; cross-stream ordering depends on\n // Node's event loop — acceptable interleaving for log-shaped\n // output. Tracked-bytes is updated on every chunk for the\n // listBackground UX (counted even past the cap, so the UX shows\n // the task's TRUE output volume).\n const appendChunk = (chunk: Buffer): void => {\n state.bytesWritten += chunk.length\n lastOutputAt = Date.now()\n armStallTimer()\n if (maxOutputBytes !== undefined) {\n const onDisk = state.bytesWritten - droppedBytes - chunk.length\n if (capExhausted || onDisk >= maxOutputBytes) {\n capExhausted = true\n droppedBytes += chunk.length\n return\n }\n const room = maxOutputBytes - onDisk\n if (chunk.length > room) {\n capExhausted = true\n // Cut on a UTF-8 codepoint boundary, same as the foreground\n // exec cap: back off while the byte after the cut is a\n // continuation byte (0b10xxxxxx) so the log never ends in a\n // mangled half-codepoint right before the truncation marker.\n let end = room\n while (end > 0 && (chunk[end] & 0xC0) === 0x80)\n end--\n droppedBytes += chunk.length - end\n if (end > 0)\n outputStream.write(chunk.subarray(0, end))\n return\n }\n }\n outputStream.write(chunk)\n }\n child.stdout?.on('data', chunk => appendChunk(chunk as Buffer))\n child.stderr?.on('data', chunk => appendChunk(chunk as Buffer))\n\n // Settle path — at-most-once via `settled` flag (checklist #14).\n // Three trigger sources: `close` (natural OR signal-killed),\n // `error` (spawn failure), explicit `killBackground` (which\n // routes through `close` itself after the SIGTERM lands).\n let exitGraceTimer: NodeJS.Timeout | undefined\n const settle = (cause: 'close' | 'error', code: number | null, signal: NodeJS.Signals | null, errMessage?: string): void => {\n if (state.settled)\n return\n state.settled = true\n // Move to the end: eviction drops the oldest FINISHED, so a long task\n // that started first must not go the moment it ends.\n if (tasks.get(taskId) === state) {\n tasks.delete(taskId)\n tasks.set(taskId, state)\n }\n untrack()\n clearStallTimer()\n clearTimeout(exitGraceTimer)\n state.endedAt = Date.now()\n\n // Determine final status from cause + signal.\n const status: TaskExitInfo['status']\n = signal === 'SIGTERM' || state.killRequested\n ? 'killed'\n : 'exited'\n // Signal-killed children report null `code` from Node; map back\n // to the POSIX `128 + signum` convention so consumers can read\n // an integer either way.\n const exitCode = code !== null\n ? code\n : signal === 'SIGTERM'\n ? 143\n : signal\n ? 128\n : 1\n state.status = status\n state.exitCode = exitCode\n if (signal)\n state.signal = signal\n\n // Flush + close the WriteStream BEFORE firing onExit — model\n // may read the file in the same turn it receives the\n // notification, and a still-open stream can hold tail bytes\n // back from disk. `stream.end(callback)` is the documented\n // \"all queued writes are flushed when this fires\" idiom.\n //\n // ORDER MATTERS: any error preamble we want in the log file\n // (spawn failures with no stdout, buffer overflows) MUST be\n // written BEFORE `end()` — once `end()` is called the stream\n // is closed for writing and subsequent `.write()` calls are\n // dropped, which would silently lose ENOENT-on-`/bin/sh` messages.\n if (errMessage) {\n try {\n outputStream.write(`\\n${errMessage}\\n`)\n }\n catch {\n // Stream may have errored before this — best-effort only.\n }\n }\n if (droppedBytes > 0) {\n try {\n // Structured + loud — the model can pattern-match the tag\n // rather than misread a truncated log as the full output.\n outputStream.write(`\\n<output-truncated bytes-dropped=\"${droppedBytes}\"/>\\n`)\n }\n catch {\n // Best-effort only, same as the error preamble above.\n }\n }\n outputStream.end(() => {\n // `stateToTaskExitInfo` reads the same fields we just set\n // on `state`, so the snapshot the consumer gets matches the\n // post-settle state exactly. `onExit` is optional — pull-based\n // consumers reconcile via `listBackground` instead. The owner's\n // callback fires first, then every kill/wait/destroy watcher.\n const info = stateToTaskExitInfo(state)\n for (const callback of [state.onExit, ...state.exitWatchers.splice(0)]) {\n try {\n callback?.(info)\n }\n catch (err) {\n // Defensive — a buggy onExit callback shouldn't crash the\n // host. Surface via stderr under ZIDANE_DEBUG; otherwise\n // swallow. Matches the spawn-tool's bubbleError pattern.\n if (process.env.ZIDANE_DEBUG)\n process.stderr.write(`[zidane/contexts] task ${taskId} onExit threw: ${err instanceof Error ? err.message : String(err)}\\n`)\n }\n }\n releaseFinishedTask(tasks, state)\n })\n // Release the process + stream references at settle: entries\n // outlive their processes in the registry (until explicit\n // `destroy`), and a session that backgrounds many tasks would\n // otherwise retain every dead ChildProcess and ended\n // WriteStream — plus the closures they anchor — for its whole\n // lifetime. Everything the post-exit readers (`listBackground` /\n // `waitBackground` / `killBackground`) project stays on `state`.\n state.child = undefined\n state.outputStream = undefined\n }\n\n child.on('close', (code, signal) => settle('close', code, signal))\n child.on('error', err => settle('error', null, null, `[spawn error] ${err.message}`))\n\n child.on('exit', (code, signal) => {\n exitGraceTimer = settleAfterExitGrace(child, state, () => settle('close', code, signal))\n })\n\n return { taskId, pid: state.pid, outputPath, ...(tty ? { terminal: true } : {}) }\n },\n }\n}\n","/**\n * Foreground `exec` of the in-process execution context. Internal module.\n */\n\nimport type { ChildProcess } from 'node:child_process'\nimport type { CappedSlot } from './output-cap'\nimport type { ProcessShell } from './process-shell'\nimport type { ProcessContextState } from './process-state'\nimport type { ExecResult, ExecutionContext, ExecutionHandle } from './types'\nimport { Buffer } from 'node:buffer'\nimport { resolve } from 'node:path'\nimport { annotateDenial } from './isolation'\nimport { appendCapped, DEFAULT_MAX_OUTPUT_BUFFER, outputExceededMessage } from './output-cap'\nimport { EXEC_KILL_ESCALATION_GRACE_MS, EXIT_PIPE_DRAIN_GRACE_MS, killProcessGroup, loadSpawn, SUPPORTS_PROCESS_GROUPS } from './process-state'\n\n/** What a running command reports, wired before it starts. */\ninterface ChildHandlers {\n data: (stream: 'stdout' | 'stderr', chunk: Buffer) => void\n /** It could not start (ENOENT on the shell, EACCES, …). */\n error: (err: Error) => void\n /** It exited; its pipes may still be open. */\n exit: (code: number | null, signal: NodeJS.Signals | null) => void\n /** It exited and its pipes closed. */\n close: (code: number | null, signal: NodeJS.Signals | null) => void\n}\n\n/** A started command: signal its group, stop reading its pipes. */\ninterface ExecChild {\n pid: number | undefined\n kill: (signal: NodeJS.Signals) => void\n releasePipes: () => void\n}\n\ninterface ChildSpec {\n file: string\n args: string[]\n cwd: string\n env: NodeJS.ProcessEnv\n}\n\n/** `node:child_process`, off Bun. */\nfunction startNodeChild(spawnChild: Awaited<ReturnType<typeof loadSpawn>>, spec: ChildSpec, on: ChildHandlers): ExecChild {\n const child: ChildProcess = spawnChild(spec.file, spec.args, {\n cwd: spec.cwd,\n env: spec.env,\n stdio: ['ignore', 'pipe', 'pipe'],\n detached: SUPPORTS_PROCESS_GROUPS,\n })\n child.stdout?.on('data', chunk => on.data('stdout', chunk as Buffer))\n child.stderr?.on('data', chunk => on.data('stderr', chunk as Buffer))\n child.on('error', on.error)\n child.on('close', on.close)\n child.on('exit', on.exit)\n return {\n pid: child.pid,\n kill: signal => killProcessGroup(child, signal),\n releasePipes: () => {\n child.stdout?.destroy()\n child.stderr?.destroy()\n },\n }\n}\n\n/**\n * `Bun.spawn`, under Bun (as `src/tui/bash-runner.ts` and `./run-bounded`):\n * Bun's `node:child_process` runs the exit callback synchronously when the\n * child is already gone by the time it watches it (a slow spawn on a loaded\n * or cold machine), so 'exit', every 'data' and 'close' fire inside\n * `spawn()`, before any listener exists, and the command only ends at its\n * timeout. `Bun.spawn`'s pipes and `exited` promise keep what happened\n * until they are read.\n */\nfunction startBunChild(spec: ChildSpec, on: ChildHandlers): ExecChild | null {\n let proc: ReturnType<typeof Bun.spawn<'ignore', 'pipe', 'pipe'>>\n try {\n proc = Bun.spawn([spec.file, ...spec.args], {\n cwd: spec.cwd,\n env: spec.env,\n stdio: ['ignore', 'pipe', 'pipe'],\n detached: SUPPORTS_PROCESS_GROUPS,\n })\n }\n catch (err) {\n on.error(err instanceof Error ? err : new Error(String(err)))\n return null\n }\n const readers = [proc.stdout.getReader(), proc.stderr.getReader()] as const\n const drain = async (reader: ReadableStreamDefaultReader<Uint8Array>, stream: 'stdout' | 'stderr'): Promise<void> => {\n try {\n for (;;) {\n const { done, value } = await reader.read()\n if (done)\n return\n on.data(stream, Buffer.from(value))\n }\n }\n catch {\n // Released, or the pipe broke (the group was killed): what was read is kept.\n }\n }\n const drained = Promise.all([drain(readers[0], 'stdout'), drain(readers[1], 'stderr')])\n void proc.exited.then(() => {\n on.exit(proc.exitCode, proc.signalCode)\n void drained.then(() => on.close(proc.exitCode, proc.signalCode))\n })\n return {\n pid: proc.pid,\n kill: signal => killProcessGroup(proc, signal),\n releasePipes: () => {\n for (const reader of readers)\n reader.cancel().catch(() => undefined)\n },\n }\n}\n\nexport function processExecMethods(s: ProcessContextState, sh: ProcessShell): Required<Pick<ExecutionContext, 'exec'>> {\n const { config, baseEnv, defaultEnv, isolation, trackSession } = s\n const { shellCommand, isolationBlocker } = sh\n\n return {\n async exec(\n handle: ExecutionHandle,\n command: string,\n options?: { cwd?: string, env?: Record<string, string>, timeout?: number, signal?: AbortSignal },\n ): Promise<ExecResult> {\n const cwd = options?.cwd ? resolve(handle.cwd, options.cwd) : handle.cwd\n\n // Pre-aborted fast path: skip the spawn entirely and synthesize a\n // killed-by-signal result. Saves a spawn round-trip + dodges Node\n // emitting an immediate `AbortError`.\n if (options?.signal?.aborted) {\n return { stdout: '', stderr: 'aborted by signal before spawn', exitCode: 143 }\n }\n\n const blocked = isolationBlocker()\n if (blocked)\n return blocked\n\n const timeoutMs = (options?.timeout ?? config?.limits?.timeout ?? 30) * 1000\n const maxBuffer = DEFAULT_MAX_OUTPUT_BUFFER\n\n // Off Bun, the lazy `node:child_process` load (see `loadSpawn`), awaited\n // before the Promise executor so it is ready synchronously inside it.\n // Under Bun, `startBunChild` uses `Bun.spawn` instead.\n const spawnChild = typeof Bun === 'undefined' ? await loadSpawn() : null\n\n return new Promise<ExecResult>((resolveP) => {\n // Spawn as a NEW process group leader so we can kill the whole\n // subtree on abort. Without `detached: true`, sending SIGTERM to\n // the shell's pid only kills the shell wrapper — its child\n // processes (the actual `sleep`, `npm`, `python`, …) get\n // reparented to init and keep running. `process.kill(-pid, …)`\n // with a NEGATIVE pid targets the whole process group; that's\n // the POSIX idiom for \"shut down everything I started\".\n //\n // On Windows there are no process groups in the POSIX sense, so\n // we leave `detached` off and accept the shell-only kill — the\n // platform's job-object machinery is the path forward there if\n // we ever need it, but it's not the bug zidane's users are\n // hitting today.\n const shell = shellCommand(command)\n let child: ExecChild | null = null\n let untrack = (): void => {}\n\n // Byte-capped accumulation via the shared exec-transport primitive\n // (see contexts/output-cap.ts) — byte accounting + codepoint-safe\n // cuts. Overflow orchestration (kill the process group, matching\n // `execAsync`'s maxBuffer behavior) stays here.\n const stdoutSlot: CappedSlot = { text: '', bytes: 0 }\n const stderrSlot: CappedSlot = { text: '', bytes: 0 }\n let bufferTruncated = false\n let timedOut = false\n let killedByAbort = false\n let settled = false\n\n // Every exec-initiated kill escalates: SIGTERM now, SIGKILL after a\n // short grace unless the child settled in between. Without this, a\n // TERM-ignoring child leaves the promise pending forever.\n const killWithEscalation = (): void => {\n child?.kill('SIGTERM')\n const escalation = setTimeout(() => {\n if (!settled)\n child?.kill('SIGKILL')\n }, EXEC_KILL_ESCALATION_GRACE_MS)\n escalation.unref?.()\n }\n\n const onChunk = (slot: CappedSlot, chunk: Buffer): void => {\n const outcome = appendCapped(slot, chunk, maxBuffer)\n if (outcome !== 'ok' && !bufferTruncated) {\n bufferTruncated = true\n killWithEscalation()\n }\n }\n\n const timeoutTimer = timeoutMs > 0\n ? setTimeout(() => {\n timedOut = true\n killWithEscalation()\n }, timeoutMs)\n : undefined\n\n const onAbort = (): void => {\n killedByAbort = true\n killWithEscalation()\n }\n const userSignal = options?.signal\n if (userSignal)\n userSignal.addEventListener('abort', onAbort, { once: true })\n\n let exitGraceTimer: NodeJS.Timeout | undefined\n\n const settle = (exitCode: number, extraStderr?: string): void => {\n if (settled)\n return\n settled = true\n untrack()\n if (timeoutTimer)\n clearTimeout(timeoutTimer)\n if (exitGraceTimer)\n clearTimeout(exitGraceTimer)\n if (userSignal)\n userSignal.removeEventListener('abort', onAbort)\n const finalStderr = extraStderr\n ? (stderrSlot.text ? `${stderrSlot.text}\\n${extraStderr}` : extraStderr)\n : stderrSlot.text\n const result: ExecResult = { stdout: stdoutSlot.text, stderr: finalStderr, exitCode }\n // Name the sandbox when a failure looks like a kernel denial so the\n // model asks the user to widen the policy instead of guessing.\n resolveP(isolation ? annotateDenial(result, isolation) : result)\n }\n\n // Shared classification ladder for `close` (fast path: pipes\n // drained normally) and the post-`exit` grace (pipes held open\n // by a daemonized grandchild). Order matters: killed-by-our-\n // abort wins over timeout wins over natural exit, because the\n // abort listener fires first when the user cancels mid-\n // timeout-window.\n const settleFromStatus = (code: number | null, signal: NodeJS.Signals | null): void => {\n if (killedByAbort) {\n settle(143, 'aborted by signal')\n return\n }\n if (timedOut) {\n settle(124, `command timed out after ${timeoutMs}ms`)\n return\n }\n if (bufferTruncated) {\n settle(143, outputExceededMessage(maxBuffer, 'process killed'))\n return\n }\n if (signal) {\n // Killed by some other signal we didn't issue. Treat as\n // signal-killed for consumer compat.\n settle(128 + 15, `terminated by signal ${signal}`)\n return\n }\n settle(typeof code === 'number' ? code : 1)\n }\n\n const handlers: ChildHandlers = {\n data: (stream, chunk) => onChunk(stream === 'stdout' ? stdoutSlot : stderrSlot, chunk),\n // Spawn failure (ENOENT on `/bin/sh`, EACCES, …). Mirror\n // `execAsync`'s \"rejects with an Error\" shape by surfacing\n // the message on stderr and a non-zero exit.\n error: err => settle(1, err.message),\n close: (code, signal) => settleFromStatus(code, signal),\n exit: (code, signal) => {\n // The command is DONE here: `close` only adds \"every stdio\n // pipe closed\", which a daemonized grandchild can block\n // forever (see EXIT_PIPE_DRAIN_GRACE_MS). Give the pipes a\n // short drain grace, then settle with what we have and\n // release them. The daemon keeps running: that was the\n // command's intent, so killing the group here would be wrong.\n exitGraceTimer = setTimeout(() => {\n if (settled)\n return\n child?.releasePipes()\n settleFromStatus(code, signal)\n }, EXIT_PIPE_DRAIN_GRACE_MS)\n exitGraceTimer.unref?.()\n },\n }\n const spec: ChildSpec = { file: shell.file, args: shell.args, cwd, env: { ...baseEnv, ...defaultEnv, ...options?.env } }\n child = spawnChild ? startNodeChild(spawnChild, spec, handlers) : startBunChild(spec, handlers)\n if (!settled)\n untrack = trackSession(child?.pid)\n })\n },\n }\n}\n","/**\n * Node-spawn `git ls-files` runner used by the local process context's glob.\n *\n * Kept separate from `./git-ls-files` (which stays node-free for edge bundles)\n * because this leg imports `node:child_process`.\n */\n\nimport { spawn } from 'node:child_process'\nimport { GIT_LS_FILES_ARGS, parseGitLsFiles } from './git-ls-files'\n\n/**\n * Run `git ls-files` in `cwd` and return its non-ignored paths (relative to\n * `cwd`). Returns `null` when the directory is not a git repo, git is missing,\n * or the call aborts — callers treat `null` as \"fall back to a filesystem\n * walk\". Never throws.\n */\nexport async function gitListFilesLocal(cwd: string, signal?: AbortSignal): Promise<string[] | null> {\n return new Promise<string[] | null>((resolveP) => {\n let child: ReturnType<typeof spawn>\n try {\n child = spawn('git', [...GIT_LS_FILES_ARGS], { cwd, stdio: ['ignore', 'pipe', 'pipe'] })\n }\n catch {\n resolveP(null)\n return\n }\n if (signal?.aborted) {\n child.kill('SIGTERM')\n resolveP(null)\n return\n }\n const stdoutChunks: string[] = []\n const onAbort = () => child.kill('SIGTERM')\n signal?.addEventListener('abort', onAbort, { once: true })\n child.stdout?.setEncoding('utf8')\n child.stdout?.on('data', chunk => stdoutChunks.push(chunk as string))\n child.on('error', () => {\n signal?.removeEventListener('abort', onAbort)\n resolveP(null)\n })\n child.on('close', (code) => {\n signal?.removeEventListener('abort', onAbort)\n if (code !== 0 || signal?.aborted) {\n resolveP(null)\n return\n }\n resolveP(parseGitLsFiles(stdoutChunks.join('')))\n })\n })\n}\n","import type { ListFileMetadata } from './types'\nimport { readdir, stat } from 'node:fs/promises'\nimport { dirname, resolve, sep } from 'node:path'\nimport { lazyAsync } from '../lazy'\nimport { gitListFilesLocal } from './git-ls-files-local'\n\ntype NodeGlob = (pattern: string, options: { cwd: string }) => AsyncIterable<string>\n\ninterface BunGlobInstance { scan: (options: { cwd: string, onlyFiles?: boolean, dot?: boolean }) => AsyncIterable<string> }\ntype BunGlobCtor = new (pattern: string) => BunGlobInstance\n\nconst loadNativeNodeGlob = lazyAsync(async (): Promise<NodeGlob | undefined> => {\n const candidate = (await import('node:fs/promises') as { glob?: unknown }).glob\n return typeof candidate === 'function' ? candidate as NodeGlob : undefined\n})\n\nfunction forcePortable(): boolean {\n return (globalThis as { __zidaneForcePortableGlobForTests?: boolean }).__zidaneForcePortableGlobForTests === true\n}\n\nasync function loadNodeGlob(): Promise<NodeGlob | undefined> {\n if (forcePortable())\n return undefined\n return loadNativeNodeGlob()\n}\n\n/**\n * Bun's `node:fs/promises.glob` buffers the entire directory walk before\n * yielding (so an early `limit` break never fires — a broad `**` pattern over\n * a large `node_modules` hangs). `Bun.Glob().scan()` streams incrementally and\n * is the fast path under Bun. Returns undefined off Bun or when tests force the\n * portable walker.\n */\nfunction loadBunGlob(): BunGlobCtor | undefined {\n if (forcePortable())\n return undefined\n const bun = (globalThis as { Bun?: { Glob?: unknown } }).Bun\n return bun && typeof bun.Glob === 'function' ? bun.Glob as BunGlobCtor : undefined\n}\n\nfunction escapeRegexChar(char: string): string {\n return /[\\\\^$.*+?()[\\]{}|]/.test(char) ? `\\\\${char}` : char\n}\n\n/** Expand the first `{a,b}` group of a glob pattern into one pattern per alternative, recursively. Returns the pattern unchanged when it has no group with a comma. */\nexport function expandBraces(pattern: string): string[] {\n const start = pattern.indexOf('{')\n if (start === -1)\n return [pattern]\n const end = pattern.indexOf('}', start + 1)\n if (end === -1)\n return [pattern]\n const body = pattern.slice(start + 1, end)\n if (!body || !body.includes(','))\n return [pattern]\n return body\n .split(',')\n .flatMap(part => expandBraces(`${pattern.slice(0, start)}${part}${pattern.slice(end + 1)}`))\n}\n\n/** Convert a glob pattern without braces into an anchored `RegExp`. `*` and `?` stay inside one path segment, `**` crosses segments, and `[!x]` negates a class. */\nexport function globPatternToRegex(pattern: string): RegExp {\n let out = '^'\n for (let i = 0; i < pattern.length; i++) {\n const char = pattern[i]\n const next = pattern[i + 1]\n if (char === '*') {\n if (next === '*') {\n const after = pattern[i + 2]\n if (after === '/') {\n out += '(?:[^/]+/)*'\n i += 2\n }\n else {\n out += '.*'\n i += 1\n }\n }\n else {\n out += '[^/]*'\n }\n }\n else if (char === '?') {\n out += '[^/]'\n }\n else if (char === '[') {\n const end = pattern.indexOf(']', i + 1)\n if (end === -1) {\n out += '\\\\['\n }\n else {\n let cls = pattern.slice(i + 1, end)\n if (cls.startsWith('!'))\n cls = `^${cls.slice(1)}`\n out += `[${cls}]`\n i = end\n }\n }\n else {\n out += escapeRegexChar(char)\n }\n }\n return new RegExp(`${out}$`)\n}\n\nexport function globLiteralPrefix(pattern: string): string {\n const firstMeta = pattern.search(/[*?[\\]{}]/)\n const prefix = firstMeta === -1 ? dirname(pattern) : pattern.slice(0, firstMeta)\n const slash = prefix.lastIndexOf('/')\n if (slash === -1)\n return ''\n return prefix.slice(0, slash)\n}\n\n/**\n * True when a pattern can match files outside `cwd` — an absolute path, a\n * Windows drive, or any `..` segment. Such patterns can't use the `git\n * ls-files` path (git only knows files under the repo) and fall back to the\n * filesystem walk.\n */\nfunction patternEscapesCwd(pattern: string): boolean {\n const norm = pattern.split(sep).join('/')\n if (norm.startsWith('/') || /^[a-z]:/i.test(norm))\n return true\n return norm.split('/').includes('..')\n}\n\nasync function addMetadata(cwd: string, rel: string, includeMetadata: boolean): Promise<ListFileMetadata | null> {\n try {\n const s = await stat(resolve(cwd, rel))\n if (!s.isFile())\n return null\n return includeMetadata ? { path: rel, size: s.size, mtimeMs: s.mtimeMs } : { path: rel }\n }\n catch {\n return null\n }\n}\n\nfunction compilePattern(pattern: string): RegExp[] {\n return expandBraces(pattern.split(sep).join('/')).map(globPatternToRegex)\n}\n\n/** Match the (already non-ignored) `git ls-files` set against the glob pattern. */\nasync function matchGitFiles(\n gitFiles: readonly string[],\n pattern: string,\n cwd: string,\n limit: number,\n includeMetadata: boolean,\n signal: AbortSignal | undefined,\n): Promise<ListFileMetadata[]> {\n const regexes = compilePattern(pattern)\n const out: ListFileMetadata[] = []\n for (const rel of gitFiles) {\n if (signal?.aborted || out.length >= limit)\n break\n if (!regexes.some(regex => regex.test(rel)))\n continue\n out.push(includeMetadata ? await addMetadata(cwd, rel, true) ?? { path: rel } : { path: rel })\n }\n return out.sort((a, b) => a.path.localeCompare(b.path))\n}\n\n/** Depth-first walk that matches against `regexes` and stops at `limit`. */\nasync function walkMatch(\n root: string,\n prefix: string,\n regexes: RegExp[],\n cwd: string,\n limit: number,\n includeMetadata: boolean,\n signal: AbortSignal | undefined,\n out: ListFileMetadata[],\n): Promise<void> {\n if (out.length >= limit || signal?.aborted)\n return\n let entries: Array<{ name: string, isDirectory: () => boolean, isFile: () => boolean }>\n try {\n entries = await readdir(resolve(root, prefix), { encoding: 'utf8', withFileTypes: true })\n }\n catch {\n return\n }\n for (const entry of entries) {\n if (out.length >= limit || signal?.aborted)\n return\n const rel = prefix ? `${prefix}/${entry.name}` : entry.name\n if (entry.isDirectory()) {\n await walkMatch(root, rel, regexes, cwd, limit, includeMetadata, signal, out)\n }\n else if (entry.isFile() && regexes.some(regex => regex.test(rel))) {\n out.push(includeMetadata ? await addMetadata(cwd, rel, true) ?? { path: rel } : { path: rel })\n }\n }\n}\n\nasync function globPortable(\n pattern: string,\n cwd: string,\n limit: number,\n includeMetadata: boolean,\n signal: AbortSignal | undefined,\n): Promise<ListFileMetadata[]> {\n const normalized = pattern.split(sep).join('/')\n const startPrefix = globLiteralPrefix(normalized)\n const regexes = expandBraces(normalized).map(globPatternToRegex)\n const out: ListFileMetadata[] = []\n await walkMatch(cwd, startPrefix, regexes, cwd, limit, includeMetadata, signal, out)\n return out.sort((a, b) => a.path.localeCompare(b.path))\n}\n\nasync function collectFromIterable(\n iter: AsyncIterable<string>,\n cwd: string,\n limit: number,\n includeMetadata: boolean,\n signal: AbortSignal | undefined,\n): Promise<ListFileMetadata[] | null> {\n const results: ListFileMetadata[] = []\n // A native scan can throw mid-iteration on a pathological tree (e.g. a\n // recursive symlink cycle → ENAMETOOLONG) and there's no way to resume it.\n // Signal the caller (null) to recover via the portable walk, which recurses\n // only into real directories and isolates per-directory errors.\n try {\n for await (const rel of iter) {\n if (signal?.aborted)\n break\n const entry = await addMetadata(cwd, rel, includeMetadata)\n if (!entry)\n continue\n results.push(entry)\n if (results.length >= limit)\n break\n }\n }\n catch {\n return null\n }\n return results.sort((a, b) => a.path.localeCompare(b.path))\n}\n\nfunction globViaBun(\n BunGlob: BunGlobCtor,\n pattern: string,\n cwd: string,\n limit: number,\n includeMetadata: boolean,\n signal: AbortSignal | undefined,\n): Promise<ListFileMetadata[] | null> {\n // `dot: true` keeps dotfile matching consistent with the Node + portable\n // paths; `onlyFiles: true` mirrors their file-only results.\n const scan = new BunGlob(pattern).scan({ cwd, onlyFiles: true, dot: true })\n return collectFromIterable(scan, cwd, limit, includeMetadata, signal)\n}\n\n/**\n * Match files under `cwd` against a glob pattern. Uses `git ls-files` unless\n * `options.gitignore` is `false`, the pattern escapes `cwd` or `cwd` is not a\n * git repo, and falls back to a filesystem scan otherwise. Returns\n * cwd-relative paths sorted by path, at most `options.limit`, with size and\n * mtime when `options.metadata` is set.\n */\nexport async function globFilesLocal(\n pattern: string,\n cwd: string,\n options: { limit: number, metadata?: boolean, gitignore?: boolean, signal?: AbortSignal },\n): Promise<ListFileMetadata[]> {\n const includeMetadata = options.metadata === true\n const { limit, signal } = options\n\n // Default path: intersect the pattern with git's non-ignored file set. Git\n // skips `.gitignore`d trees (`node_modules`, build dirs) entirely, so this is\n // both correct and fast — and never triggers the Bun `fs.glob` hang. The\n // test-only force-portable flag also bypasses it so the filesystem walker\n // stays directly exercisable.\n if (options.gitignore !== false && !forcePortable() && !patternEscapesCwd(pattern)) {\n const gitFiles = await gitListFilesLocal(cwd, signal)\n if (gitFiles)\n return matchGitFiles(gitFiles, pattern, cwd, limit, includeMetadata, signal)\n }\n\n // Fallback path: filesystem glob (gitignore disabled, not a git repo, or the\n // pattern escapes cwd). Prefer a fast native scanner; if it throws on a\n // pathological tree (null), recover via the portable walk.\n const bunGlob = loadBunGlob()\n if (bunGlob) {\n const viaBun = await globViaBun(bunGlob, pattern, cwd, limit, includeMetadata, signal)\n if (viaBun)\n return viaBun\n }\n else {\n const nodeGlob = await loadNodeGlob()\n if (nodeGlob) {\n const viaNode = await collectFromIterable(nodeGlob(pattern, { cwd }), cwd, limit, includeMetadata, signal)\n if (viaNode)\n return viaNode\n }\n }\n\n return globPortable(pattern, cwd, limit, includeMetadata, signal)\n}\n\n// `globFilesViaShell` moved to `./glob-shell` (node-free) so remote-only\n// contexts can import it without pulling this module's `node:fs` imports.\n// Re-exported here for back-compat.\nexport { globFilesViaShell } from './glob-shell'\n","/**\n * File methods (with workspace containment + sandbox write policy) of the\n * in-process execution context. Internal module.\n */\n\nimport type { Buffer } from 'node:buffer'\nimport type { ProcessContextState } from './process-state'\nimport type { ExecutionContext, ExecutionHandle, ListFilesEntry } from './types'\nimport { mkdir, readdir, readFile, realpath, stat, writeFile } from 'node:fs/promises'\nimport { basename, dirname, join, relative, resolve } from 'node:path'\nimport { nodeEntryPort } from './entries'\nimport { globFilesLocal, globLiteralPrefix } from './glob'\nimport { isWithinRoot } from './isolation'\n\nexport function processFileMethods(s: ProcessContextState): Required<Pick<ExecutionContext, 'readFile' | 'fileSize' | 'readFileBinary' | 'writeFile' | 'listFiles' | 'entries'>> {\n const { workspaceRoot, isolation } = s\n\n /**\n * Resolve `path` against the handle cwd and, when a `workspaceRoot` is\n * configured, reject anything that escapes it. Uses `realpath` on the\n * nearest existing ancestor so symlink escapes (and `..`) are caught for\n * both existing and not-yet-created targets.\n */\n async function resolveContained(handle: ExecutionHandle, path: string): Promise<string> {\n const full = resolve(handle.cwd, path)\n if (workspaceRoot === undefined)\n return full\n\n const canonical = await canonicalizeForCheck(full)\n const canonicalRoot = await realpath(workspaceRoot).catch(() => workspaceRoot)\n if (!isWithinRoot(canonicalRoot, canonical)) {\n throw new Error(\n `Path escapes the workspace root: ${path} (resolved outside ${canonicalRoot})`,\n )\n }\n return full\n }\n\n /**\n * `resolveContained` for the entry itself: its parent folder real-pathed,\n * its own name kept, so a link pointing out can still be renamed or removed.\n */\n async function resolveContainedEntry(handle: ExecutionHandle, path: string): Promise<string> {\n const full = resolve(handle.cwd, path)\n if (workspaceRoot === undefined)\n return full\n const canonical = await canonicalizeEntry(full)\n const canonicalRoot = await realpath(workspaceRoot).catch(() => workspaceRoot)\n // The root itself is in, however its own path is spelled (a parent that real-paths elsewhere).\n if (full !== resolve(workspaceRoot) && !isWithinRoot(canonicalRoot, canonical)) {\n throw new Error(\n `Path escapes the workspace root: ${path} (resolved outside ${canonicalRoot})`,\n )\n }\n return full\n }\n\n /** The entry `full` with its parent folder canonicalized and its own name kept (never followed). */\n async function canonicalizeEntry(full: string): Promise<string> {\n const parent = dirname(full)\n return parent === full ? full : join(await canonicalizeForCheck(parent), basename(full))\n }\n\n /**\n * Canonicalize the deepest existing ancestor of `full` to defeat symlink\n * escapes; the non-existent tail (for writes) is appended back verbatim.\n */\n async function canonicalizeForCheck(full: string): Promise<string> {\n let existing = full\n const tail: string[] = []\n while (true) {\n try {\n existing = await realpath(existing)\n break\n }\n catch {\n const parent = dirname(existing)\n if (parent === existing) {\n // Reached the filesystem root without an existing ancestor.\n existing = parent\n break\n }\n // `relative` (not slice) so the segment is correct even on Windows\n // drive roots where `dirname('C:\\\\foo')` is `C:\\\\` (no 1-char sep).\n tail.unshift(relative(parent, existing))\n existing = parent\n }\n }\n return tail.length ? resolve(existing, ...tail) : existing\n }\n\n /**\n * In-process counterpart of the sandbox's write policy: `writeFile` (and\n * so the `write_file` / `edit` tools) may only target `isolation.writableRoots`.\n * Reads are deliberately unrestricted — same boundary the kernel enforces\n * for shell commands, so the two never disagree about where writes land.\n */\n async function assertWritable(full: string, path: string, entry = false): Promise<void> {\n if (!isolation)\n return\n const canonical = entry ? await canonicalizeEntry(full) : await canonicalizeForCheck(full)\n if (!isolation.writableRoots.some(root => isWithinRoot(root, canonical))) {\n throw new Error(\n `[sandbox] write denied: ${path} is outside the writable roots (${isolation.writableRoots.join(', ')}). `\n + 'Ask the user to add it under Settings → \"Sandbox writable paths\" or turn off \"Sandbox shell commands\".',\n )\n }\n }\n\n return {\n // Same containment and write policy as `writeFile`, on the entry itself (a link is never followed) where it is the entry acted on.\n entries: handle => nodeEntryPort({\n resolve: path => resolveContained(handle, path),\n entry: path => resolveContainedEntry(handle, path),\n writable: (full, path) => assertWritable(full, path, true),\n }),\n\n async readFile(handle: ExecutionHandle, path: string): Promise<string> {\n return readFile(await resolveContained(handle, path), 'utf-8')\n },\n\n async fileSize(handle: ExecutionHandle, path: string): Promise<number | null> {\n try {\n // Same containment as every other file method. `stat` (NOT lstat):\n // the caller wants the TARGET's size — an lstat of a symlink\n // reports the link itself and a link to a 10GB file would sail\n // past the whole-read guard this probe exists to feed.\n const info = await stat(await resolveContained(handle, path))\n return info.isFile() ? info.size : null\n }\n catch {\n return null\n }\n },\n\n async readFileBinary(handle: ExecutionHandle, path: string): Promise<Uint8Array> {\n // No encoding → returns a Buffer (which is a Uint8Array). Used by\n // read_file to ferry image / binary content into the multimodal route.\n const buf = await readFile(await resolveContained(handle, path))\n return new Uint8Array(buf)\n },\n\n async writeFile(handle: ExecutionHandle, path: string, content: string | Buffer, encoding: BufferEncoding = 'utf-8'): Promise<void> {\n const fullPath = await resolveContained(handle, path)\n await assertWritable(fullPath, path)\n await mkdir(dirname(fullPath), { recursive: true })\n if (typeof content === 'string')\n await writeFile(fullPath, content, encoding)\n else\n await writeFile(fullPath, content)\n },\n\n async listFiles(handle: ExecutionHandle, path: string, options): Promise<ListFilesEntry[]> {\n if (options?.glob) {\n await resolveContained(handle, globLiteralPrefix(path) || '.')\n const entries = await globFilesLocal(path, handle.cwd, {\n limit: options?.limit ?? 1000,\n metadata: options?.metadata,\n gitignore: options?.gitignore,\n signal: options?.signal,\n })\n if (workspaceRoot === undefined)\n return entries\n const contained: ListFilesEntry[] = []\n for (const entry of entries) {\n try {\n await resolveContained(handle, entry.path)\n contained.push(entry)\n }\n catch {\n // Symlink escapes can be discovered by broad globs like `**/*`.\n // Keep the process context's workspaceRoot invariant by filtering\n // them exactly as read/write paths are filtered.\n }\n }\n return contained\n }\n // Literal listing — suffix directories with `/` so consumers (the\n // `list_files` tool, path suggestions) can tell files from dirs\n // without a second probe. Mirrors `ls -p` in the docker context.\n const dirents = await readdir(await resolveContained(handle, path), { withFileTypes: true })\n return dirents.map(d => (d.isDirectory() ? `${d.name}/` : d.name))\n },\n }\n}\n","/**\n * Terminal output → plain text, incrementally. A PTY emits colors, cursor\n * moves, titles and carriage-return redraws; a model (or a log file) wants\n * the words. Sequences may be split across chunks, so the parser keeps its\n * state between `push` calls.\n *\n * Line semantics follow what a person sees on a terminal, roughly: `\\r\\n`\n * ends a line, a lone `\\r` rewinds it (a progress bar redraws in place, so\n * only its last state survives), backspace erases a character. Anything\n * fancier (cursor addressing in full-screen apps) is dropped, not replayed.\n */\n\nexport interface AnsiStripper {\n /** Feed raw output; returns the lines it completed (each ends with `\\n`). */\n push: (chunk: string) => string\n /** The line being written, not yet ended. */\n partial: () => string\n /**\n * Hand out the unfinished line and treat it as written: a later rewind\n * starts a fresh line instead of editing text that is already out. For\n * logs that must show a prompt waiting on the same line.\n */\n takePartial: () => string\n}\n\nexport interface AnsiStripperOptions {\n /** Window title set by the program (OSC 0 / 2), e.g. the running command. */\n onTitle?: (title: string) => void\n}\n\n/** Parser states: plain text, after ESC, in a CSI, in an OSC/DCS string, after ESC inside one. */\nconst State = { Text: 0, Esc: 1, Csi: 2, Str: 3, StrEsc: 4 } as const\n\n/** Runs of plain text at least this long are appended in one slice; shorter ones char by char, which is cheaper for them. */\nconst SLICE_MIN = 4\n\n/** Printable text, appended to the line as is: tab, or neither a control (C0, DEL, C1) nor ESC. */\nconst isPlain = (code: number) => code === 0x09 || (code >= 0x20 && (code < 0x7F || code >= 0xA0))\n\nexport function createAnsiStripper(options: AnsiStripperOptions = {}): AnsiStripper {\n let state: (typeof State)[keyof typeof State] = State.Text\n /** Body of the OSC / DCS / APC string being read; OSC only is kept. */\n let str = ''\n let strIsOsc = false\n let line = ''\n /** A `\\r` arrived; the next printable rewinds the line unless `\\n` follows. */\n let pendingCr = false\n /** Part of the current line was handed out by `takePartial`: a rewind must start a new line. */\n let taken = false\n\n const endString = () => {\n if (strIsOsc && options.onTitle) {\n const semi = str.indexOf(';')\n const code = semi === -1 ? str : str.slice(0, semi)\n if ((code === '0' || code === '2') && semi !== -1)\n options.onTitle(str.slice(semi + 1))\n }\n str = ''\n state = State.Text\n }\n\n return {\n push(chunk) {\n let out = ''\n for (let i = 0; i < chunk.length; i++) {\n const ch = chunk[i]!\n const code = ch.charCodeAt(0)\n switch (state) {\n case State.Text:\n if (code === 0x1B) {\n state = State.Esc\n }\n else if (ch === '\\n') {\n out += `${line}\\n`\n line = ''\n pendingCr = false\n taken = false\n }\n else if (ch === '\\r') {\n pendingCr = true\n }\n else if (code === 0x08) {\n line = line.slice(0, -1)\n }\n else if (code === 0x9B) {\n state = State.Csi\n }\n else if (code === 0x9D) {\n state = State.Str\n strIsOsc = true\n }\n else if (ch === '\\t' || code >= 0x20) {\n if (code >= 0x7F && code < 0xA0)\n break\n if (pendingCr) {\n if (taken)\n out += '\\n'\n taken = false\n line = ''\n pendingCr = false\n }\n let end = i + 1\n while (end < chunk.length && isPlain(chunk.charCodeAt(end)))\n end++\n if (end - i < SLICE_MIN) {\n for (let k = i; k < end; k++) line += chunk[k]\n }\n else {\n line += chunk.slice(i, end)\n }\n i = end - 1\n }\n break\n case State.Esc:\n if (ch === '[') {\n state = State.Csi\n }\n else if (ch === ']' || ch === 'P' || ch === 'X' || ch === '^' || ch === '_') {\n state = State.Str\n strIsOsc = ch === ']'\n str = ''\n }\n else if (code >= 0x20 && code <= 0x2F) {\n // intermediate (e.g. `ESC ( B` charset): swallow the final byte next\n }\n else {\n state = State.Text\n }\n break\n case State.Csi:\n // parameters / intermediates until a final byte in @..~\n if (code >= 0x40 && code <= 0x7E)\n state = State.Text\n break\n case State.Str:\n if (code === 0x07) {\n endString()\n }\n else if (code === 0x1B) {\n state = State.StrEsc\n }\n else if (code === 0x9C) {\n endString()\n }\n else if (str.length < 4096) {\n str += ch\n }\n break\n case State.StrEsc:\n if (ch === '\\\\') {\n endString()\n }\n else {\n str += `\\x1B${ch}`\n state = State.Str\n }\n break\n }\n }\n return out\n },\n partial: () => line,\n takePartial() {\n const text = line\n if (text)\n taken = true\n line = ''\n return text\n },\n }\n}\n\n/** One-shot convenience: the plain text of a complete chunk of terminal output. */\nexport function stripAnsi(text: string): string {\n const s = createAnsiStripper()\n return s.push(text) + s.partial()\n}\n","/**\n * Shell / terminal spawn helpers of the in-process execution context.\n * Internal module.\n */\n\nimport type { ChildProcess } from 'node:child_process'\nimport type { ProcessContextState } from './process-state'\nimport type { BackgroundTerminalOptions, ExecResult } from './types'\nimport { createAnsiStripper } from './ansi-strip'\nimport { unavailableResult, wrapCommand } from './isolation'\nimport { ptyChildProcess, spawnLocalPty, TERMINAL_ENV } from './local-terminal'\n\nexport interface ProcessShell {\n shellCommand: (command: string) => { file: string, args: string[] }\n isolationBlocker: () => ExecResult | undefined\n spawnTerminalTask: (argv: string[], cwd: string, extraEnv: Record<string, string> | undefined, tty: BackgroundTerminalOptions) => ChildProcess\n terminalEnv: (extra?: Record<string, string>, unset?: readonly string[]) => Record<string, string>\n}\n\nexport function createProcessShell(s: ProcessContextState): ProcessShell {\n const { baseEnv, defaultEnv, isolation, isolationState } = s\n\n /**\n * `{ file, args }` for `/bin/sh -c command`, wrapped in the sandbox when\n * isolation is on. Callers check `isolationState.ok` first (the three\n * shell entry points return `unavailableResult` / throw before spawning).\n */\n function shellCommand(command: string): { file: string, args: string[] } {\n if (isolation && isolationState?.ok)\n return wrapCommand(isolationState.backend, isolationState.executable, isolation, command)\n return { file: '/bin/sh', args: ['-c', command] }\n }\n\n /** Failure result when isolation was requested but cannot be enforced; `undefined` = proceed. */\n function isolationBlocker(): ExecResult | undefined {\n return isolationState && !isolationState.ok ? unavailableResult(isolationState.reason) : undefined\n }\n\n /**\n * A background task in a PTY, as a `ChildProcess` look-alike whose stdout\n * carries the log text. A line still unfinished after a quiet moment (a\n * prompt waiting for input) is written out too, so the log shows it.\n */\n function spawnTerminalTask(argv: string[], cwd: string, extraEnv: Record<string, string> | undefined, tty: BackgroundTerminalOptions): ChildProcess {\n const stripper = createAnsiStripper()\n const decoder = new TextDecoder()\n let quiet: NodeJS.Timeout | undefined\n let emitLog: (text: string) => void = () => {}\n const flushPartial = () => {\n const rest = stripper.takePartial()\n if (rest)\n emitLog(rest)\n }\n const pty = spawnLocalPty(argv, {\n cwd,\n env: terminalEnv(extraEnv),\n cols: tty.cols,\n rows: tty.rows,\n onData: (data) => {\n tty.onData(data)\n const text = stripper.push(decoder.decode(data, { stream: true }))\n if (text)\n emitLog(text)\n if (quiet)\n clearTimeout(quiet)\n quiet = setTimeout(flushPartial, 300)\n quiet.unref?.()\n },\n })\n const { child, stdout } = ptyChildProcess(pty)\n const encoder = new TextEncoder()\n emitLog = text => stdout.emit('data', encoder.encode(text))\n void pty.exited.then(() => {\n if (quiet)\n clearTimeout(quiet)\n flushPartial()\n })\n tty.onReady?.({ write: pty.write, resize: pty.resize })\n return child\n }\n\n /** The environment of a terminal: what commands get, plus terminal identity, minus `unset`. */\n function terminalEnv(extra?: Record<string, string>, unset: readonly string[] = []): Record<string, string> {\n const env: Record<string, string> = {}\n for (const [key, value] of Object.entries({ ...baseEnv, ...defaultEnv, ...extra, ...TERMINAL_ENV })) {\n if (typeof value === 'string' && !unset.includes(key))\n env[key] = value\n }\n return env\n }\n\n return { shellCommand, isolationBlocker, spawnTerminalTask, terminalEnv }\n}\n","/**\n * Live bidirectional `execStream` of the in-process execution context.\n * Internal module.\n */\n\nimport type { ProcessShell } from './process-shell'\nimport type { ProcessContextState } from './process-state'\nimport type { ExecutionContext, ExecutionHandle, StreamHandle } from './types'\nimport { resolve } from 'node:path'\nimport { EXEC_KILL_ESCALATION_GRACE_MS, killProcessGroup, loadSpawn, SUPPORTS_PROCESS_GROUPS } from './process-state'\n\nexport function processStreamMethods(s: ProcessContextState, sh: ProcessShell): Required<Pick<ExecutionContext, 'execStream'>> {\n const { baseEnv, defaultEnv, registerExitHandler, streamChildren, trackSession } = s\n const { shellCommand, isolationBlocker } = sh\n\n return {\n /**\n * Live bidirectional stream to a child process — see\n * `ExecutionContext.execStream` for the seam contract.\n *\n * The reference implementation: an ordinary piped `spawn`, so both\n * streams stay separate and no terminal line discipline sits between\n * the caller and the child. Sandbox-backed contexts have to work\n * harder to reach the same shape.\n *\n * Unlike `execBackground`, nothing here lands in the `tasks` registry:\n * this handle is owned by its caller (an MCP transport's `close()`),\n * not by the model-facing background-task list that `shell_kill` /\n * `wait_task` walk. It IS tracked in `streamChildren` so the shared\n * orphan reaper and `destroy()` can sweep it — detached process-group\n * semantics (needed so `kill()` takes the child's own children with\n * it) are exactly what would otherwise leak a live server per crash.\n */\n async execStream(\n handle: ExecutionHandle,\n command: string,\n options?: { cwd?: string, env?: Record<string, string>, signal?: AbortSignal },\n ): Promise<StreamHandle> {\n const cwd = options?.cwd ? resolve(handle.cwd, options.cwd) : handle.cwd\n const spawnChild = await loadSpawn()\n\n options?.signal?.throwIfAborted()\n const blocked = isolationBlocker()\n if (blocked)\n throw new Error(blocked.stderr)\n\n const shell = shellCommand(command)\n const child = spawnChild(shell.file, shell.args, {\n cwd,\n env: { ...baseEnv, ...defaultEnv, ...options?.env },\n stdio: ['pipe', 'pipe', 'pipe'],\n detached: SUPPORTS_PROCESS_GROUPS,\n })\n\n // Same orphan-reaper coverage as `execBackground`: the detached\n // spawn (needed for kill-tree) means an unclean host exit (Ctrl+C,\n // uncaught exception, OOM) would otherwise leave the server running\n // indefinitely. Tracked in a side map rather than `tasks` — these\n // are caller-owned, invisible to `shell_kill` / `wait_task`.\n registerExitHandler()\n streamChildren.set(child, handle.id)\n const untrack = trackSession(child.pid)\n\n // A spawn failure (ENOENT on /bin/sh, EACCES on cwd) arrives as an\n // async 'error' event, never a throw. Without a listener Node\n // escalates it to an uncaughtException and takes the host down.\n let spawnError: Error | null = null\n child.on('error', (err) => { spawnError = err })\n\n let closed = false\n let escalation: ReturnType<typeof setTimeout> | undefined\n const exited = new Promise<number>((resolveExit) => {\n // 'close' rather than 'exit': it fires after the stdio streams\n // have flushed and ended, so a consumer awaiting `exited` can\n // trust that it has already seen every byte. `exit` can beat the\n // final stdout chunk and truncate the last protocol frame.\n child.once('close', (code, signalName) => {\n closed = true\n clearTimeout(escalation)\n streamChildren.delete(child)\n untrack()\n // Signal-killed children report a null code. Same mapping as\n // `execBackground`'s exit handler in process-background.ts — SIGTERM (our own\n // `kill()`) is the common case and lands on 143.\n resolveExit(\n code !== null\n ? code\n : signalName === 'SIGTERM'\n ? 143\n : signalName\n ? 128\n : 1,\n )\n })\n })\n\n /*\n * TERM the group, then KILL it if its pipes are still open after the\n * grace. Keyed on `close`, not on the shell's own exit: a TERM that\n * lands while the shell is forking (`sh -c 'echo up; sleep 30'`) kills\n * the shell but not the child it was starting, which keeps the pipes\n * (and `exited`) open for its whole life. Idempotent by contract.\n */\n const kill = async (): Promise<void> => {\n if (closed || child.pid === undefined)\n return\n killProcessGroup(child, 'SIGTERM')\n if (escalation)\n return\n escalation = setTimeout(killProcessGroup, EXEC_KILL_ESCALATION_GRACE_MS, child, 'SIGKILL')\n escalation.unref?.()\n }\n\n if (options?.signal) {\n if (options.signal.aborted) {\n void kill()\n }\n else {\n // Detach on exit: the signal is typically the RUN-long abort\n // signal, so a listener left behind after the child exits retains\n // the `kill` closure (and through it the ChildProcess) for the\n // rest of the run — one dead closure per exec on shell-heavy runs.\n const onAbort = () => { void kill() }\n const detach = () => options.signal!.removeEventListener('abort', onAbort)\n options.signal.addEventListener('abort', onAbort, { once: true })\n exited.then(detach, detach)\n }\n }\n\n return {\n pid: child.pid ?? -1,\n // Node's Readable is an async iterable of Buffer, and Buffer is a\n // Uint8Array — no adaptation needed on this context.\n stdout: child.stdout!,\n stderr: child.stderr!,\n write: async (data: Uint8Array): Promise<void> => {\n if (spawnError)\n throw spawnError\n const stdin = child.stdin\n if (!stdin || stdin.destroyed)\n throw new Error(`execStream: stdin is closed (pid ${child.pid ?? -1})`)\n // Resolve from the write callback, which fires once the chunk is\n // actually flushed to the pipe — that IS the backpressure signal,\n // so awaiting it pushes backpressure out to the caller. (Watching\n // the boolean return + 'drain' instead is a trap: for a small\n // write the callback runs synchronously, before the return value\n // is even bound.)\n await new Promise<void>((resolveWrite, rejectWrite) => {\n stdin.write(data, err => err ? rejectWrite(err) : resolveWrite())\n })\n },\n kill,\n exited,\n }\n },\n }\n}\n","/**\n * Background-task registry operations (kill / wait / reassign / list) and\n * `destroy` of the in-process execution context. Internal module.\n */\n\nimport type { ProcessContextState } from './process-state'\nimport type { ExecutionContext, ExecutionHandle, TaskEntry, TaskExitInfo, TaskStallInfo } from './types'\nimport { killProcessGroup, stateToTaskEntry, stateToTaskExitInfo } from './process-state'\n\nexport function processTaskMethods(s: ProcessContextState): Required<Pick<ExecutionContext, 'killBackground' | 'waitBackground' | 'reassignBackgroundTasks' | 'listBackground' | 'destroy'>> {\n const { tasks, destroyGraceMs, streamChildren, handles } = s\n\n return {\n async killBackground(handle: ExecutionHandle, taskId: string): Promise<TaskExitInfo | null> {\n const state = tasks.get(taskId)\n // Two miss cases collapse into one `null` return: unknown id, AND\n // known-id-but-not-owned-by-this-handle. The second case is the\n // subagent-can't-kill-parent-tasks defense; surfacing it as a\n // distinct error would leak the existence of the parent's task\n // to the subagent's model, which violates the per-handle\n // isolation contract.\n if (!state || state.handleId !== handle.id)\n return null\n // Already exited — return the cached info. We don't keep a\n // separate cached exit; the state itself carries every field\n // `TaskExitInfo` needs and `stateToTaskExitInfo` projects it.\n if (state.status !== 'running')\n return stateToTaskExitInfo(state)\n\n // Mark the intent BEFORE issuing the kill so the close handler\n // classifies the exit as `'killed'` even on platforms where the\n // SIGTERM-via-group lands faster than the close event drains.\n // (Checklist #14: at-most-once settle, plus correct status\n // classification regardless of event ordering.)\n state.killRequested = true\n\n // Wait for the existing close listener to fire — `settle()` does\n // all the flushing + onExit work. We just sit on a one-shot\n // promise tied to the `child.on('close')` we already registered\n // at spawn time.\n const closed = new Promise<void>((resolveP) => {\n if (state.settled) {\n resolveP()\n return\n }\n state.exitWatchers.push(() => resolveP())\n })\n\n killProcessGroup(state.child, 'SIGTERM')\n await closed\n return stateToTaskExitInfo(state)\n },\n\n async waitBackground(\n handle: ExecutionHandle,\n taskId: string,\n options?: { timeoutMs?: number, signal?: AbortSignal },\n ): Promise<TaskExitInfo | null> {\n const state = tasks.get(taskId)\n // Same two-misses-collapse-to-null contract as `killBackground`:\n // unknown id AND known-but-other-handle both return `null` so a\n // subagent can't observe the parent's tasks through the wait seam.\n if (!state || state.handleId !== handle.id)\n return null\n if (state.settled)\n return stateToTaskExitInfo(state)\n\n return new Promise<TaskExitInfo | null>((resolveP) => {\n let done = false\n let timer: NodeJS.Timeout | undefined\n const signal = options?.signal\n const finish = (value: TaskExitInfo | null): void => {\n if (done)\n return\n done = true\n if (timer)\n clearTimeout(timer)\n signal?.removeEventListener('abort', onAbort)\n const index = state.exitWatchers.indexOf(watcher)\n if (index >= 0)\n state.exitWatchers.splice(index, 1)\n resolveP(value)\n }\n function onAbort(): void {\n finish(null)\n }\n // A watcher alongside the owner's `onExit` (never replacing it —\n // the notification enqueue, a kill-waiter, a sibling waiter must\n // keep firing). Removed on timeout/abort so abandoned waits don't\n // pile up on a long-running task.\n const task = state\n function watcher(): void {\n finish(stateToTaskExitInfo(task))\n }\n state.exitWatchers.push(watcher)\n\n if (signal) {\n if (signal.aborted) {\n finish(null)\n return\n }\n signal.addEventListener('abort', onAbort, { once: true })\n }\n const timeoutMs = options?.timeoutMs\n if (typeof timeoutMs === 'number' && Number.isFinite(timeoutMs) && timeoutMs > 0) {\n timer = setTimeout(finish, timeoutMs, null)\n timer.unref?.()\n }\n })\n },\n\n async reassignBackgroundTasks(\n fromHandle: ExecutionHandle,\n toHandle: ExecutionHandle,\n newOnExit?: (info: TaskExitInfo) => void,\n newOnStall?: (info: TaskStallInfo) => void,\n ): Promise<readonly TaskEntry[]> {\n // `fromHandle === toHandle` keeps ownership and only rebinds the\n // callbacks — a host rebuilding the agent on a handle it keeps.\n const promoted: TaskEntry[] = []\n for (const state of tasks.values()) {\n if (state.handleId !== fromHandle.id || state.status !== 'running')\n continue\n state.handleId = toHandle.id\n // Replace the OWNER callbacks. The originals closed over the\n // spawning agent's hook bus, which is about to be destroyed —\n // without rewiring, the task's eventual `background:exit` (or a\n // stall) fires into a torn-down hookable and the new owner never\n // learns. In-flight kill/wait watchers are separate and survive.\n if (newOnExit)\n state.onExit = newOnExit\n if (newOnStall)\n state.onStall = newOnStall\n promoted.push(stateToTaskEntry(state))\n }\n return promoted\n },\n\n async listBackground(handle: ExecutionHandle): Promise<readonly TaskEntry[]> {\n // Snapshot — callers must not assume the returned array stays\n // in sync with the live registry. Sorted by startedAt so the\n // model / UI sees consistent ordering across calls. Scoped to\n // the calling handle so subagents don't see the parent's tasks\n // (and vice versa) in their listing.\n return [...tasks.values()]\n .filter(s => s.handleId === handle.id)\n .sort((a, b) => a.startedAt - b.startedAt)\n .map(stateToTaskEntry)\n },\n\n async destroy(handle: ExecutionHandle): Promise<void> {\n // Kill every still-running background task SPAWNED THROUGH THIS\n // HANDLE before tearing the handle down. SIGTERM the groups,\n // await the close + flush, THEN drop the registry entries.\n // Sequential — destroy is one-shot teardown, the few ms of extra\n // latency aren't worth the synchronization complexity.\n //\n // The handle scope matters when the same `ExecutionContext` is\n // shared across a parent agent and its `spawn`-ed subagents (the\n // default — `spawn.ts` passes `execution: ctx.execution`). Each\n // agent mints its own `ExecutionHandle` and registers its\n // background tasks under that handle's id. Without the filter,\n // a child agent's `destroy()` (fired by `spawn.ts`'s `finally`\n // when the subagent finishes / is cancelled) would walk the\n // shared registry and SIGTERM the parent's tasks too. So\n // cancelling a subagent that has its own background shells kills\n // just those subagent shells, leaving the parent's intact.\n const survivors = [...tasks.values()].filter(s => s.handleId === handle.id && !s.settled)\n await Promise.all(survivors.map(async (state) => {\n state.killRequested = true\n await new Promise<void>((resolveP) => {\n let graceTimer: NodeJS.Timeout | undefined\n state.exitWatchers.push(() => {\n if (graceTimer)\n clearTimeout(graceTimer)\n resolveP()\n })\n killProcessGroup(state.child, 'SIGTERM')\n // Bounded drain: a task that traps/ignores SIGTERM — or whose\n // `close` event is held back by an escaped grandchild (setsid'd\n // out of the process group) keeping the inherited stdio pipe\n // open — must not wedge `agent.destroy()` forever. After the\n // grace period, SIGKILL the group and stop waiting: `close`\n // may STILL never fire (the pipe holder isn't in the group),\n // so resolving here is the only way destroy() stays bounded.\n graceTimer = setTimeout(() => {\n killProcessGroup(state.child, 'SIGKILL')\n // settle() normally flushes + ends the log stream, but it\n // only runs off `close` — which we just gave up on. Tear the\n // stream down so the fd doesn't leak into a long-lived host.\n state.outputStream?.destroy()\n resolveP()\n }, destroyGraceMs)\n graceTimer.unref?.()\n })\n }))\n // Drop only this handle's tasks from the registry. Other handles\n // (siblings, parent) keep their entries.\n for (const [taskId, state] of tasks) {\n if (state.handleId === handle.id)\n tasks.delete(taskId)\n }\n // Stream children are caller-owned (the MCP transport's close(), which\n // the agent runs BEFORE executionContext.destroy()), so live entries\n // here mean the owner leaked them. Sweep this handle's slice — same\n // scoping rationale as the task loop above.\n for (const [child, ownerId] of streamChildren) {\n if (ownerId === handle.id) {\n killProcessGroup(child, 'SIGTERM')\n streamChildren.delete(child)\n }\n }\n handles.delete(handle.id)\n // Drop the orphan reaper ONLY when no handles remain — otherwise\n // a child's `destroy()` would strip the parent's safety net. The\n // reaper protects every still-tracked task in the context, so it\n // sticks around until the LAST handle is gone.\n //\n // Without this guard, the spawn-tool sequence\n // parent.spawn(child) → child.run() → child.destroy() (auto)\n // would deregister the handler mid-parent-lifetime. The parent's\n // own subsequent Ctrl+C orphan-kill safety would silently degrade.\n if (s.exitHandlerRegistered && handles.size === 0) {\n process.off('exit', s.exitHandler)\n s.exitHandlerRegistered = false\n }\n },\n }\n}\n","/**\n * In-process execution context.\n *\n * Runs everything in the current Node/Bun process.\n * No isolation — fastest, used as the default.\n */\n\nimport type { ContextCapabilities, ExecutionContext, ExecutionHandle, SpawnConfig, TerminalOptions, TerminalProcess } from './types'\nimport { mkdir, stat } from 'node:fs/promises'\nimport { resolve } from 'node:path'\nimport { hasLocalPty, localTerminalProcess, loginShell, spawnLocalPty } from './local-terminal'\nimport { processBackgroundMethods } from './process-background'\nimport { processExecMethods } from './process-exec'\nimport { processFileMethods } from './process-files'\nimport { createProcessShell } from './process-shell'\nimport { createProcessState } from './process-state'\nimport { processStreamMethods } from './process-stream'\nimport { processTaskMethods } from './process-tasks'\n\nexport { formatContextTimestamp, killProcessGroup, SUPPORTS_PROCESS_GROUPS, TASK_LOG_FILENAME_RE } from './process-state'\n\n/**\n * Creates an execution context that runs commands and file operations in the current process.\n * No isolation unless `config.isolation` asks for an OS sandbox. This is the default context.\n *\n * @param config - Default spawn settings, such as `cwd`, file containment root and isolation.\n *\n * @example\n * ```ts\n * import { createAgent } from 'zidane'\n * import { createProcessContext } from 'zidane/contexts'\n * import { basic } from 'zidane/presets'\n * import { anthropic } from 'zidane/providers/anthropic'\n *\n * const agent = createAgent({\n * ...basic,\n * provider: anthropic(),\n * execution: createProcessContext({ cwd: process.cwd() }),\n * })\n * ```\n */\nexport function createProcessContext(config?: SpawnConfig): ExecutionContext {\n const s = createProcessState(config)\n const { handles, defaultCwd, isolation, isolationState } = s\n const sh = createProcessShell(s)\n const { shellCommand, isolationBlocker, terminalEnv } = sh\n const files = processFileMethods(s)\n const execM = processExecMethods(s, sh)\n const streamM = processStreamMethods(s, sh)\n const bg = processBackgroundMethods(s, sh)\n const taskM = processTaskMethods(s)\n\n return {\n type: 'process',\n\n capabilities: {\n shell: true,\n filesystem: true,\n glob: true,\n network: true,\n gpu: false,\n stream: true,\n // Enforced, not requested: a requested sandbox whose backend is\n // missing fails every command closed, which is not \"isolated\".\n isolated: isolation !== undefined && isolationState?.ok === true,\n // Background tasks are OS children of this process's machine —\n // they survive `agent.destroy()` reassignment games but NOT a\n // host machine reboot, and the orphan reaper kills them on\n // process exit. That's the 'process-lifetime' tier.\n detachedTasks: 'process-lifetime',\n } satisfies ContextCapabilities,\n\n async spawn(overrides?: SpawnConfig): Promise<ExecutionHandle> {\n const id = `process-${++s.counter}`\n const cwd = overrides?.cwd ?? defaultCwd\n\n // Only create `cwd` when it is genuinely missing. An unconditional\n // `mkdir(cwd, { recursive: true })` on an already-existing directory is a\n // wasted write that needlessly demands FS-write permission — which breaks\n // read-only / no-write runtimes (Supabase Edge Functions write only to\n // `/tmp`; Deno edge isolates) where the cwd already exists. `stat` is a\n // read (permitted there); the write is attempted only on a confirmed\n // ENOENT. Any other stat failure (e.g. EACCES on a sandbox-restricted\n // path) must NOT escalate to a mkdir we'd also be denied — assume present\n // and let a later file op surface a precise error if it truly isn't.\n let needsCreate = false\n try {\n await stat(cwd)\n }\n catch (err) {\n needsCreate = (err as NodeJS.ErrnoException)?.code === 'ENOENT'\n }\n if (needsCreate)\n await mkdir(cwd, { recursive: true })\n\n const handle: ExecutionHandle = { id, type: 'process', cwd }\n handles.set(id, handle)\n return handle\n },\n\n exec: execM.exec,\n\n readFile: files.readFile,\n\n fileSize: files.fileSize,\n\n readFileBinary: files.readFileBinary,\n\n writeFile: files.writeFile,\n\n listFiles: files.listFiles,\n\n entries: files.entries,\n\n execStream: streamM.execStream,\n\n // Only where a PTY exists (Bun): no terminal beats a pretend one.\n ...(hasLocalPty()\n ? {\n async openTerminal(handle: ExecutionHandle, options: TerminalOptions): Promise<TerminalProcess> {\n const blocked = isolationBlocker()\n if (blocked)\n throw new Error(blocked.stderr)\n const env = terminalEnv(options.env, options.unsetEnv)\n const shell = loginShell(env)\n // Under OS isolation the shell runs inside the same sandbox as the agent's commands.\n const argv = isolation && isolationState?.ok\n ? (({ file, args }) => [file, ...args])(shellCommand(`exec ${JSON.stringify(shell)} -l`))\n : [shell, '-l']\n const pty = spawnLocalPty(argv, {\n cwd: options.cwd ? resolve(handle.cwd, options.cwd) : handle.cwd,\n env,\n cols: options.cols,\n rows: options.rows,\n onData: options.onData,\n })\n return localTerminalProcess(pty, { id: `pty-${pty.pid}` })\n },\n }\n : {}),\n\n execBackground: bg.execBackground,\n\n killBackground: taskM.killBackground,\n\n waitBackground: taskM.waitBackground,\n\n reassignBackgroundTasks: taskM.reassignBackgroundTasks,\n\n listBackground: taskM.listBackground,\n\n destroy: taskM.destroy,\n }\n}\n"],"mappings":"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"}
|