zidane 9.1.1 → 9.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{acp-Di9WvMDF.js → acp-Cl4gCZN6.js} +7 -7
- package/dist/{acp-Di9WvMDF.js.map → acp-Cl4gCZN6.js.map} +1 -1
- package/dist/acp-cli.js +5 -5
- package/dist/acp.d.ts +2 -2
- package/dist/acp.js +1 -1
- package/dist/{agent-DJhpTS-B.js → agent-Dh_XZ7fj.js} +74 -19
- package/dist/agent-Dh_XZ7fj.js.map +1 -0
- package/dist/agent.d.ts +1 -1
- package/dist/agent.js +1 -1
- package/dist/{auth-store-port-DFgf22oo.js → auth-store-port-DBl2JUC6.js} +2 -2
- package/dist/{auth-store-port-DFgf22oo.js.map → auth-store-port-DBl2JUC6.js.map} +1 -1
- package/dist/{auto-update-restart-BFB7Ek87.js → auto-update-restart-CF_kjcJd.js} +277 -41
- package/dist/auto-update-restart-CF_kjcJd.js.map +1 -0
- package/dist/{browser-BcoCCB_n.js → browser-BkdeKnxO.js} +56 -2
- package/dist/browser-BkdeKnxO.js.map +1 -0
- package/dist/{browser-entry-ypi8CyE-.d.ts → browser-entry-BCwruqNa.d.ts} +10 -10
- package/dist/{browser-entry-ypi8CyE-.d.ts.map → browser-entry-BCwruqNa.d.ts.map} +1 -1
- package/dist/channels.d.ts +5 -5
- package/dist/chat/browser.d.ts +4 -4
- package/dist/chat/browser.js +6 -6
- package/dist/chat/pure.d.ts +5 -5
- package/dist/chat/pure.js +8 -8
- package/dist/chat.d.ts +5 -5
- package/dist/chat.js +55 -55
- package/dist/chat.js.map +1 -1
- package/dist/{cli-shared-CabruH8Z.js → cli-shared-DIV9c5Nr.js} +4 -4
- package/dist/{cli-shared-CabruH8Z.js.map → cli-shared-DIV9c5Nr.js.map} +1 -1
- package/dist/cli-style-DBEm6CyT.js +105 -0
- package/dist/cli-style-DBEm6CyT.js.map +1 -0
- package/dist/{client-core-CIixwznM.d.ts → client-core-C_4m_oL6.d.ts} +4 -4
- package/dist/{client-core-CIixwznM.d.ts.map → client-core-C_4m_oL6.d.ts.map} +1 -1
- package/dist/{client-CCaIXWue.d.ts → client-ygTASGis.d.ts} +2 -2
- package/dist/{client-CCaIXWue.d.ts.map → client-ygTASGis.d.ts.map} +1 -1
- package/dist/codemode-worker.js +8 -5
- package/dist/codemode-worker.js.map +1 -1
- package/dist/codemode.d.ts +16 -0
- package/dist/codemode.d.ts.map +1 -1
- package/dist/codemode.js +2 -2
- package/dist/{connection-loop-QmWL-fJf.d.ts → connection-loop-D_pRONCr.d.ts} +4 -4
- package/dist/{connection-loop-QmWL-fJf.d.ts.map → connection-loop-D_pRONCr.d.ts.map} +1 -1
- package/dist/contexts/daytona.d.ts +3 -3
- package/dist/contexts/docker.d.ts +1 -1
- package/dist/contexts/e2b.d.ts +2 -2
- package/dist/contexts/sandbox.d.ts +1 -1
- package/dist/{contexts-C72b0mMa.js → contexts-DLZTSRHU.js} +17 -106
- package/dist/contexts-DLZTSRHU.js.map +1 -0
- package/dist/contexts.d.ts +4 -4
- package/dist/contexts.js +2 -2
- package/dist/{credentials-wwETW8rI.js → credentials-D71duF64.js} +2 -2
- package/dist/{credentials-wwETW8rI.js.map → credentials-D71duF64.js.map} +1 -1
- package/dist/{cwd-picker-CcekODCt.js → cwd-picker-BsHA6HKv.js} +4 -4
- package/dist/{cwd-picker-CcekODCt.js.map → cwd-picker-BsHA6HKv.js.map} +1 -1
- package/dist/daemon-cli.js +4 -3
- package/dist/daemon-cli.js.map +1 -1
- package/dist/{decisions-CXmK0nz9.js → decisions-hsw5XS2g.js} +3 -1
- package/dist/decisions-hsw5XS2g.js.map +1 -0
- package/dist/{discovery-DycXFxdA.js → discovery-DD4wPWKS.js} +4 -4
- package/dist/{discovery-DycXFxdA.js.map → discovery-DD4wPWKS.js.map} +1 -1
- package/dist/durable/sqlite.d.ts +2 -2
- package/dist/durable.d.ts +1 -1
- package/dist/{engine-VQ86XGdG.js → engine-BDmtgr2O.js} +6 -6
- package/dist/{engine-VQ86XGdG.js.map → engine-BDmtgr2O.js.map} +1 -1
- package/dist/{eval-Bod0I1W_.js → eval-CfGUDAkN.js} +3 -3
- package/dist/{eval-Bod0I1W_.js.map → eval-CfGUDAkN.js.map} +1 -1
- package/dist/eval.d.ts +1 -1
- package/dist/eval.js +1 -1
- package/dist/{executor-C7RQrkEq.js → executor-EWOhLyd9.js} +4 -4
- package/dist/{executor-C7RQrkEq.js.map → executor-EWOhLyd9.js.map} +1 -1
- package/dist/{extension-mark-BqKdEZwF.js → extension-mark-_rhkDWL5.js} +9 -6
- package/dist/extension-mark-_rhkDWL5.js.map +1 -0
- package/dist/extensions/testing.d.ts +1 -1
- package/dist/extensions/testing.js +2 -2
- package/dist/{extensions-BCx4QuGB.js → extensions-DklXPjiq.js} +8 -8
- package/dist/{extensions-BCx4QuGB.js.map → extensions-DklXPjiq.js.map} +1 -1
- package/dist/{extensions-client-D8tEAcMw.d.ts → extensions-client-D4Q2XRKV.d.ts} +31 -5
- package/dist/extensions-client-D4Q2XRKV.d.ts.map +1 -0
- package/dist/extensions.d.ts +1 -1
- package/dist/extensions.js +6 -6
- package/dist/{fold-rules-DvLK8pbf.d.ts → fold-rules-1DpDwG9h.d.ts} +2 -2
- package/dist/{fold-rules-DvLK8pbf.d.ts.map → fold-rules-1DpDwG9h.d.ts.map} +1 -1
- package/dist/{google-Crva32sk.js → google-BtMW9KzL.js} +2 -2
- package/dist/{google-Crva32sk.js.map → google-BtMW9KzL.js.map} +1 -1
- package/dist/{headless-CCm-jLLT.js → headless-CQm19BL0.js} +4 -4
- package/dist/{headless-CCm-jLLT.js.map → headless-CQm19BL0.js.map} +1 -1
- package/dist/headless.d.ts +1 -1
- package/dist/headless.js +1 -1
- package/dist/history-worker.js +1 -1
- package/dist/{host-BHMs9jsN.js → host-DEoEzQal.js} +13 -4
- package/dist/host-DEoEzQal.js.map +1 -0
- package/dist/{host-scoped-settings-CrbcqOkP.js → host-scoped-settings-WBYaCork.js} +2 -2
- package/dist/{host-scoped-settings-CrbcqOkP.js.map → host-scoped-settings-WBYaCork.js.map} +1 -1
- package/dist/{host-signals-Jsjd_-4g.js → host-signals-91zyko_i.js} +5 -5
- package/dist/{host-signals-Jsjd_-4g.js.map → host-signals-91zyko_i.js.map} +1 -1
- package/dist/{host-wO_6GW0y.js → host-uP3t08w8.js} +276 -103
- package/dist/host-uP3t08w8.js.map +1 -0
- package/dist/{host-version-CNAr9pov.js → host-version-_RHlAB29.js} +2 -2
- package/dist/{host-version-CNAr9pov.js.map → host-version-_RHlAB29.js.map} +1 -1
- package/dist/{index-C6nnKu32.d.ts → index-B0PLo9jn.d.ts} +4 -4
- package/dist/{index-C6nnKu32.d.ts.map → index-B0PLo9jn.d.ts.map} +1 -1
- package/dist/{index-Djnc8Peh.d.ts → index-De4x-s76.d.ts} +14 -14
- package/dist/{index-Djnc8Peh.d.ts.map → index-De4x-s76.d.ts.map} +1 -1
- package/dist/{index-CGbOWa7y.d.ts → index-WlE93Q6d.d.ts} +411 -3
- package/dist/index-WlE93Q6d.d.ts.map +1 -0
- package/dist/{index-CCf_WeTQ.d.ts → index-f-XWIoYo.d.ts} +2 -2
- package/dist/{index-CCf_WeTQ.d.ts.map → index-f-XWIoYo.d.ts.map} +1 -1
- package/dist/index.d.ts +5 -5
- package/dist/index.js +17 -17
- package/dist/ipc/browser-types.d.ts +304 -7
- package/dist/ipc/browser-types.d.ts.map +1 -1
- package/dist/ipc/browser.d.ts +4 -4
- package/dist/ipc/browser.js +2 -2
- package/dist/ipc/remote.d.ts +6 -6
- package/dist/ipc/remote.js +3 -3
- package/dist/{ipc-BzWhIybr.js → ipc-CatnsVEd.js} +4 -4
- package/dist/{ipc-BzWhIybr.js.map → ipc-CatnsVEd.js.map} +1 -1
- package/dist/ipc.d.ts +10 -10
- package/dist/ipc.js +8 -8
- package/dist/{json-Dj-YATkZ.js → json-BjClr43H.js} +2 -20
- package/dist/json-BjClr43H.js.map +1 -0
- package/dist/{links-CJG_rFvf.js → links-a8C9eby4.js} +9 -9
- package/dist/{links-CJG_rFvf.js.map → links-a8C9eby4.js.map} +1 -1
- package/dist/{loaded-entry-DTURJo_R.js → loaded-entry-D6jzt5HQ.js} +2 -2
- package/dist/{loaded-entry-DTURJo_R.js.map → loaded-entry-D6jzt5HQ.js.map} +1 -1
- package/dist/mcp.d.ts +1 -1
- package/dist/{media-type-BtA0cbfI.d.ts → media-type-ZSmAGHvg.d.ts} +188 -7
- package/dist/media-type-ZSmAGHvg.d.ts.map +1 -0
- package/dist/{memory-DuVGrzbl.js → memory-CJy52DNi.js} +132 -31
- package/dist/memory-CJy52DNi.js.map +1 -0
- package/dist/model-test-CAtJ76kM.js.map +1 -1
- package/dist/{move-session-kylExJ5H.js → move-session-D7ILECs-.js} +4 -4
- package/dist/{move-session-kylExJ5H.js.map → move-session-D7ILECs-.js.map} +1 -1
- package/dist/{nested-call-record-DlzPeTB7.js → nested-call-record-OayszZBQ.js} +4 -3
- package/dist/nested-call-record-OayszZBQ.js.map +1 -0
- package/dist/output/stream-json.d.ts +1 -1
- package/dist/output/terminal.d.ts +1 -1
- package/dist/{path-display-COVV71Yu.js → path-display-CAWz-sMq.js} +3 -3
- package/dist/{path-display-COVV71Yu.js.map → path-display-CAWz-sMq.js.map} +1 -1
- package/dist/plugins.d.ts +1 -1
- package/dist/{prelude-CVKoUzV8.js → prelude-BwiSR1uA.js} +16 -5
- package/dist/prelude-BwiSR1uA.js.map +1 -0
- package/dist/{presets-CBt6rFfS.js → presets-CMY43nUP.js} +3 -3
- package/dist/{presets-CBt6rFfS.js.map → presets-CMY43nUP.js.map} +1 -1
- package/dist/presets.d.ts +1 -1
- package/dist/presets.js +1 -1
- package/dist/{protocol-CEVqBO-q.d.ts → protocol-C2lqKuMd.d.ts} +50 -7
- package/dist/protocol-C2lqKuMd.d.ts.map +1 -0
- package/dist/protocol-DOGyHgLQ.js.map +1 -1
- package/dist/protocol-NSllElLw.js.map +1 -1
- package/dist/providers/anthropic.d.ts +1 -1
- package/dist/providers/arcee.d.ts +1 -1
- package/dist/providers/baseten.d.ts +1 -1
- package/dist/providers/cerebras.d.ts +1 -1
- package/dist/providers/google.d.ts +1 -1
- package/dist/providers/google.js +1 -1
- package/dist/providers/local.d.ts +1 -1
- package/dist/providers/neuralwatt.d.ts +1 -1
- package/dist/providers/openai-compat.d.ts +1 -1
- package/dist/providers/openai.d.ts +1 -1
- package/dist/providers/openrouter.d.ts +1 -1
- package/dist/providers/xai.d.ts +1 -1
- package/dist/{providers-Z0TaBp1O.js → providers-zVRxiJDv.js} +5 -5
- package/dist/providers-zVRxiJDv.js.map +1 -0
- package/dist/providers.d.ts +1 -1
- package/dist/providers.js +1 -1
- package/dist/{readonly-db-D7Z-k0pQ.js → readonly-db-DrbT8tX6.js} +2 -2
- package/dist/{readonly-db-D7Z-k0pQ.js.map → readonly-db-DrbT8tX6.js.map} +1 -1
- package/dist/{registry-BKjeBnoy.js → registry-CBoYDIND.js} +2 -2
- package/dist/{registry-BKjeBnoy.js.map → registry-CBoYDIND.js.map} +1 -1
- package/dist/{registry-B6Ww76iW.js → registry-CQOU5jvF.js} +2 -2
- package/dist/{registry-B6Ww76iW.js.map → registry-CQOU5jvF.js.map} +1 -1
- package/dist/{registry-B9INJwJR.js → registry-YUUqbYGr.js} +324 -39
- package/dist/registry-YUUqbYGr.js.map +1 -0
- package/dist/{remote-hosts-BMWoHCWO.js → remote-hosts-CT8Q95dR.js} +4 -4
- package/dist/{remote-hosts-BMWoHCWO.js.map → remote-hosts-CT8Q95dR.js.map} +1 -1
- package/dist/{repo-url-D4Dr8NfZ.js → repo-url-DLjjuVk_.js} +169 -2
- package/dist/repo-url-DLjjuVk_.js.map +1 -0
- package/dist/restate.d.ts +2 -2
- package/dist/{sandbox-BwiPGKF7.d.ts → sandbox-B4OW6oNx.d.ts} +2 -2
- package/dist/{sandbox-BwiPGKF7.d.ts.map → sandbox-B4OW6oNx.d.ts.map} +1 -1
- package/dist/script-progress-CrZ507Qq.js +900 -0
- package/dist/script-progress-CrZ507Qq.js.map +1 -0
- package/dist/session/sqlite.d.ts +1 -1
- package/dist/session.d.ts +1 -1
- package/dist/{setting-BQBSyUq0.js → setting-_jh2OtiL.js} +6 -6
- package/dist/{setting-BQBSyUq0.js.map → setting-_jh2OtiL.js.map} +1 -1
- package/dist/{settings-catalog-4IU2i_jG.js → settings-catalog-DEZlXP51.js} +14 -2
- package/dist/settings-catalog-DEZlXP51.js.map +1 -0
- package/dist/{settings-keys-iI_Y-7MC.js → settings-keys-BT0_oKjO.js} +3 -3
- package/dist/{settings-keys-iI_Y-7MC.js.map → settings-keys-BT0_oKjO.js.map} +1 -1
- package/dist/{skills-CFXRItJ6.js → skills-CEbosUlM.js} +2 -2
- package/dist/{skills-CFXRItJ6.js.map → skills-CEbosUlM.js.map} +1 -1
- package/dist/skills.d.ts +1 -1
- package/dist/skills.js +1 -1
- package/dist/{source-Bl1Z501r.js → source-3ZnEPOSa.js} +3 -2
- package/dist/source-3ZnEPOSa.js.map +1 -0
- package/dist/{sqlite-runtime-BZ2L4RaG.d.ts → sqlite-runtime-CS_LBaAN.d.ts} +2 -2
- package/dist/sqlite-runtime-CS_LBaAN.d.ts.map +1 -0
- package/dist/{src-BY_ND2xn.js → src-BmTXDta8.js} +2 -2
- package/dist/{src-BY_ND2xn.js.map → src-BmTXDta8.js.map} +1 -1
- package/dist/{store-C6gI7FfZ.js → store-ByCDaKgJ.js} +14 -3
- package/dist/store-ByCDaKgJ.js.map +1 -0
- package/dist/{system-freeze-m5o1sGIM.js → system-freeze-DxJ-lRhu.js} +3 -3
- package/dist/{system-freeze-m5o1sGIM.js.map → system-freeze-DxJ-lRhu.js.map} +1 -1
- package/dist/{todo-edits-CbukbjyV.js → todo-edits-Dyj32ds6.js} +4 -3
- package/dist/todo-edits-Dyj32ds6.js.map +1 -0
- package/dist/tools/fetch-url.d.ts +1 -1
- package/dist/tools/web-search.d.ts +1 -1
- package/dist/{tools-CVTGhggj.js → tools-BsrGQ8K4.js} +2 -2
- package/dist/{tools-CVTGhggj.js.map → tools-BsrGQ8K4.js.map} +1 -1
- package/dist/tools.d.ts +1 -1
- package/dist/tools.js +3 -3
- package/dist/{transcript-anchors-CiSi_UBn.js → transcript-anchors-DMjvyUjk.js} +3 -3
- package/dist/{transcript-anchors-CiSi_UBn.js.map → transcript-anchors-DMjvyUjk.js.map} +1 -1
- package/dist/{transcript-reconcile-jbSBjLq2.js → transcript-reconcile-DpQO85wl.js} +3 -3
- package/dist/{transcript-reconcile-jbSBjLq2.js.map → transcript-reconcile-DpQO85wl.js.map} +1 -1
- package/dist/tui.d.ts +9 -9
- package/dist/tui.d.ts.map +1 -1
- package/dist/tui.js +289 -38
- package/dist/tui.js.map +1 -1
- package/dist/{types-bDQagoiL.d.ts → types-2HrgolQz.d.ts} +20 -8
- package/dist/types-2HrgolQz.d.ts.map +1 -0
- package/dist/types-4q1bFG53.js +122 -0
- package/dist/types-4q1bFG53.js.map +1 -0
- package/dist/{types-DnRd9_cA.d.ts → types-SXqk6hLD.d.ts} +3 -3
- package/dist/{types-DnRd9_cA.d.ts.map → types-SXqk6hLD.d.ts.map} +1 -1
- package/dist/types-myxheQkw.js.map +1 -1
- package/dist/types.d.ts +3 -3
- package/dist/{usage-summary-BfcXjiSM.js → usage-summary-BM7B3JdI.js} +2 -2
- package/dist/{usage-summary-BfcXjiSM.js.map → usage-summary-BM7B3JdI.js.map} +1 -1
- package/dist/{version-DqqqvHDP.js → version-DwQI12WA.js} +2 -2
- package/dist/{version-DqqqvHDP.js.map → version-DwQI12WA.js.map} +1 -1
- package/dist/{wait-task-BX4NcOOm.js → wait-task-BiI5UaZQ.js} +13 -3
- package/dist/wait-task-BiI5UaZQ.js.map +1 -0
- package/dist/{wire-CLm2rMK0.js → wire-Dxwxb7QQ.js} +2 -2
- package/dist/{wire-CLm2rMK0.js.map → wire-Dxwxb7QQ.js.map} +1 -1
- package/dist/{write-file-0E6TUJ9A.js → write-file-Dquu7MzB.js} +5 -3
- package/dist/write-file-Dquu7MzB.js.map +1 -0
- package/dist/{ws-DfGGYQ4W.js → ws-CA3o2nie.js} +4 -4
- package/dist/{ws-DfGGYQ4W.js.map → ws-CA3o2nie.js.map} +1 -1
- package/dist/{ws-client-CFMbhsNq.js → ws-client-C0iPAAzc.js} +2 -2
- package/dist/{ws-client-CFMbhsNq.js.map → ws-client-C0iPAAzc.js.map} +1 -1
- package/docs/CHAT.md +55 -0
- package/docs/CODEMODE.md +37 -0
- package/docs/EXTENSIONS.md +8 -6
- package/docs/RELEASE-NOTES-NEXT.md +48 -1
- package/docs/RELEASE.md +9 -1
- package/package.json +2 -3
- package/dist/agent-DJhpTS-B.js.map +0 -1
- package/dist/auto-update-restart-BFB7Ek87.js.map +0 -1
- package/dist/browser-BcoCCB_n.js.map +0 -1
- package/dist/contexts-C72b0mMa.js.map +0 -1
- package/dist/decisions-CXmK0nz9.js.map +0 -1
- package/dist/extension-mark-BqKdEZwF.js.map +0 -1
- package/dist/extensions-client-D8tEAcMw.d.ts.map +0 -1
- package/dist/host-BHMs9jsN.js.map +0 -1
- package/dist/host-wO_6GW0y.js.map +0 -1
- package/dist/index-CGbOWa7y.d.ts.map +0 -1
- package/dist/json-Dj-YATkZ.js.map +0 -1
- package/dist/media-type-BtA0cbfI.d.ts.map +0 -1
- package/dist/memory-DuVGrzbl.js.map +0 -1
- package/dist/nested-call-events-BYk8XvGX.js +0 -182
- package/dist/nested-call-events-BYk8XvGX.js.map +0 -1
- package/dist/nested-call-record-DlzPeTB7.js.map +0 -1
- package/dist/prelude-CVKoUzV8.js.map +0 -1
- package/dist/protocol-CEVqBO-q.d.ts.map +0 -1
- package/dist/providers-Z0TaBp1O.js.map +0 -1
- package/dist/registry-B9INJwJR.js.map +0 -1
- package/dist/repo-url-D4Dr8NfZ.js.map +0 -1
- package/dist/settings-catalog-4IU2i_jG.js.map +0 -1
- package/dist/source-Bl1Z501r.js.map +0 -1
- package/dist/sqlite-runtime-BZ2L4RaG.d.ts.map +0 -1
- package/dist/store-C6gI7FfZ.js.map +0 -1
- package/dist/todo-edits-CbukbjyV.js.map +0 -1
- package/dist/types-DTMEhKJO.js +0 -14
- package/dist/types-DTMEhKJO.js.map +0 -1
- package/dist/types-bDQagoiL.d.ts.map +0 -1
- package/dist/wait-task-BX4NcOOm.js.map +0 -1
- package/dist/write-file-0E6TUJ9A.js.map +0 -1
- package/scripts/eval.ts +0 -179
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"host-scoped-settings-CrbcqOkP.js","names":[],"sources":["../src/chat/environment-settings.ts","../src/chat/host-scoped-settings.ts"],"sourcesContent":["/**\n * Environments in Settings — which kinds are offered, the default, and each\n * kind's options — plus the wire-safe descriptors every picker and settings\n * section renders. Shared by the chat host (daemon / GUI) and the TUI's local\n * runtime so both surfaces show and store exactly the same thing.\n *\n * Storage:\n * - `Settings.environments` (`state.json`, synced like every setting):\n * `{ defaultKind?, disabled?, config?: { [kind]: { [key]: value } } }`.\n * - Fields bound to a pre-existing setting (`field.setting`, e.g. Local's\n * OS sandbox → `Settings.sandbox`) read and write THAT key.\n * - `secret` fields live in the 0600 environment credential store\n * (`environment-credentials.ts`) and never reach a client — descriptors\n * only say whether one is configured (stored, or via its env var).\n *\n * Readers are tolerant (anything malformed reads as the default); writes go\n * through {@link applyEnvironmentSettingsChange}, which validates against the\n * provider's schema — the boundary check for every client.\n */\nimport type {\n EnvironmentConfig,\n EnvironmentConfigField,\n EnvironmentConfigValue,\n EnvironmentProvider,\n EnvironmentRegistry,\n} from './environment'\nimport { withTimeout } from '../timeout'\nimport { environmentTakesBranch, LOCAL_ENVIRONMENT, probeEnvironment } from './environment'\n\n/** `Settings.environments`. Every part optional: absent = defaults. */\nexport interface EnvironmentSettings {\n /** Kind new sessions start in. Default / invalid / disabled → `local`. */\n defaultKind?: string\n /** Kinds hidden from pickers and refused at creation. `local` can't be disabled. */\n disabled?: string[]\n /** Kinds turned on that are off by default (`provider.offByDefault`). */\n enabled?: string[]\n /** Per-kind options (non-secret, non-bound fields only). */\n config?: Record<string, Record<string, EnvironmentConfigValue>>\n}\n\n/** Where `secret` fields live — see `environment-credentials.ts`. */\nexport interface EnvironmentSecrets {\n /** Returns the stored secret for a kind and field key, or `undefined`. */\n get: (kind: string, key: string) => string | undefined\n /** `null` clears. */\n set: (kind: string, key: string, value: string | null) => void\n}\n\n/**\n * The settings object this module reads: `environments` plus any keys fields\n * are bound to (`field.setting`). Any `Settings`-shaped object fits.\n */\nexport type EnvironmentSettingsSource = object\n\nfunction boundSetting(settings: EnvironmentSettingsSource | undefined, key: string): unknown {\n return (settings as Record<string, unknown> | undefined)?.[key]\n}\n\n/**\n * Tolerant read of `Settings.environments`.\n *\n * @param settings - Settings object, or `undefined`.\n */\nexport function readEnvironmentSettings(settings: EnvironmentSettingsSource | undefined): Required<EnvironmentSettings> {\n const raw = (settings as { environments?: unknown } | undefined)?.environments\n const record = raw && typeof raw === 'object' && !Array.isArray(raw) ? raw as Record<string, unknown> : {}\n const kinds = (value: unknown): string[] => Array.isArray(value)\n ? [...new Set(value.filter((kind): kind is string => typeof kind === 'string' && kind !== LOCAL_ENVIRONMENT.kind))]\n : []\n const disabled = kinds(record.disabled)\n const enabled = kinds(record.enabled)\n const config: Record<string, Record<string, EnvironmentConfigValue>> = {}\n if (record.config && typeof record.config === 'object' && !Array.isArray(record.config)) {\n for (const [kind, values] of Object.entries(record.config as Record<string, unknown>)) {\n if (!values || typeof values !== 'object' || Array.isArray(values))\n continue\n const entries = Object.entries(values as Record<string, unknown>)\n .filter((entry): entry is [string, EnvironmentConfigValue] => ['string', 'number', 'boolean'].includes(typeof entry[1]))\n config[kind] = Object.fromEntries(entries)\n }\n }\n return {\n defaultKind: typeof record.defaultKind === 'string' && record.defaultKind ? record.defaultKind : LOCAL_ENVIRONMENT.kind,\n disabled,\n enabled,\n config,\n }\n}\n\n/**\n * Whether `kind` may be picked. `local` always can: it is the fallback. An\n * `offByDefault` provider needs turning on first — pass it to honour that.\n *\n * @param settings - Settings object, or `undefined`.\n * @param kind - Environment kind to check.\n * @param provider - The kind's provider. When it is `offByDefault`, the kind must also be turned on in settings.\n */\nexport function isEnvironmentEnabled(settings: EnvironmentSettingsSource | undefined, kind: string, provider?: Pick<EnvironmentProvider, 'offByDefault'>): boolean {\n if (kind === LOCAL_ENVIRONMENT.kind)\n return true\n const { disabled, enabled } = readEnvironmentSettings(settings)\n if (disabled.includes(kind))\n return false\n return provider?.offByDefault ? enabled.includes(kind) : true\n}\n\n/**\n * The default kind for new sessions: the configured one when registered and enabled, else `local`.\n *\n * @param registry - Registry of known environment kinds.\n * @param settings - Settings object, or `undefined`.\n */\nexport function defaultEnvironmentKind(registry: EnvironmentRegistry, settings: EnvironmentSettingsSource | undefined): string {\n const { defaultKind } = readEnvironmentSettings(settings)\n const provider = registry.get(defaultKind)\n return provider && isEnvironmentEnabled(settings, defaultKind, provider) ? defaultKind : LOCAL_ENVIRONMENT.kind\n}\n\n/** Coerce a stored / submitted value to the field's type; `undefined` when it doesn't fit. */\nfunction coerce(field: EnvironmentConfigField, value: unknown): EnvironmentConfigValue | undefined {\n switch (field.type) {\n case 'boolean':\n return typeof value === 'boolean' ? value : value === 'true' ? true : value === 'false' ? false : undefined\n case 'number': {\n const n = typeof value === 'number' ? value : typeof value === 'string' && value.trim() ? Number(value) : Number.NaN\n return Number.isFinite(n) ? n : undefined\n }\n case 'choice':\n return typeof value === 'string' && field.choices?.some(choice => choice.value === value) ? value : undefined\n default:\n return typeof value === 'string' ? value : undefined\n }\n}\n\n/** Where {@link resolveProviderConfig} reads option values from. */\nexport interface ResolveConfigContext {\n /** Settings object, or `undefined`. Supplies stored values and bound `field.setting` keys. */\n settings: EnvironmentSettingsSource | undefined\n /** Secret store that supplies `secret` fields. */\n secrets: EnvironmentSecrets\n /** Env-var fallbacks. Default: `process.env`. */\n env?: Record<string, string | undefined>\n}\n\n/**\n * A kind's effective options: bound settings, stored values, secrets, env-var\n * fallbacks, then schema defaults — in that order.\n *\n * @param provider - Provider whose `configSchema` defines the options.\n * @param context - Settings, secret store, and optional env-var source.\n */\nexport function resolveProviderConfig(provider: EnvironmentProvider, context: ResolveConfigContext): EnvironmentConfig {\n const env = context.env ?? process.env\n const stored = readEnvironmentSettings(context.settings).config[provider.kind] ?? {}\n const out: Record<string, EnvironmentConfigValue | undefined> = {}\n for (const field of provider.configSchema ?? []) {\n let value: EnvironmentConfigValue | undefined\n if (field.setting)\n value = coerce(field, boundSetting(context.settings, field.setting))\n else if (field.type === 'secret')\n value = context.secrets.get(provider.kind, field.key) || undefined\n else\n value = coerce(field, stored[field.key])\n if (value === undefined && field.env && env[field.env])\n value = coerce(field, env[field.env])\n out[field.key] = value ?? field.default\n }\n return out\n}\n\n// ---------------------------------------------------------------------------\n// Wire-safe descriptors (pickers + settings sections)\n// ---------------------------------------------------------------------------\n\n/** Wire-safe description of one environment option, for pickers and settings sections. */\nexport interface EnvironmentFieldDescriptor {\n /** Field key within the environment kind. */\n key: string\n /** Label shown next to the field. */\n label: string\n /** Help text for the field. */\n description?: string\n /** Value type of the field. */\n type: EnvironmentConfigField['type']\n /** Allowed values, for `choice` fields. */\n choices?: EnvironmentConfigField['choices']\n /** Placeholder shown in an empty input. */\n placeholder?: string\n /** Current value — omitted for secrets. */\n value?: EnvironmentConfigValue\n /** Schema default. Omitted for secrets. */\n default?: EnvironmentConfigValue\n /** Secrets: a value is stored, or its env var is set. */\n configured?: boolean\n /** Secrets / fallbacks: the env var currently supplying the value. */\n fromEnv?: string\n /** False while its `when` condition doesn't hold — renderers hide it. */\n visible: boolean\n}\n\n/**\n * Wire-safe description of one environment kind, as returned by {@link describeEnvironments}.\n */\nexport interface EnvironmentDescriptor {\n /** Environment kind id, such as `local`. */\n kind: string\n /** Name shown in pickers. */\n label: string\n /** Short description of the kind. */\n description?: string\n /** Whether the kind may be picked, per {@link isEnvironmentEnabled}. */\n enabled: boolean\n /** Whether new sessions start in this kind. */\n isDefault: boolean\n /** Can be offered for the requested folder right now. */\n available: boolean\n /** Why the kind is unavailable. Present only when `available` is `false`. */\n reason?: string\n /** Whether creating a session in this kind takes a branch name. */\n takesBranch: boolean\n /** Branch name the provider suggests, when `takesBranch` is `true`. */\n suggestedBranch?: string\n /** The kind has a \"Test connection\" (`provider.verify`). */\n canVerify: boolean\n /** What creating one here will do (`provider.note`), when available. */\n note?: string\n /** A machine's kind (`local@<name>`): which machine, and whether it is online now. */\n machine?: { id: string, name: string, status: 'online' | 'offline' }\n /** The kind's options, in schema order. */\n fields: EnvironmentFieldDescriptor[]\n}\n\n/**\n * How long a listing waits on one kind's `available` and `note` (a wedged\n * Docker daemon, a slow git). Past it the kind lists unavailable (no note), so\n * one kind never holds every picker. Creation probes again, unbounded.\n */\nexport const ENVIRONMENT_PROBE_TIMEOUT_MS = 5_000\n\n/**\n * Every registered kind, described for `cwd` — what `environments.list` returns.\n *\n * @param registry - Registry of known environment kinds.\n * @param context - Settings, secret store, optional env-var source, and the folder to check availability for (`machineOnly`: what the machine needs, not the folder).\n */\nexport async function describeEnvironments(\n registry: EnvironmentRegistry,\n context: ResolveConfigContext & { cwd: string, machineOnly?: boolean },\n): Promise<EnvironmentDescriptor[]> {\n const env = context.env ?? process.env\n const defaultKind = defaultEnvironmentKind(registry, context.settings)\n // A forgotten machine's kinds stay registered (a registry never drops one) but are not offered.\n const listed = registry.list().filter(provider => !provider.machine || provider.machine() !== undefined)\n return Promise.all(listed.map(async (provider) => {\n const config = resolveProviderConfig(provider, context)\n const machine = provider.machine?.()\n const bounded = <T>(work: Promise<T>, what: string) =>\n withTimeout(work, { operation: `${provider.label} ${what}`, timeoutMs: ENVIRONMENT_PROBE_TIMEOUT_MS })\n const availability = await bounded(probeEnvironment(provider, { cwd: context.cwd, config, ...(context.machineOnly ? { machineOnly: true } : {}) }), 'availability check')\n .catch(() => ({ ok: false as const, reason: `Checking ${provider.label} took too long.` }))\n const takesBranch = environmentTakesBranch(provider, config)\n const note = availability.ok && provider.note\n ? await bounded(provider.note({ cwd: context.cwd, config }), 'note').catch(() => undefined)\n : undefined\n return {\n kind: provider.kind,\n label: provider.label,\n ...(provider.description ? { description: provider.description } : {}),\n enabled: isEnvironmentEnabled(context.settings, provider.kind, provider),\n isDefault: provider.kind === defaultKind,\n available: availability.ok,\n ...(availability.ok ? {} : { reason: availability.reason }),\n takesBranch,\n ...(takesBranch && provider.suggestBranch ? { suggestedBranch: provider.suggestBranch(config) } : {}),\n canVerify: provider.verify !== undefined,\n ...(note ? { note } : {}),\n ...(machine ? { machine } : {}),\n fields: (provider.configSchema ?? []).map((field): EnvironmentFieldDescriptor => {\n const secret = field.type === 'secret'\n const stored = secret ? context.secrets.get(provider.kind, field.key) : undefined\n const envSupplied = field.env && env[field.env] && (secret ? !stored : config[field.key] === coerce(field, env[field.env])) ? field.env : undefined\n return {\n key: field.key,\n label: field.label,\n ...(field.description ? { description: field.description } : {}),\n type: field.type,\n ...(field.choices ? { choices: field.choices } : {}),\n ...(field.placeholder ? { placeholder: field.placeholder } : {}),\n ...(secret ? { configured: Boolean(stored) || Boolean(envSupplied) } : { value: config[field.key] }),\n ...(field.default !== undefined && !secret ? { default: field.default } : {}),\n ...(envSupplied ? { fromEnv: envSupplied } : {}),\n visible: !field.when || config[field.when.key] === field.when.equals,\n }\n }),\n }\n }))\n}\n\n// ---------------------------------------------------------------------------\n// Writes\n// ---------------------------------------------------------------------------\n\n/** One edit from a settings UI. */\nexport interface EnvironmentSettingsChange {\n /** Environment kind the edit targets. */\n kind: string\n /** Turn the kind on (`true`) or off (`false`). Omit to leave it unchanged. */\n enabled?: boolean\n /** Make this kind the default for new sessions (enables it). */\n makeDefault?: boolean\n /** Field values; `null` resets to the default (or clears a secret). */\n values?: Record<string, EnvironmentConfigValue | null>\n}\n\n/**\n * Result of {@link applyEnvironmentSettingsChange}: the settings and secret writes to perform.\n */\nexport interface EnvironmentSettingsWrite {\n /** Patch for `settings.set` — `environments` plus any bound keys. */\n settingsPatch: Record<string, unknown>\n /** Secret writes for the environment credential store. */\n secrets: Array<{ key: string, value: string | null }>\n}\n\n/**\n * Validate `change` against the kind's schema and turn it into a settings\n * patch + secret writes. Throws with a user-facing message on an unknown\n * kind or field, a value that doesn't fit its type, or disabling `local`.\n *\n * @param registry - Registry of known environment kinds.\n * @param settings - Current settings object, or `undefined`.\n * @param change - The edit to validate and apply.\n */\nexport function applyEnvironmentSettingsChange(\n registry: EnvironmentRegistry,\n settings: EnvironmentSettingsSource | undefined,\n change: EnvironmentSettingsChange,\n): EnvironmentSettingsWrite {\n const provider = registry.get(change.kind)\n if (!provider)\n throw new Error(`Unknown environment \"${change.kind}\".`)\n const current = readEnvironmentSettings(settings)\n const next: Required<EnvironmentSettings> = {\n defaultKind: current.defaultKind,\n disabled: [...current.disabled],\n enabled: [...current.enabled],\n config: { ...current.config, [change.kind]: { ...current.config[change.kind] } },\n }\n const settingsPatch: Record<string, unknown> = {}\n const secrets: Array<{ key: string, value: string | null }> = []\n\n if (change.enabled === false) {\n if (change.kind === LOCAL_ENVIRONMENT.kind)\n throw new Error('Local can\\'t be disabled: it is the fallback environment.')\n if (!next.disabled.includes(change.kind))\n next.disabled.push(change.kind)\n next.enabled = next.enabled.filter(kind => kind !== change.kind)\n if (next.defaultKind === change.kind)\n next.defaultKind = LOCAL_ENVIRONMENT.kind\n }\n if (change.enabled === true || change.makeDefault) {\n next.disabled = next.disabled.filter(kind => kind !== change.kind)\n if (provider.offByDefault && !next.enabled.includes(change.kind))\n next.enabled.push(change.kind)\n }\n if (change.makeDefault)\n next.defaultKind = change.kind\n\n for (const [key, raw] of Object.entries(change.values ?? {})) {\n const field = provider.configSchema?.find(candidate => candidate.key === key)\n if (!field)\n throw new Error(`${provider.label} has no option \"${key}\".`)\n if (field.type === 'secret') {\n if (raw !== null && typeof raw !== 'string')\n throw new Error(`${field.label} must be text.`)\n secrets.push({ key, value: raw === null || raw === '' ? null : raw })\n continue\n }\n const value = raw === null ? null : coerce(field, raw)\n if (value === undefined)\n throw new Error(`${field.label}: ${field.type === 'choice' ? `pick one of ${field.choices?.map(choice => choice.value).join(', ')}` : `expected a ${field.type}`}.`)\n if (field.setting) {\n settingsPatch[field.setting] = value ?? field.default\n continue\n }\n if (value === null)\n delete next.config[change.kind]![key]\n else\n next.config[change.kind]![key] = value\n }\n if (Object.keys(next.config[change.kind]!).length === 0)\n delete next.config[change.kind]\n settingsPatch.environments = next\n return { settingsPatch, secrets }\n}\n","/**\n * Which settings a host owns when a window edits it (the active session\n * runs on a server), and which stay the window's. Shared by the TUI's and\n * the GUI's Settings surfaces.\n *\n * Window-only: how the window looks and behaves (the UI category, theme,\n * fps, icons, keyboard and editor habits) and which hosts it uses\n * (`WINDOW_LOCAL_SETTINGS`). Everything else (safe mode, sandbox, limits,\n * compaction, the enabled skills / MCP servers / extensions…) shapes the\n * host's agents, so it is read with `settings.get` and written with\n * `settings.set` on that host, never into this computer's `state.json`.\n */\nimport type { ApprovalMode, Settings } from './types'\nimport { SETTINGS_CHOICES, SETTINGS_INPUTS, SETTINGS_TOGGLES } from './settings-catalog'\nimport { approvalModeFromSafeMode } from './settings-defaults'\n\n/**\n * Settings that belong to the window even while a host owns the settings\n * file (daemon or remote mode): which host the next launch uses.\n */\nexport const WINDOW_LOCAL_SETTINGS = ['useDaemon', 'remoteHosts'] as const satisfies readonly (keyof Settings)[]\n\n/** Agent-category keys that are still about the window, not the agents. */\nconst WINDOW_ONLY_KEYS: readonly (keyof Settings)[] = [\n 'theme',\n 'targetFps',\n 'mouseInteractions',\n 'uiMode',\n 'ctrlCBehavior',\n 'terminalTitle',\n 'sessionIcon',\n 'attentionIcon',\n 'activeIcon',\n 'thinkingBinding',\n 'toolCallDisplay',\n 'editDiffDisplay',\n 'transcriptDensity',\n 'resumeLastSession',\n 'externalEditor',\n 'inlineAutocomplete',\n 'checkForUpdates',\n 'autoInstallUpdates',\n 'subscriptionUsage',\n 'openIn',\n 'editor',\n // How this computer groups its sessions (the `spaces` toggle is `ui`, so window-only already).\n 'spaceList',\n // What this computer's new sessions start on: the model names its own accounts, the agent its extensions.\n 'defaultAgent',\n 'defaultModel',\n 'defaultEffort',\n 'defaultModelOptions',\n]\n\nconst WINDOW_ONLY: ReadonlySet<string> = new Set<string>([\n ...WINDOW_LOCAL_SETTINGS,\n ...WINDOW_ONLY_KEYS,\n ...[...SETTINGS_TOGGLES, ...SETTINGS_CHOICES, ...SETTINGS_INPUTS].filter(row => row.category === 'ui').map(row => row.key),\n])\n\n/**\n * Tells whether a settings key stays with the window instead of the host.\n *\n * @param key - Settings key to check.\n * @returns `true` for window-only keys (UI settings and {@link WINDOW_LOCAL_SETTINGS}).\n */\nexport function isWindowOnlySetting(key: keyof Settings | string): boolean {\n return WINDOW_ONLY.has(key)\n}\n\n/** The per-server lists a host leaving unset means its defaults for: everything enabled, each server's own `shared`. */\nexport const HOST_ENABLED_LISTS = ['enabledSkills', 'enabledMcps', 'enabledExtensions', 'enabledPlugins', 'disabledMcpTools', 'mcpSharing'] as const satisfies readonly (keyof Settings)[]\n\n/**\n * Settings as sent to a host or to a window. Peers older than `approvalMode`\n * know tool approvals only as the legacy `safeMode` boolean, so it rides\n * along; a current peer drops it (`settingsFromWire`).\n *\n * @param values - Settings, whole or partial; `safeMode` is added only when they carry `approvalMode`.\n */\nexport function settingsToWire<T extends object>(values: T): T & { safeMode?: boolean } {\n return 'approvalMode' in values ? { ...values, safeMode: values.approvalMode !== 'off' } : { ...values }\n}\n\n/**\n * Settings from a peer as this side reads them, without `safeMode`. Beside\n * a matching `approvalMode` it is only the copy `settingsToWire` adds;\n * alone, or contradicting an `approvalMode` (one a newer client stored on\n * an older server, which kept enforcing `safeMode`), it is the peer's\n * actual state and maps onto the approval mode.\n *\n * @param values - The received values.\n * @param current - The approval mode a lone `safeMode: true` keeps (unless `'off'`).\n */\nexport function settingsFromWire<T extends object>(values: T & { safeMode?: unknown }, current: ApprovalMode): Omit<T, 'safeMode'> {\n const { safeMode, ...rest } = values\n const stated = 'approvalMode' in rest ? rest.approvalMode : undefined\n if (typeof safeMode !== 'boolean' || (stated !== undefined && (stated !== 'off') === safeMode))\n return rest\n return { ...rest, approvalMode: approvalModeFromSafeMode(safeMode, stated === 'off' ? 'off' : current) }\n}\n\n/**\n * `local` with the host's values for every key the host owns.\n *\n * @param local - The window's own settings.\n * @param host - Settings read from the host (`settings.get`, `settings.set`). Window-only keys in it are ignored.\n */\nexport function overlayHostSettings<S extends Settings>(local: S, host: Partial<Settings> & { safeMode?: boolean }): S {\n const merged = { ...local } as Record<string, unknown>\n // A server older than `approvalMode` reports only `safeMode`, which asks when on.\n for (const [key, value] of Object.entries(settingsFromWire(host, 'ask'))) {\n if (!isWindowOnlySetting(key))\n merged[key] = value\n }\n // Allowlists the host leaves unset mean \"everything enabled\": not this window's lists.\n for (const key of HOST_ENABLED_LISTS) {\n if (!(key in host))\n delete merged[key]\n }\n return merged as S\n}\n\n/**\n * Split a settings patch into the window's part and the host's part.\n *\n * @param patch - Settings patch to partition by owner.\n */\nexport function splitHostSettingsPatch<S extends Partial<Settings>>(patch: S): { window: Partial<S>, host: Partial<S> } {\n const window: Record<string, unknown> = {}\n const host: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(patch))\n (isWindowOnlySetting(key) ? window : host)[key] = value\n return { window: window as Partial<S>, host: host as Partial<S> }\n}\n"],"mappings":";;;;AAuDA,SAAS,aAAa,UAAiD,KAAsB;CAC3F,OAAQ,WAAmD;AAC7D;;;;;;AAOA,SAAgB,wBAAwB,UAAgF;CACtH,MAAM,MAAO,UAAqD;CAClE,MAAM,SAAS,OAAO,OAAO,QAAQ,YAAY,CAAC,MAAM,QAAQ,GAAG,IAAI,MAAiC,CAAC;CACzG,MAAM,SAAS,UAA6B,MAAM,QAAQ,KAAK,IAC3D,CAAC,GAAG,IAAI,IAAI,MAAM,QAAQ,SAAyB,OAAO,SAAS,YAAY,SAAS,kBAAkB,IAAI,CAAC,CAAC,IAChH,CAAC;CACL,MAAM,WAAW,MAAM,OAAO,QAAQ;CACtC,MAAM,UAAU,MAAM,OAAO,OAAO;CACpC,MAAM,SAAiE,CAAC;CACxE,IAAI,OAAO,UAAU,OAAO,OAAO,WAAW,YAAY,CAAC,MAAM,QAAQ,OAAO,MAAM,GACpF,KAAK,MAAM,CAAC,MAAM,WAAW,OAAO,QAAQ,OAAO,MAAiC,GAAG;EACrF,IAAI,CAAC,UAAU,OAAO,WAAW,YAAY,MAAM,QAAQ,MAAM,GAC/D;EACF,MAAM,UAAU,OAAO,QAAQ,MAAiC,CAAC,CAC9D,QAAQ,UAAqD;GAAC;GAAU;GAAU;EAAS,CAAC,CAAC,SAAS,OAAO,MAAM,EAAE,CAAC;EACzH,OAAO,QAAQ,OAAO,YAAY,OAAO;CAC3C;CAEF,OAAO;EACL,aAAa,OAAO,OAAO,gBAAgB,YAAY,OAAO,cAAc,OAAO,cAAc,kBAAkB;EACnH;EACA;EACA;CACF;AACF;;;;;;;;;AAUA,SAAgB,qBAAqB,UAAiD,MAAc,UAA+D;CACjK,IAAI,SAAS,kBAAkB,MAC7B,OAAO;CACT,MAAM,EAAE,UAAU,YAAY,wBAAwB,QAAQ;CAC9D,IAAI,SAAS,SAAS,IAAI,GACxB,OAAO;CACT,OAAO,UAAU,eAAe,QAAQ,SAAS,IAAI,IAAI;AAC3D;;;;;;;AAQA,SAAgB,uBAAuB,UAA+B,UAAyD;CAC7H,MAAM,EAAE,gBAAgB,wBAAwB,QAAQ;CACxD,MAAM,WAAW,SAAS,IAAI,WAAW;CACzC,OAAO,YAAY,qBAAqB,UAAU,aAAa,QAAQ,IAAI,cAAc,kBAAkB;AAC7G;;AAGA,SAAS,OAAO,OAA+B,OAAoD;CACjG,QAAQ,MAAM,MAAd;EACE,KAAK,WACH,OAAO,OAAO,UAAU,YAAY,QAAQ,UAAU,SAAS,OAAO,UAAU,UAAU,QAAQ,KAAA;EACpG,KAAK,UAAU;GACb,MAAM,IAAI,OAAO,UAAU,WAAW,QAAQ,OAAO,UAAU,YAAY,MAAM,KAAK,IAAI,OAAO,KAAK,IAAI;GAC1G,OAAO,OAAO,SAAS,CAAC,IAAI,IAAI,KAAA;EAClC;EACA,KAAK,UACH,OAAO,OAAO,UAAU,YAAY,MAAM,SAAS,MAAK,WAAU,OAAO,UAAU,KAAK,IAAI,QAAQ,KAAA;EACtG,SACE,OAAO,OAAO,UAAU,WAAW,QAAQ,KAAA;CAC/C;AACF;;;;;;;;AAmBA,SAAgB,sBAAsB,UAA+B,SAAkD;CACrH,MAAM,MAAM,QAAQ,OAAO,QAAQ;CACnC,MAAM,SAAS,wBAAwB,QAAQ,QAAQ,CAAC,CAAC,OAAO,SAAS,SAAS,CAAC;CACnF,MAAM,MAA0D,CAAC;CACjE,KAAK,MAAM,SAAS,SAAS,gBAAgB,CAAC,GAAG;EAC/C,IAAI;EACJ,IAAI,MAAM,SACR,QAAQ,OAAO,OAAO,aAAa,QAAQ,UAAU,MAAM,OAAO,CAAC;OAChE,IAAI,MAAM,SAAS,UACtB,QAAQ,QAAQ,QAAQ,IAAI,SAAS,MAAM,MAAM,GAAG,KAAK,KAAA;OAEzD,QAAQ,OAAO,OAAO,OAAO,MAAM,IAAI;EACzC,IAAI,UAAU,KAAA,KAAa,MAAM,OAAO,IAAI,MAAM,MAChD,QAAQ,OAAO,OAAO,IAAI,MAAM,IAAI;EACtC,IAAI,MAAM,OAAO,SAAS,MAAM;CAClC;CACA,OAAO;AACT;;;;;;AAqEA,MAAa,+BAA+B;;;;;;;AAQ5C,eAAsB,qBACpB,UACA,SACkC;CAClC,MAAM,MAAM,QAAQ,OAAO,QAAQ;CACnC,MAAM,cAAc,uBAAuB,UAAU,QAAQ,QAAQ;CAErE,MAAM,SAAS,SAAS,KAAK,CAAC,CAAC,QAAO,aAAY,CAAC,SAAS,WAAW,SAAS,QAAQ,MAAM,KAAA,CAAS;CACvG,OAAO,QAAQ,IAAI,OAAO,IAAI,OAAO,aAAa;EAChD,MAAM,SAAS,sBAAsB,UAAU,OAAO;EACtD,MAAM,UAAU,SAAS,UAAU;EACnC,MAAM,WAAc,MAAkB,SACpC,YAAY,MAAM;GAAE,WAAW,GAAG,SAAS,MAAM,GAAG;GAAQ,WAAW;EAA6B,CAAC;EACvG,MAAM,eAAe,MAAM,QAAQ,iBAAiB,UAAU;GAAE,KAAK,QAAQ;GAAK;GAAQ,GAAI,QAAQ,cAAc,EAAE,aAAa,KAAK,IAAI,CAAC;EAAG,CAAC,GAAG,oBAAoB,CAAC,CACtK,aAAa;GAAE,IAAI;GAAgB,QAAQ,YAAY,SAAS,MAAM;EAAiB,EAAE;EAC5F,MAAM,cAAc,uBAAuB,UAAU,MAAM;EAC3D,MAAM,OAAO,aAAa,MAAM,SAAS,OACrC,MAAM,QAAQ,SAAS,KAAK;GAAE,KAAK,QAAQ;GAAK;EAAO,CAAC,GAAG,MAAM,CAAC,CAAC,YAAY,KAAA,CAAS,IACxF,KAAA;EACJ,OAAO;GACL,MAAM,SAAS;GACf,OAAO,SAAS;GAChB,GAAI,SAAS,cAAc,EAAE,aAAa,SAAS,YAAY,IAAI,CAAC;GACpE,SAAS,qBAAqB,QAAQ,UAAU,SAAS,MAAM,QAAQ;GACvE,WAAW,SAAS,SAAS;GAC7B,WAAW,aAAa;GACxB,GAAI,aAAa,KAAK,CAAC,IAAI,EAAE,QAAQ,aAAa,OAAO;GACzD;GACA,GAAI,eAAe,SAAS,gBAAgB,EAAE,iBAAiB,SAAS,cAAc,MAAM,EAAE,IAAI,CAAC;GACnG,WAAW,SAAS,WAAW,KAAA;GAC/B,GAAI,OAAO,EAAE,KAAK,IAAI,CAAC;GACvB,GAAI,UAAU,EAAE,QAAQ,IAAI,CAAC;GAC7B,SAAS,SAAS,gBAAgB,CAAC,EAAA,CAAG,KAAK,UAAsC;IAC/E,MAAM,SAAS,MAAM,SAAS;IAC9B,MAAM,SAAS,SAAS,QAAQ,QAAQ,IAAI,SAAS,MAAM,MAAM,GAAG,IAAI,KAAA;IACxE,MAAM,cAAc,MAAM,OAAO,IAAI,MAAM,SAAS,SAAS,CAAC,SAAS,OAAO,MAAM,SAAS,OAAO,OAAO,IAAI,MAAM,IAAI,KAAK,MAAM,MAAM,KAAA;IAC1I,OAAO;KACL,KAAK,MAAM;KACX,OAAO,MAAM;KACb,GAAI,MAAM,cAAc,EAAE,aAAa,MAAM,YAAY,IAAI,CAAC;KAC9D,MAAM,MAAM;KACZ,GAAI,MAAM,UAAU,EAAE,SAAS,MAAM,QAAQ,IAAI,CAAC;KAClD,GAAI,MAAM,cAAc,EAAE,aAAa,MAAM,YAAY,IAAI,CAAC;KAC9D,GAAI,SAAS,EAAE,YAAY,QAAQ,MAAM,KAAK,QAAQ,WAAW,EAAE,IAAI,EAAE,OAAO,OAAO,MAAM,KAAK;KAClG,GAAI,MAAM,YAAY,KAAA,KAAa,CAAC,SAAS,EAAE,SAAS,MAAM,QAAQ,IAAI,CAAC;KAC3E,GAAI,cAAc,EAAE,SAAS,YAAY,IAAI,CAAC;KAC9C,SAAS,CAAC,MAAM,QAAQ,OAAO,MAAM,KAAK,SAAS,MAAM,KAAK;IAChE;GACF,CAAC;EACH;CACF,CAAC,CAAC;AACJ;;;;;;;;;;AAqCA,SAAgB,+BACd,UACA,UACA,QAC0B;CAC1B,MAAM,WAAW,SAAS,IAAI,OAAO,IAAI;CACzC,IAAI,CAAC,UACH,MAAM,IAAI,MAAM,wBAAwB,OAAO,KAAK,GAAG;CACzD,MAAM,UAAU,wBAAwB,QAAQ;CAChD,MAAM,OAAsC;EAC1C,aAAa,QAAQ;EACrB,UAAU,CAAC,GAAG,QAAQ,QAAQ;EAC9B,SAAS,CAAC,GAAG,QAAQ,OAAO;EAC5B,QAAQ;GAAE,GAAG,QAAQ;IAAS,OAAO,OAAO,EAAE,GAAG,QAAQ,OAAO,OAAO,MAAM;EAAE;CACjF;CACA,MAAM,gBAAyC,CAAC;CAChD,MAAM,UAAwD,CAAC;CAE/D,IAAI,OAAO,YAAY,OAAO;EAC5B,IAAI,OAAO,SAAS,kBAAkB,MACpC,MAAM,IAAI,MAAM,0DAA2D;EAC7E,IAAI,CAAC,KAAK,SAAS,SAAS,OAAO,IAAI,GACrC,KAAK,SAAS,KAAK,OAAO,IAAI;EAChC,KAAK,UAAU,KAAK,QAAQ,QAAO,SAAQ,SAAS,OAAO,IAAI;EAC/D,IAAI,KAAK,gBAAgB,OAAO,MAC9B,KAAK,cAAc,kBAAkB;CACzC;CACA,IAAI,OAAO,YAAY,QAAQ,OAAO,aAAa;EACjD,KAAK,WAAW,KAAK,SAAS,QAAO,SAAQ,SAAS,OAAO,IAAI;EACjE,IAAI,SAAS,gBAAgB,CAAC,KAAK,QAAQ,SAAS,OAAO,IAAI,GAC7D,KAAK,QAAQ,KAAK,OAAO,IAAI;CACjC;CACA,IAAI,OAAO,aACT,KAAK,cAAc,OAAO;CAE5B,KAAK,MAAM,CAAC,KAAK,QAAQ,OAAO,QAAQ,OAAO,UAAU,CAAC,CAAC,GAAG;EAC5D,MAAM,QAAQ,SAAS,cAAc,MAAK,cAAa,UAAU,QAAQ,GAAG;EAC5E,IAAI,CAAC,OACH,MAAM,IAAI,MAAM,GAAG,SAAS,MAAM,kBAAkB,IAAI,GAAG;EAC7D,IAAI,MAAM,SAAS,UAAU;GAC3B,IAAI,QAAQ,QAAQ,OAAO,QAAQ,UACjC,MAAM,IAAI,MAAM,GAAG,MAAM,MAAM,eAAe;GAChD,QAAQ,KAAK;IAAE;IAAK,OAAO,QAAQ,QAAQ,QAAQ,KAAK,OAAO;GAAI,CAAC;GACpE;EACF;EACA,MAAM,QAAQ,QAAQ,OAAO,OAAO,OAAO,OAAO,GAAG;EACrD,IAAI,UAAU,KAAA,GACZ,MAAM,IAAI,MAAM,GAAG,MAAM,MAAM,IAAI,MAAM,SAAS,WAAW,eAAe,MAAM,SAAS,KAAI,WAAU,OAAO,KAAK,CAAC,CAAC,KAAK,IAAI,MAAM,cAAc,MAAM,OAAO,EAAE;EACrK,IAAI,MAAM,SAAS;GACjB,cAAc,MAAM,WAAW,SAAS,MAAM;GAC9C;EACF;EACA,IAAI,UAAU,MACZ,OAAO,KAAK,OAAO,OAAO,KAAK,CAAE;OAEjC,KAAK,OAAO,OAAO,KAAK,CAAE,OAAO;CACrC;CACA,IAAI,OAAO,KAAK,KAAK,OAAO,OAAO,KAAM,CAAC,CAAC,WAAW,GACpD,OAAO,KAAK,OAAO,OAAO;CAC5B,cAAc,eAAe;CAC7B,OAAO;EAAE;EAAe;CAAQ;AAClC;;;;;;;ACvXA,MAAa,wBAAwB,CAAC,aAAa,aAAa;;AAGhE,MAAM,mBAAgD;CACpD;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CAEA;CAEA;CACA;CACA;CACA;AACF;AAEA,MAAM,8BAAmC,IAAI,IAAY;CACvD,GAAG;CACH,GAAG;CACH,GAAG;EAAC,GAAG;EAAkB,GAAG;EAAkB,GAAG;CAAe,CAAC,CAAC,QAAO,QAAO,IAAI,aAAa,IAAI,CAAC,CAAC,KAAI,QAAO,IAAI,GAAG;AAC3H,CAAC;;;;;;;AAQD,SAAgB,oBAAoB,KAAuC;CACzE,OAAO,YAAY,IAAI,GAAG;AAC5B;;AAGA,MAAa,qBAAqB;CAAC;CAAiB;CAAe;CAAqB;CAAkB;CAAoB;AAAY;;;;;;;;AAS1I,SAAgB,eAAiC,QAAuC;CACtF,OAAO,kBAAkB,SAAS;EAAE,GAAG;EAAQ,UAAU,OAAO,iBAAiB;CAAM,IAAI,EAAE,GAAG,OAAO;AACzG;;;;;;;;;;;AAYA,SAAgB,iBAAmC,QAAoC,SAA4C;CACjI,MAAM,EAAE,UAAU,GAAG,SAAS;CAC9B,MAAM,SAAS,kBAAkB,OAAO,KAAK,eAAe,KAAA;CAC5D,IAAI,OAAO,aAAa,aAAc,WAAW,KAAA,KAAc,WAAW,UAAW,UACnF,OAAO;CACT,OAAO;EAAE,GAAG;EAAM,cAAc,yBAAyB,UAAU,WAAW,QAAQ,QAAQ,OAAO;CAAE;AACzG;;;;;;;AAQA,SAAgB,oBAAwC,OAAU,MAAqD;CACrH,MAAM,SAAS,EAAE,GAAG,MAAM;CAE1B,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,iBAAiB,MAAM,KAAK,CAAC,GACrE,IAAI,CAAC,oBAAoB,GAAG,GAC1B,OAAO,OAAO;CAGlB,KAAK,MAAM,OAAO,oBAChB,IAAI,EAAE,OAAO,OACX,OAAO,OAAO;CAElB,OAAO;AACT;;;;;;AAOA,SAAgB,uBAAoD,OAAoD;CACtH,MAAM,SAAkC,CAAC;CACzC,MAAM,OAAgC,CAAC;CACvC,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,KAAK,GAC7C,CAAC,oBAAoB,GAAG,IAAI,SAAS,KAAA,CAAM,OAAO;CACpD,OAAO;EAAU;EAA4B;CAAmB;AAClE"}
|
|
1
|
+
{"version":3,"file":"host-scoped-settings-WBYaCork.js","names":[],"sources":["../src/chat/environment-settings.ts","../src/chat/host-scoped-settings.ts"],"sourcesContent":["/**\n * Environments in Settings — which kinds are offered, the default, and each\n * kind's options — plus the wire-safe descriptors every picker and settings\n * section renders. Shared by the chat host (daemon / GUI) and the TUI's local\n * runtime so both surfaces show and store exactly the same thing.\n *\n * Storage:\n * - `Settings.environments` (`state.json`, synced like every setting):\n * `{ defaultKind?, disabled?, config?: { [kind]: { [key]: value } } }`.\n * - Fields bound to a pre-existing setting (`field.setting`, e.g. Local's\n * OS sandbox → `Settings.sandbox`) read and write THAT key.\n * - `secret` fields live in the 0600 environment credential store\n * (`environment-credentials.ts`) and never reach a client — descriptors\n * only say whether one is configured (stored, or via its env var).\n *\n * Readers are tolerant (anything malformed reads as the default); writes go\n * through {@link applyEnvironmentSettingsChange}, which validates against the\n * provider's schema — the boundary check for every client.\n */\nimport type {\n EnvironmentConfig,\n EnvironmentConfigField,\n EnvironmentConfigValue,\n EnvironmentProvider,\n EnvironmentRegistry,\n} from './environment'\nimport { withTimeout } from '../timeout'\nimport { environmentTakesBranch, LOCAL_ENVIRONMENT, probeEnvironment } from './environment'\n\n/** `Settings.environments`. Every part optional: absent = defaults. */\nexport interface EnvironmentSettings {\n /** Kind new sessions start in. Default / invalid / disabled → `local`. */\n defaultKind?: string\n /** Kinds hidden from pickers and refused at creation. `local` can't be disabled. */\n disabled?: string[]\n /** Kinds turned on that are off by default (`provider.offByDefault`). */\n enabled?: string[]\n /** Per-kind options (non-secret, non-bound fields only). */\n config?: Record<string, Record<string, EnvironmentConfigValue>>\n}\n\n/** Where `secret` fields live — see `environment-credentials.ts`. */\nexport interface EnvironmentSecrets {\n /** Returns the stored secret for a kind and field key, or `undefined`. */\n get: (kind: string, key: string) => string | undefined\n /** `null` clears. */\n set: (kind: string, key: string, value: string | null) => void\n}\n\n/**\n * The settings object this module reads: `environments` plus any keys fields\n * are bound to (`field.setting`). Any `Settings`-shaped object fits.\n */\nexport type EnvironmentSettingsSource = object\n\nfunction boundSetting(settings: EnvironmentSettingsSource | undefined, key: string): unknown {\n return (settings as Record<string, unknown> | undefined)?.[key]\n}\n\n/**\n * Tolerant read of `Settings.environments`.\n *\n * @param settings - Settings object, or `undefined`.\n */\nexport function readEnvironmentSettings(settings: EnvironmentSettingsSource | undefined): Required<EnvironmentSettings> {\n const raw = (settings as { environments?: unknown } | undefined)?.environments\n const record = raw && typeof raw === 'object' && !Array.isArray(raw) ? raw as Record<string, unknown> : {}\n const kinds = (value: unknown): string[] => Array.isArray(value)\n ? [...new Set(value.filter((kind): kind is string => typeof kind === 'string' && kind !== LOCAL_ENVIRONMENT.kind))]\n : []\n const disabled = kinds(record.disabled)\n const enabled = kinds(record.enabled)\n const config: Record<string, Record<string, EnvironmentConfigValue>> = {}\n if (record.config && typeof record.config === 'object' && !Array.isArray(record.config)) {\n for (const [kind, values] of Object.entries(record.config as Record<string, unknown>)) {\n if (!values || typeof values !== 'object' || Array.isArray(values))\n continue\n const entries = Object.entries(values as Record<string, unknown>)\n .filter((entry): entry is [string, EnvironmentConfigValue] => ['string', 'number', 'boolean'].includes(typeof entry[1]))\n config[kind] = Object.fromEntries(entries)\n }\n }\n return {\n defaultKind: typeof record.defaultKind === 'string' && record.defaultKind ? record.defaultKind : LOCAL_ENVIRONMENT.kind,\n disabled,\n enabled,\n config,\n }\n}\n\n/**\n * Whether `kind` may be picked. `local` always can: it is the fallback. An\n * `offByDefault` provider needs turning on first — pass it to honour that.\n *\n * @param settings - Settings object, or `undefined`.\n * @param kind - Environment kind to check.\n * @param provider - The kind's provider. When it is `offByDefault`, the kind must also be turned on in settings.\n */\nexport function isEnvironmentEnabled(settings: EnvironmentSettingsSource | undefined, kind: string, provider?: Pick<EnvironmentProvider, 'offByDefault'>): boolean {\n if (kind === LOCAL_ENVIRONMENT.kind)\n return true\n const { disabled, enabled } = readEnvironmentSettings(settings)\n if (disabled.includes(kind))\n return false\n return provider?.offByDefault ? enabled.includes(kind) : true\n}\n\n/**\n * The default kind for new sessions: the configured one when registered and enabled, else `local`.\n *\n * @param registry - Registry of known environment kinds.\n * @param settings - Settings object, or `undefined`.\n */\nexport function defaultEnvironmentKind(registry: EnvironmentRegistry, settings: EnvironmentSettingsSource | undefined): string {\n const { defaultKind } = readEnvironmentSettings(settings)\n const provider = registry.get(defaultKind)\n return provider && isEnvironmentEnabled(settings, defaultKind, provider) ? defaultKind : LOCAL_ENVIRONMENT.kind\n}\n\n/** Coerce a stored / submitted value to the field's type; `undefined` when it doesn't fit. */\nfunction coerce(field: EnvironmentConfigField, value: unknown): EnvironmentConfigValue | undefined {\n switch (field.type) {\n case 'boolean':\n return typeof value === 'boolean' ? value : value === 'true' ? true : value === 'false' ? false : undefined\n case 'number': {\n const n = typeof value === 'number' ? value : typeof value === 'string' && value.trim() ? Number(value) : Number.NaN\n return Number.isFinite(n) ? n : undefined\n }\n case 'choice':\n return typeof value === 'string' && field.choices?.some(choice => choice.value === value) ? value : undefined\n default:\n return typeof value === 'string' ? value : undefined\n }\n}\n\n/** Where {@link resolveProviderConfig} reads option values from. */\nexport interface ResolveConfigContext {\n /** Settings object, or `undefined`. Supplies stored values and bound `field.setting` keys. */\n settings: EnvironmentSettingsSource | undefined\n /** Secret store that supplies `secret` fields. */\n secrets: EnvironmentSecrets\n /** Env-var fallbacks. Default: `process.env`. */\n env?: Record<string, string | undefined>\n}\n\n/**\n * A kind's effective options: bound settings, stored values, secrets, env-var\n * fallbacks, then schema defaults — in that order.\n *\n * @param provider - Provider whose `configSchema` defines the options.\n * @param context - Settings, secret store, and optional env-var source.\n */\nexport function resolveProviderConfig(provider: EnvironmentProvider, context: ResolveConfigContext): EnvironmentConfig {\n const env = context.env ?? process.env\n const stored = readEnvironmentSettings(context.settings).config[provider.kind] ?? {}\n const out: Record<string, EnvironmentConfigValue | undefined> = {}\n for (const field of provider.configSchema ?? []) {\n let value: EnvironmentConfigValue | undefined\n if (field.setting)\n value = coerce(field, boundSetting(context.settings, field.setting))\n else if (field.type === 'secret')\n value = context.secrets.get(provider.kind, field.key) || undefined\n else\n value = coerce(field, stored[field.key])\n if (value === undefined && field.env && env[field.env])\n value = coerce(field, env[field.env])\n out[field.key] = value ?? field.default\n }\n return out\n}\n\n// ---------------------------------------------------------------------------\n// Wire-safe descriptors (pickers + settings sections)\n// ---------------------------------------------------------------------------\n\n/** Wire-safe description of one environment option, for pickers and settings sections. */\nexport interface EnvironmentFieldDescriptor {\n /** Field key within the environment kind. */\n key: string\n /** Label shown next to the field. */\n label: string\n /** Help text for the field. */\n description?: string\n /** Value type of the field. */\n type: EnvironmentConfigField['type']\n /** Allowed values, for `choice` fields. */\n choices?: EnvironmentConfigField['choices']\n /** Placeholder shown in an empty input. */\n placeholder?: string\n /** Current value — omitted for secrets. */\n value?: EnvironmentConfigValue\n /** Schema default. Omitted for secrets. */\n default?: EnvironmentConfigValue\n /** Secrets: a value is stored, or its env var is set. */\n configured?: boolean\n /** Secrets / fallbacks: the env var currently supplying the value. */\n fromEnv?: string\n /** False while its `when` condition doesn't hold — renderers hide it. */\n visible: boolean\n}\n\n/**\n * Wire-safe description of one environment kind, as returned by {@link describeEnvironments}.\n */\nexport interface EnvironmentDescriptor {\n /** Environment kind id, such as `local`. */\n kind: string\n /** Name shown in pickers. */\n label: string\n /** Short description of the kind. */\n description?: string\n /** Whether the kind may be picked, per {@link isEnvironmentEnabled}. */\n enabled: boolean\n /** Whether new sessions start in this kind. */\n isDefault: boolean\n /** Can be offered for the requested folder right now. */\n available: boolean\n /** Why the kind is unavailable. Present only when `available` is `false`. */\n reason?: string\n /** Whether creating a session in this kind takes a branch name. */\n takesBranch: boolean\n /** Branch name the provider suggests, when `takesBranch` is `true`. */\n suggestedBranch?: string\n /** The kind has a \"Test connection\" (`provider.verify`). */\n canVerify: boolean\n /** What creating one here will do (`provider.note`), when available. */\n note?: string\n /** A machine's kind (`local@<name>`): which machine, and whether it is online now. */\n machine?: { id: string, name: string, status: 'online' | 'offline' }\n /** The kind's options, in schema order. */\n fields: EnvironmentFieldDescriptor[]\n}\n\n/**\n * How long a listing waits on one kind's `available` and `note` (a wedged\n * Docker daemon, a slow git). Past it the kind lists unavailable (no note), so\n * one kind never holds every picker. Creation probes again, unbounded.\n */\nexport const ENVIRONMENT_PROBE_TIMEOUT_MS = 5_000\n\n/**\n * Every registered kind, described for `cwd` — what `environments.list` returns.\n *\n * @param registry - Registry of known environment kinds.\n * @param context - Settings, secret store, optional env-var source, and the folder to check availability for (`machineOnly`: what the machine needs, not the folder).\n */\nexport async function describeEnvironments(\n registry: EnvironmentRegistry,\n context: ResolveConfigContext & { cwd: string, machineOnly?: boolean },\n): Promise<EnvironmentDescriptor[]> {\n const env = context.env ?? process.env\n const defaultKind = defaultEnvironmentKind(registry, context.settings)\n // A forgotten machine's kinds stay registered (a registry never drops one) but are not offered.\n const listed = registry.list().filter(provider => !provider.machine || provider.machine() !== undefined)\n return Promise.all(listed.map(async (provider) => {\n const config = resolveProviderConfig(provider, context)\n const machine = provider.machine?.()\n const bounded = <T>(work: Promise<T>, what: string) =>\n withTimeout(work, { operation: `${provider.label} ${what}`, timeoutMs: ENVIRONMENT_PROBE_TIMEOUT_MS })\n const availability = await bounded(probeEnvironment(provider, { cwd: context.cwd, config, ...(context.machineOnly ? { machineOnly: true } : {}) }), 'availability check')\n .catch(() => ({ ok: false as const, reason: `Checking ${provider.label} took too long.` }))\n const takesBranch = environmentTakesBranch(provider, config)\n const note = availability.ok && provider.note\n ? await bounded(provider.note({ cwd: context.cwd, config }), 'note').catch(() => undefined)\n : undefined\n return {\n kind: provider.kind,\n label: provider.label,\n ...(provider.description ? { description: provider.description } : {}),\n enabled: isEnvironmentEnabled(context.settings, provider.kind, provider),\n isDefault: provider.kind === defaultKind,\n available: availability.ok,\n ...(availability.ok ? {} : { reason: availability.reason }),\n takesBranch,\n ...(takesBranch && provider.suggestBranch ? { suggestedBranch: provider.suggestBranch(config) } : {}),\n canVerify: provider.verify !== undefined,\n ...(note ? { note } : {}),\n ...(machine ? { machine } : {}),\n fields: (provider.configSchema ?? []).map((field): EnvironmentFieldDescriptor => {\n const secret = field.type === 'secret'\n const stored = secret ? context.secrets.get(provider.kind, field.key) : undefined\n const envSupplied = field.env && env[field.env] && (secret ? !stored : config[field.key] === coerce(field, env[field.env])) ? field.env : undefined\n return {\n key: field.key,\n label: field.label,\n ...(field.description ? { description: field.description } : {}),\n type: field.type,\n ...(field.choices ? { choices: field.choices } : {}),\n ...(field.placeholder ? { placeholder: field.placeholder } : {}),\n ...(secret ? { configured: Boolean(stored) || Boolean(envSupplied) } : { value: config[field.key] }),\n ...(field.default !== undefined && !secret ? { default: field.default } : {}),\n ...(envSupplied ? { fromEnv: envSupplied } : {}),\n visible: !field.when || config[field.when.key] === field.when.equals,\n }\n }),\n }\n }))\n}\n\n// ---------------------------------------------------------------------------\n// Writes\n// ---------------------------------------------------------------------------\n\n/** One edit from a settings UI. */\nexport interface EnvironmentSettingsChange {\n /** Environment kind the edit targets. */\n kind: string\n /** Turn the kind on (`true`) or off (`false`). Omit to leave it unchanged. */\n enabled?: boolean\n /** Make this kind the default for new sessions (enables it). */\n makeDefault?: boolean\n /** Field values; `null` resets to the default (or clears a secret). */\n values?: Record<string, EnvironmentConfigValue | null>\n}\n\n/**\n * Result of {@link applyEnvironmentSettingsChange}: the settings and secret writes to perform.\n */\nexport interface EnvironmentSettingsWrite {\n /** Patch for `settings.set` — `environments` plus any bound keys. */\n settingsPatch: Record<string, unknown>\n /** Secret writes for the environment credential store. */\n secrets: Array<{ key: string, value: string | null }>\n}\n\n/**\n * Validate `change` against the kind's schema and turn it into a settings\n * patch + secret writes. Throws with a user-facing message on an unknown\n * kind or field, a value that doesn't fit its type, or disabling `local`.\n *\n * @param registry - Registry of known environment kinds.\n * @param settings - Current settings object, or `undefined`.\n * @param change - The edit to validate and apply.\n */\nexport function applyEnvironmentSettingsChange(\n registry: EnvironmentRegistry,\n settings: EnvironmentSettingsSource | undefined,\n change: EnvironmentSettingsChange,\n): EnvironmentSettingsWrite {\n const provider = registry.get(change.kind)\n if (!provider)\n throw new Error(`Unknown environment \"${change.kind}\".`)\n const current = readEnvironmentSettings(settings)\n const next: Required<EnvironmentSettings> = {\n defaultKind: current.defaultKind,\n disabled: [...current.disabled],\n enabled: [...current.enabled],\n config: { ...current.config, [change.kind]: { ...current.config[change.kind] } },\n }\n const settingsPatch: Record<string, unknown> = {}\n const secrets: Array<{ key: string, value: string | null }> = []\n\n if (change.enabled === false) {\n if (change.kind === LOCAL_ENVIRONMENT.kind)\n throw new Error('Local can\\'t be disabled: it is the fallback environment.')\n if (!next.disabled.includes(change.kind))\n next.disabled.push(change.kind)\n next.enabled = next.enabled.filter(kind => kind !== change.kind)\n if (next.defaultKind === change.kind)\n next.defaultKind = LOCAL_ENVIRONMENT.kind\n }\n if (change.enabled === true || change.makeDefault) {\n next.disabled = next.disabled.filter(kind => kind !== change.kind)\n if (provider.offByDefault && !next.enabled.includes(change.kind))\n next.enabled.push(change.kind)\n }\n if (change.makeDefault)\n next.defaultKind = change.kind\n\n for (const [key, raw] of Object.entries(change.values ?? {})) {\n const field = provider.configSchema?.find(candidate => candidate.key === key)\n if (!field)\n throw new Error(`${provider.label} has no option \"${key}\".`)\n if (field.type === 'secret') {\n if (raw !== null && typeof raw !== 'string')\n throw new Error(`${field.label} must be text.`)\n secrets.push({ key, value: raw === null || raw === '' ? null : raw })\n continue\n }\n const value = raw === null ? null : coerce(field, raw)\n if (value === undefined)\n throw new Error(`${field.label}: ${field.type === 'choice' ? `pick one of ${field.choices?.map(choice => choice.value).join(', ')}` : `expected a ${field.type}`}.`)\n if (field.setting) {\n settingsPatch[field.setting] = value ?? field.default\n continue\n }\n if (value === null)\n delete next.config[change.kind]![key]\n else\n next.config[change.kind]![key] = value\n }\n if (Object.keys(next.config[change.kind]!).length === 0)\n delete next.config[change.kind]\n settingsPatch.environments = next\n return { settingsPatch, secrets }\n}\n","/**\n * Which settings a host owns when a window edits it (the active session\n * runs on a server), and which stay the window's. Shared by the TUI's and\n * the GUI's Settings surfaces.\n *\n * Window-only: how the window looks and behaves (the UI category, theme,\n * fps, icons, keyboard and editor habits) and which hosts it uses\n * (`WINDOW_LOCAL_SETTINGS`). Everything else (safe mode, sandbox, limits,\n * compaction, the enabled skills / MCP servers / extensions…) shapes the\n * host's agents, so it is read with `settings.get` and written with\n * `settings.set` on that host, never into this computer's `state.json`.\n */\nimport type { ApprovalMode, Settings } from './types'\nimport { SETTINGS_CHOICES, SETTINGS_INPUTS, SETTINGS_TOGGLES } from './settings-catalog'\nimport { approvalModeFromSafeMode } from './settings-defaults'\n\n/**\n * Settings that belong to the window even while a host owns the settings\n * file (daemon or remote mode): which host the next launch uses.\n */\nexport const WINDOW_LOCAL_SETTINGS = ['useDaemon', 'remoteHosts'] as const satisfies readonly (keyof Settings)[]\n\n/** Agent-category keys that are still about the window, not the agents. */\nconst WINDOW_ONLY_KEYS: readonly (keyof Settings)[] = [\n 'theme',\n 'targetFps',\n 'mouseInteractions',\n 'uiMode',\n 'ctrlCBehavior',\n 'terminalTitle',\n 'sessionIcon',\n 'attentionIcon',\n 'activeIcon',\n 'thinkingBinding',\n 'toolCallDisplay',\n 'editDiffDisplay',\n 'transcriptDensity',\n 'resumeLastSession',\n 'externalEditor',\n 'inlineAutocomplete',\n 'checkForUpdates',\n 'autoInstallUpdates',\n 'subscriptionUsage',\n 'openIn',\n 'editor',\n // How this computer groups its sessions (the `spaces` toggle is `ui`, so window-only already).\n 'spaceList',\n // What this computer's new sessions start on: the model names its own accounts, the agent its extensions.\n 'defaultAgent',\n 'defaultModel',\n 'defaultEffort',\n 'defaultModelOptions',\n]\n\nconst WINDOW_ONLY: ReadonlySet<string> = new Set<string>([\n ...WINDOW_LOCAL_SETTINGS,\n ...WINDOW_ONLY_KEYS,\n ...[...SETTINGS_TOGGLES, ...SETTINGS_CHOICES, ...SETTINGS_INPUTS].filter(row => row.category === 'ui').map(row => row.key),\n])\n\n/**\n * Tells whether a settings key stays with the window instead of the host.\n *\n * @param key - Settings key to check.\n * @returns `true` for window-only keys (UI settings and {@link WINDOW_LOCAL_SETTINGS}).\n */\nexport function isWindowOnlySetting(key: keyof Settings | string): boolean {\n return WINDOW_ONLY.has(key)\n}\n\n/** The per-server lists a host leaving unset means its defaults for: everything enabled, each server's own `shared`. */\nexport const HOST_ENABLED_LISTS = ['enabledSkills', 'enabledMcps', 'enabledExtensions', 'enabledPlugins', 'disabledMcpTools', 'mcpSharing'] as const satisfies readonly (keyof Settings)[]\n\n/**\n * Settings as sent to a host or to a window. Peers older than `approvalMode`\n * know tool approvals only as the legacy `safeMode` boolean, so it rides\n * along; a current peer drops it (`settingsFromWire`).\n *\n * @param values - Settings, whole or partial; `safeMode` is added only when they carry `approvalMode`.\n */\nexport function settingsToWire<T extends object>(values: T): T & { safeMode?: boolean } {\n return 'approvalMode' in values ? { ...values, safeMode: values.approvalMode !== 'off' } : { ...values }\n}\n\n/**\n * Settings from a peer as this side reads them, without `safeMode`. Beside\n * a matching `approvalMode` it is only the copy `settingsToWire` adds;\n * alone, or contradicting an `approvalMode` (one a newer client stored on\n * an older server, which kept enforcing `safeMode`), it is the peer's\n * actual state and maps onto the approval mode.\n *\n * @param values - The received values.\n * @param current - The approval mode a lone `safeMode: true` keeps (unless `'off'`).\n */\nexport function settingsFromWire<T extends object>(values: T & { safeMode?: unknown }, current: ApprovalMode): Omit<T, 'safeMode'> {\n const { safeMode, ...rest } = values\n const stated = 'approvalMode' in rest ? rest.approvalMode : undefined\n if (typeof safeMode !== 'boolean' || (stated !== undefined && (stated !== 'off') === safeMode))\n return rest\n return { ...rest, approvalMode: approvalModeFromSafeMode(safeMode, stated === 'off' ? 'off' : current) }\n}\n\n/**\n * `local` with the host's values for every key the host owns.\n *\n * @param local - The window's own settings.\n * @param host - Settings read from the host (`settings.get`, `settings.set`). Window-only keys in it are ignored.\n */\nexport function overlayHostSettings<S extends Settings>(local: S, host: Partial<Settings> & { safeMode?: boolean }): S {\n const merged = { ...local } as Record<string, unknown>\n // A server older than `approvalMode` reports only `safeMode`, which asks when on.\n for (const [key, value] of Object.entries(settingsFromWire(host, 'ask'))) {\n if (!isWindowOnlySetting(key))\n merged[key] = value\n }\n // Allowlists the host leaves unset mean \"everything enabled\": not this window's lists.\n for (const key of HOST_ENABLED_LISTS) {\n if (!(key in host))\n delete merged[key]\n }\n return merged as S\n}\n\n/**\n * Split a settings patch into the window's part and the host's part.\n *\n * @param patch - Settings patch to partition by owner.\n */\nexport function splitHostSettingsPatch<S extends Partial<Settings>>(patch: S): { window: Partial<S>, host: Partial<S> } {\n const window: Record<string, unknown> = {}\n const host: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(patch))\n (isWindowOnlySetting(key) ? window : host)[key] = value\n return { window: window as Partial<S>, host: host as Partial<S> }\n}\n"],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { A as connectOrSpawnDaemon, k as connectIpcClient } from "./memory-
|
|
1
|
+
import { A as connectOrSpawnDaemon, k as connectIpcClient } from "./memory-CJy52DNi.js";
|
|
2
2
|
import { t as JsonRpcConnectionClosedError } from "./json-rpc-G0rBfEar.js";
|
|
3
|
-
import { l as defaultSocketPath, p as selfDaemonSpawnCommand, u as ensureDaemonRunning } from "./settings-keys-
|
|
3
|
+
import { l as defaultSocketPath, p as selfDaemonSpawnCommand, u as ensureDaemonRunning } from "./settings-keys-BT0_oKjO.js";
|
|
4
4
|
//#region src/tui/runtime/transport.ts
|
|
5
5
|
/** The shared daemon over its socket; spawns one when none is listening. */
|
|
6
6
|
function socketTransport(options = {}) {
|
|
@@ -41,7 +41,7 @@ function wsTransport(options) {
|
|
|
41
41
|
return {
|
|
42
42
|
async connect(connectOptions = {}) {
|
|
43
43
|
connectOptions.signal?.throwIfAborted();
|
|
44
|
-
const { connectWsClient } = await import("./ws-client-
|
|
44
|
+
const { connectWsClient } = await import("./ws-client-C0iPAAzc.js").then((n) => n.i);
|
|
45
45
|
connectOptions.signal?.throwIfAborted();
|
|
46
46
|
return connectWsClient({
|
|
47
47
|
url: options.url,
|
|
@@ -53,7 +53,7 @@ function wsTransport(options) {
|
|
|
53
53
|
});
|
|
54
54
|
},
|
|
55
55
|
async classify(err) {
|
|
56
|
-
const { classifyWsFailure } = await import("./ws-
|
|
56
|
+
const { classifyWsFailure } = await import("./ws-CA3o2nie.js").then((n) => n.i);
|
|
57
57
|
return classifyWsFailure(err);
|
|
58
58
|
}
|
|
59
59
|
};
|
|
@@ -121,4 +121,4 @@ function hostSignalHandlers(sinks) {
|
|
|
121
121
|
//#endregion
|
|
122
122
|
export { wsTransport as i, lazyInProcessTransport as n, socketTransport as r, hostSignalHandlers as t };
|
|
123
123
|
|
|
124
|
-
//# sourceMappingURL=host-signals-
|
|
124
|
+
//# sourceMappingURL=host-signals-91zyko_i.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"host-signals-Jsjd_-4g.js","names":[],"sources":["../src/tui/runtime/transport.ts","../src/tui/host/host-signals.ts"],"sourcesContent":["/**\n * How a window reaches its chat host: the shared daemon over its unix\n * socket (spawned on demand), a host running in the window's own process,\n * or a remote server over a WebSocket.\n * Everything above the transport (`connectHostSession`, the presence\n * watcher) speaks `IpcClient` and cannot tell which one it got.\n */\nimport type { IpcClient } from '../../ipc/client'\nimport type { HostFailureKind } from '../../ipc/hosts/connection-loop'\nimport type { InProcessHost } from '../../ipc/memory'\nimport { JsonRpcConnectionClosedError } from '../../acp/json-rpc'\nimport { connectIpcClient, connectOrSpawnDaemon } from '../../ipc/client'\nimport { defaultSocketPath, ensureDaemonRunning, selfDaemonSpawnCommand } from '../../ipc/daemon/lifecycle'\n\nexport interface HostConnectOptions {\n appVersion?: string\n /** The connection dropped (daemon exit, socket error, host shutdown). Not called for `close()`. */\n onClose?: () => void\n /**\n * A watcher that must never retire a mismatched daemon (the presence\n * client): it connects to whatever is running and degrades instead.\n * Session controllers are active: a stale daemon is drained and respawned.\n * Meaningless in-process, where client and host are one build.\n */\n passive?: boolean\n /** Give up before connecting once aborted (the attempt was superseded). */\n signal?: AbortSignal\n}\n\nexport interface HostTransport {\n connect: (options?: HostConnectOptions) => Promise<IpcClient>\n /**\n * How a failed `connect` is handled (`../../ipc/hosts/connection-loop`):\n * a server's refusal for good, another protocol version, or \"retry\".\n * Absent: always retry (This computer's daemon).\n */\n classify?: (err: unknown) => Promise<HostFailureKind>\n}\n\n/** The shared daemon over its socket; spawns one when none is listening. */\nexport function socketTransport(options: { socketPath?: string, spawnCommand?: string[] } = {}): HostTransport {\n // Resolved once: a window keeps talking to the daemon it started with,\n // even if the environment that named it changes before a reconnect.\n const socketPath = { socketPath: options.socketPath ?? defaultSocketPath() }\n return {\n async connect(connectOptions = {}) {\n const spawnCommand = options.spawnCommand ?? selfDaemonSpawnCommand()\n const common = {\n ...(connectOptions.appVersion ? { appVersion: connectOptions.appVersion } : {}),\n ...(connectOptions.onClose ? { onClose: connectOptions.onClose } : {}),\n }\n if (connectOptions.passive) {\n const path = await ensureDaemonRunning({ ...socketPath, spawnCommand })\n connectOptions.signal?.throwIfAborted()\n return connectIpcClient({ ...common, socketPath: path, drainOnMismatch: false })\n }\n connectOptions.signal?.throwIfAborted()\n return connectOrSpawnDaemon({ ...common, ...socketPath, spawnCommand })\n },\n }\n}\n\n/**\n * A remote host over a WebSocket (`zidane-server`). Nothing to spawn and\n * nothing to drain: `passive` changes nothing, a version mismatch is the\n * server's to resolve. The WebSocket client loads on the first connect, so\n * a window that never goes remote never loads it.\n */\nexport function wsTransport(options: { url: string, token?: string, expectHostId?: string }): HostTransport {\n return {\n async connect(connectOptions = {}) {\n connectOptions.signal?.throwIfAborted()\n const { connectWsClient } = await import('../../ipc/transports/ws-client')\n connectOptions.signal?.throwIfAborted()\n return connectWsClient({\n url: options.url,\n ...(options.token ? { token: options.token } : {}),\n ...(options.expectHostId ? { expectHostId: options.expectHostId } : {}),\n ...(connectOptions.appVersion ? { appVersion: connectOptions.appVersion } : {}),\n ...(connectOptions.onClose ? { onClose: connectOptions.onClose } : {}),\n ...(connectOptions.signal ? { signal: connectOptions.signal } : {}),\n })\n },\n async classify(err) {\n const { classifyWsFailure } = await import('../../ipc/hosts/ws')\n return classifyWsFailure(err)\n },\n }\n}\n\n/** A host in this process (see `startInProcessHost`). */\nexport function inProcessTransport(host: InProcessHost): HostTransport {\n return {\n async connect(options = {}) {\n options.signal?.throwIfAborted()\n return host.connect({\n ...(options.appVersion ? { appVersion: options.appVersion } : {}),\n ...(options.onClose ? { onClose: options.onClose } : {}),\n })\n },\n }\n}\n\nexport interface LazyInProcessTransport extends HostTransport {\n /** The host, once a connect started it. */\n started: () => InProcessHost | null\n /**\n * Shut the host down if it started (runs suspend, clients' `onClose` fires)\n * and refuse later connects. Idempotent.\n */\n close: () => Promise<void>\n}\n\n/**\n * A host in this process, started by the first connect (a window that never\n * opens a session never builds one). A failed start is retried by the next.\n */\nexport function lazyInProcessTransport(start: () => Promise<InProcessHost>): LazyInProcessTransport {\n let starting: Promise<InProcessHost> | null = null\n let host: InProcessHost | null = null\n let closed = false\n const ensure = (): Promise<InProcessHost> => {\n starting ??= start().then(\n (started) => {\n host = started\n return started\n },\n (err: unknown) => {\n starting = null\n throw err\n },\n )\n return starting\n }\n return {\n async connect(options = {}) {\n if (closed)\n throw new JsonRpcConnectionClosedError()\n const started = await ensure()\n // Closed while starting: the close below shuts it down.\n if (closed)\n throw new JsonRpcConnectionClosedError()\n return inProcessTransport(started).connect(options)\n },\n started: () => host,\n async close() {\n closed = true\n const pending = starting\n if (!pending)\n return\n const started = await pending.catch(() => null)\n await started?.close()\n },\n }\n}\n","/**\n * What the window takes from a directory host's app-lifetime connection\n * (the shared connection loop's callbacks): its presence rows\n * (`presence.list` on connect, then `presence:changed`; none while it is\n * down) and its session changes (`sessions:changed`, which a host sends\n * every connection, watching a session or not). No WebSocket import.\n */\nimport type { HostSignal, IpcClient, SessionPresence } from '../../ipc/index'\n\nexport interface HostSignalSinks {\n onPresence?: (key: string, rows: readonly SessionPresence[]) => void\n /** Connected (also after a reconnect): the list should refresh. */\n onConnected?: (key: string) => void\n onSessionsChanged?: (key: string) => void\n}\n\nexport function hostSignalHandlers(sinks: HostSignalSinks): {\n onSignal: (key: string, signal: HostSignal) => void\n onConnected: (key: string, client: IpcClient) => void\n onDisconnected: (key: string) => void\n} {\n const { onPresence, onConnected, onSessionsChanged } = sinks\n return {\n onSignal: (key, signal) => {\n if (signal.kind === 'presence:changed')\n onPresence?.(key, signal.sessions)\n else if (signal.kind === 'sessions:changed')\n onSessionsChanged?.(key)\n },\n onConnected: (key, client) => {\n onConnected?.(key)\n if (onPresence)\n void client.request('presence.list', {}).then(rows => onPresence(key, rows), () => undefined)\n },\n onDisconnected: key => onPresence?.(key, []),\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"host-signals-91zyko_i.js","names":[],"sources":["../src/tui/runtime/transport.ts","../src/tui/host/host-signals.ts"],"sourcesContent":["/**\n * How a window reaches its chat host: the shared daemon over its unix\n * socket (spawned on demand), a host running in the window's own process,\n * or a remote server over a WebSocket.\n * Everything above the transport (`connectHostSession`, the presence\n * watcher) speaks `IpcClient` and cannot tell which one it got.\n */\nimport type { IpcClient } from '../../ipc/client'\nimport type { HostFailureKind } from '../../ipc/hosts/connection-loop'\nimport type { InProcessHost } from '../../ipc/memory'\nimport { JsonRpcConnectionClosedError } from '../../acp/json-rpc'\nimport { connectIpcClient, connectOrSpawnDaemon } from '../../ipc/client'\nimport { defaultSocketPath, ensureDaemonRunning, selfDaemonSpawnCommand } from '../../ipc/daemon/lifecycle'\n\nexport interface HostConnectOptions {\n appVersion?: string\n /** The connection dropped (daemon exit, socket error, host shutdown). Not called for `close()`. */\n onClose?: () => void\n /**\n * A watcher that must never retire a mismatched daemon (the presence\n * client): it connects to whatever is running and degrades instead.\n * Session controllers are active: a stale daemon is drained and respawned.\n * Meaningless in-process, where client and host are one build.\n */\n passive?: boolean\n /** Give up before connecting once aborted (the attempt was superseded). */\n signal?: AbortSignal\n}\n\nexport interface HostTransport {\n connect: (options?: HostConnectOptions) => Promise<IpcClient>\n /**\n * How a failed `connect` is handled (`../../ipc/hosts/connection-loop`):\n * a server's refusal for good, another protocol version, or \"retry\".\n * Absent: always retry (This computer's daemon).\n */\n classify?: (err: unknown) => Promise<HostFailureKind>\n}\n\n/** The shared daemon over its socket; spawns one when none is listening. */\nexport function socketTransport(options: { socketPath?: string, spawnCommand?: string[] } = {}): HostTransport {\n // Resolved once: a window keeps talking to the daemon it started with,\n // even if the environment that named it changes before a reconnect.\n const socketPath = { socketPath: options.socketPath ?? defaultSocketPath() }\n return {\n async connect(connectOptions = {}) {\n const spawnCommand = options.spawnCommand ?? selfDaemonSpawnCommand()\n const common = {\n ...(connectOptions.appVersion ? { appVersion: connectOptions.appVersion } : {}),\n ...(connectOptions.onClose ? { onClose: connectOptions.onClose } : {}),\n }\n if (connectOptions.passive) {\n const path = await ensureDaemonRunning({ ...socketPath, spawnCommand })\n connectOptions.signal?.throwIfAborted()\n return connectIpcClient({ ...common, socketPath: path, drainOnMismatch: false })\n }\n connectOptions.signal?.throwIfAborted()\n return connectOrSpawnDaemon({ ...common, ...socketPath, spawnCommand })\n },\n }\n}\n\n/**\n * A remote host over a WebSocket (`zidane-server`). Nothing to spawn and\n * nothing to drain: `passive` changes nothing, a version mismatch is the\n * server's to resolve. The WebSocket client loads on the first connect, so\n * a window that never goes remote never loads it.\n */\nexport function wsTransport(options: { url: string, token?: string, expectHostId?: string }): HostTransport {\n return {\n async connect(connectOptions = {}) {\n connectOptions.signal?.throwIfAborted()\n const { connectWsClient } = await import('../../ipc/transports/ws-client')\n connectOptions.signal?.throwIfAborted()\n return connectWsClient({\n url: options.url,\n ...(options.token ? { token: options.token } : {}),\n ...(options.expectHostId ? { expectHostId: options.expectHostId } : {}),\n ...(connectOptions.appVersion ? { appVersion: connectOptions.appVersion } : {}),\n ...(connectOptions.onClose ? { onClose: connectOptions.onClose } : {}),\n ...(connectOptions.signal ? { signal: connectOptions.signal } : {}),\n })\n },\n async classify(err) {\n const { classifyWsFailure } = await import('../../ipc/hosts/ws')\n return classifyWsFailure(err)\n },\n }\n}\n\n/** A host in this process (see `startInProcessHost`). */\nexport function inProcessTransport(host: InProcessHost): HostTransport {\n return {\n async connect(options = {}) {\n options.signal?.throwIfAborted()\n return host.connect({\n ...(options.appVersion ? { appVersion: options.appVersion } : {}),\n ...(options.onClose ? { onClose: options.onClose } : {}),\n })\n },\n }\n}\n\nexport interface LazyInProcessTransport extends HostTransport {\n /** The host, once a connect started it. */\n started: () => InProcessHost | null\n /**\n * Shut the host down if it started (runs suspend, clients' `onClose` fires)\n * and refuse later connects. Idempotent.\n */\n close: () => Promise<void>\n}\n\n/**\n * A host in this process, started by the first connect (a window that never\n * opens a session never builds one). A failed start is retried by the next.\n */\nexport function lazyInProcessTransport(start: () => Promise<InProcessHost>): LazyInProcessTransport {\n let starting: Promise<InProcessHost> | null = null\n let host: InProcessHost | null = null\n let closed = false\n const ensure = (): Promise<InProcessHost> => {\n starting ??= start().then(\n (started) => {\n host = started\n return started\n },\n (err: unknown) => {\n starting = null\n throw err\n },\n )\n return starting\n }\n return {\n async connect(options = {}) {\n if (closed)\n throw new JsonRpcConnectionClosedError()\n const started = await ensure()\n // Closed while starting: the close below shuts it down.\n if (closed)\n throw new JsonRpcConnectionClosedError()\n return inProcessTransport(started).connect(options)\n },\n started: () => host,\n async close() {\n closed = true\n const pending = starting\n if (!pending)\n return\n const started = await pending.catch(() => null)\n await started?.close()\n },\n }\n}\n","/**\n * What the window takes from a directory host's app-lifetime connection\n * (the shared connection loop's callbacks): its presence rows\n * (`presence.list` on connect, then `presence:changed`; none while it is\n * down) and its session changes (`sessions:changed`, which a host sends\n * every connection, watching a session or not). No WebSocket import.\n */\nimport type { HostSignal, IpcClient, SessionPresence } from '../../ipc/index'\n\nexport interface HostSignalSinks {\n onPresence?: (key: string, rows: readonly SessionPresence[]) => void\n /** Connected (also after a reconnect): the list should refresh. */\n onConnected?: (key: string) => void\n onSessionsChanged?: (key: string) => void\n}\n\nexport function hostSignalHandlers(sinks: HostSignalSinks): {\n onSignal: (key: string, signal: HostSignal) => void\n onConnected: (key: string, client: IpcClient) => void\n onDisconnected: (key: string) => void\n} {\n const { onPresence, onConnected, onSessionsChanged } = sinks\n return {\n onSignal: (key, signal) => {\n if (signal.kind === 'presence:changed')\n onPresence?.(key, signal.sessions)\n else if (signal.kind === 'sessions:changed')\n onSessionsChanged?.(key)\n },\n onConnected: (key, client) => {\n onConnected?.(key)\n if (onPresence)\n void client.request('presence.list', {}).then(rows => onPresence(key, rows), () => undefined)\n },\n onDisconnected: key => onPresence?.(key, []),\n }\n}\n"],"mappings":";;;;;AAwCA,SAAgB,gBAAgB,UAA4D,CAAC,GAAkB;CAG7G,MAAM,aAAa,EAAE,YAAY,QAAQ,cAAc,kBAAkB,EAAE;CAC3E,OAAO,EACL,MAAM,QAAQ,iBAAiB,CAAC,GAAG;EACjC,MAAM,eAAe,QAAQ,gBAAgB,uBAAuB;EACpE,MAAM,SAAS;GACb,GAAI,eAAe,aAAa,EAAE,YAAY,eAAe,WAAW,IAAI,CAAC;GAC7E,GAAI,eAAe,UAAU,EAAE,SAAS,eAAe,QAAQ,IAAI,CAAC;EACtE;EACA,IAAI,eAAe,SAAS;GAC1B,MAAM,OAAO,MAAM,oBAAoB;IAAE,GAAG;IAAY;GAAa,CAAC;GACtE,eAAe,QAAQ,eAAe;GACtC,OAAO,iBAAiB;IAAE,GAAG;IAAQ,YAAY;IAAM,iBAAiB;GAAM,CAAC;EACjF;EACA,eAAe,QAAQ,eAAe;EACtC,OAAO,qBAAqB;GAAE,GAAG;GAAQ,GAAG;GAAY;EAAa,CAAC;CACxE,EACF;AACF;;;;;;;AAQA,SAAgB,YAAY,SAAgF;CAC1G,OAAO;EACL,MAAM,QAAQ,iBAAiB,CAAC,GAAG;GACjC,eAAe,QAAQ,eAAe;GACtC,MAAM,EAAE,oBAAoB,MAAM,OAAO,0BAAiC,CAAA,MAAA,MAAA,EAAA,CAAA;GAC1E,eAAe,QAAQ,eAAe;GACtC,OAAO,gBAAgB;IACrB,KAAK,QAAQ;IACb,GAAI,QAAQ,QAAQ,EAAE,OAAO,QAAQ,MAAM,IAAI,CAAC;IAChD,GAAI,QAAQ,eAAe,EAAE,cAAc,QAAQ,aAAa,IAAI,CAAC;IACrE,GAAI,eAAe,aAAa,EAAE,YAAY,eAAe,WAAW,IAAI,CAAC;IAC7E,GAAI,eAAe,UAAU,EAAE,SAAS,eAAe,QAAQ,IAAI,CAAC;IACpE,GAAI,eAAe,SAAS,EAAE,QAAQ,eAAe,OAAO,IAAI,CAAC;GACnE,CAAC;EACH;EACA,MAAM,SAAS,KAAK;GAClB,MAAM,EAAE,sBAAsB,MAAM,OAAO,mBAAqB,CAAA,MAAA,MAAA,EAAA,CAAA;GAChE,OAAO,kBAAkB,GAAG;EAC9B;CACF;AACF;;AAGA,SAAgB,mBAAmB,MAAoC;CACrE,OAAO,EACL,MAAM,QAAQ,UAAU,CAAC,GAAG;EAC1B,QAAQ,QAAQ,eAAe;EAC/B,OAAO,KAAK,QAAQ;GAClB,GAAI,QAAQ,aAAa,EAAE,YAAY,QAAQ,WAAW,IAAI,CAAC;GAC/D,GAAI,QAAQ,UAAU,EAAE,SAAS,QAAQ,QAAQ,IAAI,CAAC;EACxD,CAAC;CACH,EACF;AACF;;;;;AAgBA,SAAgB,uBAAuB,OAA6D;CAClG,IAAI,WAA0C;CAC9C,IAAI,OAA6B;CACjC,IAAI,SAAS;CACb,MAAM,eAAuC;EAC3C,aAAa,MAAM,CAAC,CAAC,MAClB,YAAY;GACX,OAAO;GACP,OAAO;EACT,IACC,QAAiB;GAChB,WAAW;GACX,MAAM;EACR,CACF;EACA,OAAO;CACT;CACA,OAAO;EACL,MAAM,QAAQ,UAAU,CAAC,GAAG;GAC1B,IAAI,QACF,MAAM,IAAI,6BAA6B;GACzC,MAAM,UAAU,MAAM,OAAO;GAE7B,IAAI,QACF,MAAM,IAAI,6BAA6B;GACzC,OAAO,mBAAmB,OAAO,CAAC,CAAC,QAAQ,OAAO;EACpD;EACA,eAAe;EACf,MAAM,QAAQ;GACZ,SAAS;GACT,MAAM,UAAU;GAChB,IAAI,CAAC,SACH;GAEF,OAAM,MADgB,QAAQ,YAAY,IAAI,EAAA,EAC/B,MAAM;EACvB;CACF;AACF;;;AC1IA,SAAgB,mBAAmB,OAIjC;CACA,MAAM,EAAE,YAAY,aAAa,sBAAsB;CACvD,OAAO;EACL,WAAW,KAAK,WAAW;GACzB,IAAI,OAAO,SAAS,oBAClB,aAAa,KAAK,OAAO,QAAQ;QAC9B,IAAI,OAAO,SAAS,oBACvB,oBAAoB,GAAG;EAC3B;EACA,cAAc,KAAK,WAAW;GAC5B,cAAc,GAAG;GACjB,IAAI,YACF,OAAY,QAAQ,iBAAiB,CAAC,CAAC,CAAC,CAAC,MAAK,SAAQ,WAAW,KAAK,IAAI,SAAS,KAAA,CAAS;EAChG;EACA,iBAAgB,QAAO,aAAa,KAAK,CAAC,CAAC;CAC7C;AACF"}
|