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 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extensions-BCx4QuGB.js","names":[],"sources":["../src/extensions/bundle/policy.ts","../src/extensions/bundle/entries.ts","../src/extensions/completion-providers.ts","../src/extensions/config.ts","../src/extensions/config-actions.ts","../src/extensions/provider-oauth.ts","../src/extensions/runtime/registry-view.ts","../src/extensions/register.ts","../src/extensions/runtime/reload.ts","../src/extensions/declarative/config.ts","../src/extensions/install.ts","../src/extensions/declarative/lock.ts","../src/extensions/declarative/plan.ts","../src/extensions/declarative/reconcile.ts","../src/extensions/declarative/node.ts","../src/extensions/declarative/host-sync.ts","../src/extensions/declarative/settings-layer.ts","../src/extensions/discover-and-build.ts","../src/extensions/integrations/oauth-provider-method.ts","../src/extensions/panel-host.ts","../src/extensions/prompt-bridge.ts","../src/extensions/api/contracts.ts","../src/extensions/shared-watches.ts"],"sourcesContent":["/**\n * What a `ui.tsx` entry may import. The entry runs in the desktop and web\n * renderer, next to the host's own React and zidane-ui, so those stay\n * external (the renderer hands its live modules in); everything else the\n * extension ships is bundled into the one module the renderer loads. App\n * internals, TUI-only, Electron and Node modules do not exist there: an\n * import of one fails the build with a message that says where it belongs.\n *\n * Pure: the bundler backend (`./compile-ui`) asks {@link classifyUiImport}\n * for each import, so another backend (esbuild in a Node host) reuses it.\n */\n\nimport { isBuiltin } from 'node:module'\nimport { isAbsolute, relative, resolve, sep } from 'node:path'\n\n/**\n * Bare specifiers kept external in a bundled `ui` entry: the renderer's\n * shared modules. `zidane` and `zidane/extensions` are usually imported\n * for types only (erased); a value import of them stays external and the\n * renderer must map it.\n */\nexport const UI_HOST_MODULES: readonly string[] = [\n 'react',\n 'react/jsx-runtime',\n 'react/jsx-dev-runtime',\n 'react-dom',\n 'react-dom/client',\n 'zidane-ui',\n 'zidane',\n 'zidane/extensions',\n]\n\n/** Prefixes whose every subpath is a host module (`zidane-ui/extensions/kit`, …). */\nconst HOST_MODULE_PREFIXES: readonly string[] = ['zidane-ui/', 'react-dom/']\n\n/** How the bundler treats one import of a `ui` entry. */\nexport type UiImportVerdict\n = | { kind: 'external' }\n | { kind: 'bundle' }\n | { kind: 'error', message: string }\n\n/**\n * Whether `specifier` names a module the renderer provides.\n *\n * @param specifier - The import specifier as written.\n * @param extra - More host modules the caller allows.\n */\nexport function isUiHostModule(specifier: string, extra: readonly string[] = []): boolean {\n return UI_HOST_MODULES.includes(specifier)\n || extra.includes(specifier)\n || HOST_MODULE_PREFIXES.some(prefix => specifier.startsWith(prefix))\n}\n\nfunction isInside(path: string, root: string): boolean {\n const rel = relative(root, path)\n return rel === '' || (!rel.startsWith('..') && !isAbsolute(rel))\n}\n\nfunction inNodeModules(path: string): boolean {\n return path.split(sep).includes('node_modules')\n}\n\n/**\n * Decides one import of a `ui` entry's graph.\n *\n * - Host modules ({@link UI_HOST_MODULES}) stay external.\n * - Other `zidane/*` entries, `@opentui/*`, `electron`, `bun:*` and Node\n * built-ins are errors: the renderer has none of them.\n * - A relative or absolute path from the extension's own files must stay in\n * the extension folder (app internals such as `../../src/chat` are refused).\n * Files inside `node_modules` may import what they like within their package.\n * - Everything else (local files, packages) is bundled.\n *\n * @param specifier - The import specifier as written.\n * @param importer - The real path of the importing file.\n * @param root - The real path of the extension folder.\n * @param extra - More host modules the caller allows.\n */\nexport function classifyUiImport(specifier: string, importer: string, root: string, extra: readonly string[] = []): UiImportVerdict {\n if (isUiHostModule(specifier, extra))\n return { kind: 'external' }\n const from = importer ? ` (imported by ${relative(root, importer) || importer})` : ''\n if (specifier === 'zidane' || specifier.startsWith('zidane/')) {\n return { kind: 'error', message: `\"${specifier}\"${from} is not available to a ui entry: the renderer only provides ${UI_HOST_MODULES.join(', ')} and zidane-ui/*. Reach the backend through useRpc and useStore.` }\n }\n if (specifier.startsWith('@opentui/'))\n return { kind: 'error', message: `\"${specifier}\"${from} is the terminal renderer: import it from the tui entry, not the ui entry.` }\n if (specifier === 'electron' || specifier.startsWith('electron/'))\n return { kind: 'error', message: `\"${specifier}\"${from} only exists in the desktop main process: use ctx.desktop from the extension's index.` }\n if (specifier.startsWith('bun:') || specifier.startsWith('node:') || isBuiltin(specifier))\n return { kind: 'error', message: `\"${specifier}\"${from} is a server module; the ui entry runs in a browser renderer. Move the code to the extension's index and call it through RPC.` }\n const isPath = specifier.startsWith('./') || specifier.startsWith('../') || specifier === '.' || specifier === '..' || isAbsolute(specifier)\n if (isPath && importer && !inNodeModules(importer)) {\n const target = isAbsolute(specifier) ? specifier : resolve(importer, '..', specifier)\n if (!isInside(target, root))\n return { kind: 'error', message: `\"${specifier}\"${from} resolves outside the extension folder (${target}). A ui entry bundles only the extension's own files and packages.` }\n }\n return { kind: 'bundle' }\n}\n","/**\n * Where an extension's UI entries live: `definition.ui` / `definition.tui`\n * when set, else `ui.tsx` / `tui.tsx` (or `.ts`, `.jsx`, `.js`) next to the\n * extension's index.\n */\n\nimport { existsSync } from 'node:fs'\nimport { isAbsolute, join, relative, resolve } from 'node:path'\n\n/** The files tried, in order, when the definition names no entry. */\nexport const DEFAULT_UI_ENTRY_FILES = {\n ui: ['ui.tsx', 'ui.ts', 'ui.jsx', 'ui.js'],\n tui: ['tui.tsx', 'tui.ts', 'tui.jsx', 'tui.js'],\n} as const\n\n/** What {@link resolveUiEntries} found. */\nexport interface UiEntries {\n /** Absolute path of the desktop and web entry, when there is one. */\n ui?: string\n /** Absolute path of the terminal entry, when there is one. */\n tui?: string\n /** Why a named entry was refused (outside the folder, missing). */\n errors: string[]\n}\n\n/** The definition fields that name UI entries (`ExtensionDefinition.ui` / `.tui`). */\nexport interface UiEntryFields {\n /** The desktop and web entry, relative to the extension folder. */\n ui?: unknown\n /** The terminal entry, relative to the extension folder. */\n tui?: unknown\n}\n\n/** Options of {@link resolveUiEntries}. */\nexport interface ResolveUiEntriesOptions {\n /** Whether a file exists. Default: `existsSync`. */\n exists?: (path: string) => boolean\n}\n\n/**\n * The UI entries of an extension in `dir`.\n *\n * A named entry (`definition.ui`, `definition.tui`) is resolved against\n * `dir`; it must stay inside it and exist, otherwise it is reported in\n * `errors` and left out (the default files are not tried then). Without a\n * named entry the first existing default file is used.\n *\n * @param dir - The extension folder (where its index lives).\n * @param definition - The extension definition's `ui` and `tui` fields.\n * @param options - `exists`, to check files without the disk.\n * @returns The entries found and the errors.\n * @example\n * ```ts\n * const { ui, tui, errors } = resolveUiEntries('/ext/notes', { ui: 'web/ui.tsx' })\n * ```\n */\nexport function resolveUiEntries(dir: string, definition: UiEntryFields = {}, options: ResolveUiEntriesOptions = {}): UiEntries {\n const exists = options.exists ?? existsSync\n const root = resolve(dir)\n const result: UiEntries = { errors: [] }\n for (const kind of ['ui', 'tui'] as const) {\n const named = definition[kind]\n if (named === undefined) {\n const found = DEFAULT_UI_ENTRY_FILES[kind].map(file => join(root, file)).find(path => exists(path))\n if (found)\n result[kind] = found\n continue\n }\n if (typeof named !== 'string' || named.trim() === '') {\n result.errors.push(`${kind}: must be a file path relative to the extension folder`)\n continue\n }\n const path = resolve(root, named)\n const rel = relative(root, path)\n if (rel === '' || rel.startsWith('..') || isAbsolute(rel)) {\n result.errors.push(`${kind}: \"${named}\" is outside the extension folder`)\n continue\n }\n if (!exists(path)) {\n result.errors.push(`${kind}: \"${named}\" does not exist`)\n continue\n }\n result[kind] = path\n }\n return result\n}\n","/**\n * Extension completion providers (`ctx.registerCompletionProvider`) as an app\n * runs them for its composer: the renderable set, one provider's items in a\n * wire-safe shape, and the submit hooks (`resolveReferences`, `onSubmit`).\n * The desktop app runs them over its own IPC, a host over `completions.*`.\n */\nimport type { CompletionProvider } from '../chat/completion-core'\nimport { resolveCompletionSubmit } from '../chat/completion-core'\n\n/** A provider as an app's composer lists it: its trigger opens its popup. */\nexport interface ExtensionCompletionProviderSummary {\n /** The provider's id (`completions.suggest` names it). */\n id: string\n /** One character. */\n trigger: string\n /** The popup's section title (the id when the provider names none). */\n label: string\n}\n\n/** One item of a provider's popup. */\nexport interface ExtensionCompletionItemSummary {\n /** The item's id. */\n id: string\n /** What the row shows. */\n label: string\n /** What picking it inserts (the id when the provider gives none). */\n insertText: string\n /** Short text under the label. */\n description?: string\n}\n\n/** Most items a provider's popup lists. */\nexport const MAX_COMPLETION_ITEMS = 8\n\n/** Triggers owned by the built-in file (`@`), skill (`/`), and chat (`#`) completers. */\nconst RESERVED_COMPLETION_TRIGGERS = ['@', '/', '#'] as const\n\n/**\n * The providers a composer can render: drops invalid ids / triggers / suggest\n * functions and the reserved triggers, first wins on both id and trigger.\n *\n * @param providers - The registry's providers.\n */\nexport function usableCompletionProviders(providers: readonly CompletionProvider[]): CompletionProvider[] {\n const used = new Set<string>(RESERVED_COMPLETION_TRIGGERS)\n const ids = new Set<string>()\n const out: CompletionProvider[] = []\n for (const provider of providers) {\n if (\n typeof provider.id !== 'string'\n || provider.id.trim().length === 0\n || ids.has(provider.id)\n || typeof provider.trigger !== 'string'\n || Array.from(provider.trigger).length !== 1\n || typeof provider.suggest !== 'function'\n || used.has(provider.trigger)\n ) {\n continue\n }\n ids.add(provider.id)\n used.add(provider.trigger)\n out.push(provider)\n }\n return out\n}\n\n/**\n * The usable providers as a composer lists them.\n *\n * @param providers - The registry's providers.\n */\nexport function completionProviderSummaries(providers: readonly CompletionProvider[]): ExtensionCompletionProviderSummary[] {\n return usableCompletionProviders(providers).map(provider => ({\n id: provider.id,\n trigger: provider.trigger,\n label: typeof provider.label === 'string' && provider.label.trim().length > 0 ? provider.label : provider.id,\n }))\n}\n\n/**\n * Runs one provider's `suggest` and keeps the well-formed items, at most\n * {@link MAX_COMPLETION_ITEMS}. A throwing provider or a non-array result\n * answers `[]`; `insertText` falls back to the item id.\n *\n * @param provider - The provider.\n * @param query - The text after the trigger.\n * @param context - The composer's state.\n * @param context.text - Its text.\n * @param context.cursor - The cursor's offset in it.\n * @param signal - Aborted when the query moves on.\n */\nexport async function suggestCompletionItems(\n provider: CompletionProvider,\n query: string,\n context: { text: string, cursor: number },\n signal: AbortSignal,\n): Promise<ExtensionCompletionItemSummary[]> {\n let items: unknown\n try {\n items = await provider.suggest(query, context, signal)\n }\n catch {\n return []\n }\n if (!Array.isArray(items))\n return []\n return (items as (Record<string, unknown> | null)[])\n .filter((item): item is Record<string, unknown> & { id: string, label: string } =>\n !!item && typeof item.id === 'string' && typeof item.label === 'string')\n .slice(0, MAX_COMPLETION_ITEMS)\n .map(item => ({\n id: item.id,\n label: item.label,\n insertText: typeof item.insertText === 'string' ? item.insertText : item.id,\n ...(typeof item.description === 'string' ? { description: item.description } : {}),\n }))\n}\n\n/**\n * Runs the submit hooks of the usable providers that declare one, with the\n * same reference collection as the terminal app (`resolveCompletionSubmit`).\n *\n * @param providers - The registry's providers.\n * @param text - The submitted text.\n * @param cursor - The cursor at submit.\n * @param signal - Aborts the hooks.\n */\nexport async function resolveExtensionCompletionSubmit(\n providers: readonly CompletionProvider[],\n text: string,\n cursor: number,\n signal: AbortSignal,\n): Promise<void> {\n const usable = usableCompletionProviders(providers).filter(\n provider => typeof provider.resolveReferences === 'function' || typeof provider.onSubmit === 'function',\n )\n if (usable.length > 0)\n await resolveCompletionSubmit(text, usable, { cursor, signal })\n}\n\n/** How long a provider's `suggest`, or the submit hooks, may run before the answer is given up. */\nexport const COMPLETION_TIMEOUT_MS = 5_000\n\n/** Runs completion work for a composer: each bounded in time, a newer suggest for the same key aborting the older one. */\nexport interface CompletionRunner {\n /** The items of `provider` for `query`; `[]` once a newer suggest for `key` started or the time is up. */\n suggest: (key: string, provider: CompletionProvider, query: string, context: { text: string, cursor: number }) => Promise<ExtensionCompletionItemSummary[]>\n /** The submit hooks ({@link resolveExtensionCompletionSubmit}); resolves once they ran or the time is up. */\n submit: (providers: readonly CompletionProvider[], text: string, cursor: number) => Promise<void>\n}\n\n/**\n * Creates a {@link CompletionRunner}. A provider that ignores its signal can't\n * hold the answer past `timeoutMs`.\n *\n * @param timeoutMs - The bound of each call. Default {@link COMPLETION_TIMEOUT_MS}.\n */\nexport function createCompletionRunner(timeoutMs = COMPLETION_TIMEOUT_MS): CompletionRunner {\n const suggests = new Map<string, AbortController>()\n const bounded = async <T>(controller: AbortController, run: (signal: AbortSignal) => Promise<T>, fallback: T): Promise<T> => {\n const timer = setTimeout(() => controller.abort(), timeoutMs)\n try {\n return await Promise.race([\n run(controller.signal),\n new Promise<T>(resolve => controller.signal.addEventListener('abort', () => resolve(fallback), { once: true })),\n ])\n }\n finally {\n clearTimeout(timer)\n }\n }\n return {\n async suggest(key, provider, query, context) {\n suggests.get(key)?.abort()\n const controller = new AbortController()\n suggests.set(key, controller)\n try {\n return await bounded(controller, signal => suggestCompletionItems(provider, query, context, signal), [])\n }\n finally {\n if (suggests.get(key) === controller)\n suggests.delete(key)\n }\n },\n submit: (providers, text, cursor) =>\n bounded(new AbortController(), signal => resolveExtensionCompletionSubmit(providers, text, cursor, signal), undefined),\n }\n}\n","/**\n * Typed, extension-contributed configuration.\n *\n * Extensions declare config CATEGORIES and typed config ITEMS during\n * `setup(ctx)` via `ctx.registerConfigCategory` / `ctx.registerConfigItem`.\n * Values are persisted in the user's `Settings.extensionConfig` bag\n * (`extName → itemKey → value`) and read back — default-first, with\n * graceful degradation on missing / malformed values — through a single\n * resolver ({@link resolveExtensionConfigValue}). The same resolver\n * powers `ctx.config.get(key)` inside the extension (hooks / tools) and\n * both Settings UIs (TUI + GUI).\n *\n * Design intent:\n * - **One chokepoint for graceful degradation.** Every read — host,\n * extension, TUI render, GUI render — funnels through\n * {@link resolveExtensionConfigValue}; a value that's missing, the\n * wrong type, out of range, off the enum, or failing the author's\n * `validate` collapses to the item's `default`. The UI therefore\n * never has to special-case a broken `state.json` / DB row.\n * - **Namespacing by extension.** Items are keyed `extName → itemKey`\n * so two extensions can both ship a `verbose` knob without colliding.\n * Categories are a flat global registry (an extension may add items\n * to another extension's category, or to its own implicit category\n * whose id is the extension name).\n * - **Wire-safe schema.** The optional main-side `validate` callback is\n * the only non-serializable field; {@link toWireConfigSchema} drops it\n * so the schema crosses an IPC boundary (the GUI) cleanly.\n */\n\nimport type { Settings } from '../chat/types'\nimport type { ExtensionRegistry } from './types'\n\n// ---------------------------------------------------------------------------\n// Schema types\n// ---------------------------------------------------------------------------\n\n/** Concrete value a config item can hold. */\nexport type ExtensionConfigValue = boolean | number | string\n\n/** Where a config value should be persisted. */\nexport type ExtensionConfigScope = 'user' | 'project' | 'session'\n/** How a host applies a changed config value: read live, rebuild the agent, or restart. */\nexport type ExtensionConfigChangeBehavior = 'live' | 'agent-rebuild' | 'restart'\n\n/** Fields shared by every config-item variant. */\nexport interface ExtensionConfigItemBase {\n /**\n * Stable key, unique within the declaring extension. Used as the\n * persistence key (`extensionConfig[extName][key]`) and the\n * `ctx.config.get(key)` lookup — pick a stable identifier.\n */\n key: string\n /** Short display label rendered in the Settings UIs. */\n label: string\n /** Longer one-line gloss shown under the label. */\n description?: string\n /**\n * Optional main-side validator, run at READ time AFTER the built-in\n * type / range / enum / pattern checks (both must pass). Throwing is\n * treated as \"invalid\" — the read degrades to the item's `default`. It\n * is **never invoked at registration** (declaring an item has no side\n * effects) and is **never serialized over IPC** ({@link toWireConfigSchema}\n * strips it), so it only runs in-process (TUI host + extension reads);\n * the GUI renderer is optimistic and relies on the authoritative core read.\n */\n validate?: (v: unknown) => boolean\n /**\n * Desired persistence scope. Current stores still persist through the\n * existing per-extension settings bag unless a host implements scoped writes;\n * this metadata lets UIs and future stores present the right ownership.\n */\n scope?: ExtensionConfigScope\n /** Whether changing this value requires rebuilding runtime objects. */\n requiresRestart?: boolean\n /** How hosts should apply a changed value. Defaults to live reads through `ctx.config.get`. */\n onChange?: ExtensionConfigChangeBehavior\n}\n\n/** A boolean config item — rendered as a toggle. */\nexport interface ExtensionConfigBooleanItem extends ExtensionConfigItemBase {\n /** Discriminant for a boolean item. */\n type: 'boolean'\n /** Value used until the user sets one. */\n default: boolean\n}\n\n/**\n * A numeric config item — rendered as a free input row, clamped to `[min, max]`\n * and snapped to `step`. The `default` must itself lie within `[min, max]` or\n * the item is rejected at registration.\n */\nexport interface ExtensionConfigNumberItem extends ExtensionConfigItemBase {\n /** Discriminant for a number item. */\n type: 'number'\n /** Value used until the user sets one. Must lie within `[min, max]`. */\n default: number\n /** Smallest accepted value. */\n min?: number\n /** Largest accepted value. */\n max?: number\n /** Increment values snap to. */\n step?: number\n}\n\n/** A string config item — rendered as a free input row (optionally `multiline`), validated against `pattern`. */\nexport interface ExtensionConfigStringItem extends ExtensionConfigItemBase {\n /** Discriminant for a string item. */\n type: 'string'\n /** Value used until the user sets one. */\n default: string\n /**\n * Anchored or unanchored JS-regex source gating user-entered values at read\n * time. An invalid pattern is ignored (treated as \"no constraint\"). The\n * pattern is intentionally NOT applied to the `default`, so an empty / unset\n * default (`default: ''`) for an optional patterned field is valid.\n */\n pattern?: string\n /** Renders a multi-line editor instead of a single-line input. */\n multiline?: boolean\n /**\n * Treat the value as a credential: Settings UIs render it masked\n * (`••••••••`, last 4 characters kept for recognition when the value is\n * longer than 8) and seed the editor\n * EMPTY rather than with the stored value, so the secret never appears on\n * screen or in a screen share.\n *\n * Presentation only — the value still lives in the plain settings bag, so\n * this is for \"don't shoulder-surf my service token\", not for secrets that\n * warrant the credential store. Ignored for `multiline` items.\n */\n secret?: boolean\n}\n\n/**\n * An enum config item — rendered as a cycling choice row. The `default` must be\n * one of the `options` values or the item is rejected at registration.\n */\nexport interface ExtensionConfigEnumItem extends ExtensionConfigItemBase {\n /** Discriminant for an enum item. */\n type: 'enum'\n /** Value used until the user picks one. Must be one of `options`. */\n default: string\n /** Choices the user can pick from. */\n options: readonly { value: string, label: string }[]\n}\n\n/**\n * A model-id config item — rendered as an inline searchable picker over the\n * host's credentialed model catalog (the same interaction grammar as the\n * ctrl+m cross-provider picker: type to filter, `↵` picks — or toggles, in\n * `multi` mode, where `esc` applies the selection).\n *\n * The persisted value is a plain model id, or a comma-separated id list\n * when `multi` — a string either way, so {@link ExtensionConfigValue} and\n * every settings store stay unchanged, and hosts without a catalog\n * (headless, no authed providers) degrade to the free string input.\n * Deliberately catalog-UNvalidated at read time: a stored id whose\n * provider is temporarily unauthed must survive, not silently reset to\n * the default — catalog validation is the consuming extension's call.\n */\nexport interface ExtensionConfigModelItem extends ExtensionConfigItemBase {\n /** Discriminant for a model item. */\n type: 'model'\n /** Value used until the user picks one: a model id, or a comma-separated list when `multi`. */\n default: string\n /** Allow picking MORE than one model (comma-separated persisted value). */\n multi?: boolean\n}\n\n/**\n * What a config ACTION reports back to the host after running. Actions\n * cannot write settings directly — there is deliberately no `config.set`\n * surface for extensions — so a successful run RETURNS the values it wants\n * persisted and the host writes them through its own validated settings\n * path ({@link sanitizeExtensionConfigActionPatch} gates the patch).\n */\nexport interface ExtensionConfigActionResult {\n /** One-line feedback shown in the Settings UI (e.g. \"proxy running at …\"). */\n message?: string\n /**\n * Config values of the DECLARING extension to persist on success, keyed\n * by item key. Entries naming unknown keys, action items, or values that\n * fail the item's schema are dropped (not errors) — a buggy action can\n * degrade but never corrupt the settings bag.\n */\n config?: Record<string, ExtensionConfigValue>\n}\n\n/**\n * An imperative config item — rendered as a \"press ↵ to run\" row instead\n * of a value editor. `run` executes in the extension's own process (it is\n * never serialized — {@link toWireConfigSchema} omits action items\n * entirely), so it can close over the extension's `setup(ctx)` scope.\n *\n * Contract for `run`:\n * - Resolve with an {@link ExtensionConfigActionResult} (or `void`) on\n * success — `message` becomes the row's feedback line, `config`\n * values are persisted by the host.\n * - Throw / reject on failure — the error message is shown on the row.\n * - Bound your own runtime: the host serializes actions (one in flight\n * per modal) but imposes no timeout, so a hanging `run` holds the\n * \"running…\" state until it settles.\n *\n * Actions hold no persisted value: `ctx.config.get(key)` returns\n * `undefined` for an action key and the resolver never yields a value.\n */\nexport interface ExtensionConfigActionItem extends Pick<ExtensionConfigItemBase, 'key' | 'label' | 'description'> {\n /** Discriminant for an action item. */\n type: 'action'\n /** Runs the action. May return values to persist. Throwing shows the error on the row. */\n run: () => ExtensionConfigActionResult | void | Promise<ExtensionConfigActionResult | void>\n /**\n * Optional passive probe — called by the host when the settings panel\n * surfaces the row (and re-called after any action of the panel\n * settles), so the row can show live state (\"running at …\") WITHOUT\n * the user pressing ↵. Contract:\n *\n * - Resolve an {@link ExtensionConfigActionStatus} to show it, or\n * `undefined` for \"no status\" (e.g. the probed tool isn't\n * installed — stay quiet rather than nag).\n * - Throwing is treated as `undefined` — probes must be safe to call\n * at any time and MUST NOT mutate anything.\n * - Be fast: the TUI caps each probe at 3 seconds and discards\n * late results.\n */\n status?: () => ExtensionConfigActionStatus | undefined | Promise<ExtensionConfigActionStatus | undefined>\n}\n\n/**\n * Result of an action's passive `status` probe. `state` drives the row\n * color (`ok` accent / `off` mute / `error` error); `message` is the\n * one-line text rendered in the row's value slot.\n */\nexport interface ExtensionConfigActionStatus {\n /** Row state: `ok`, `off` or `error`. */\n state: 'ok' | 'off' | 'error'\n /** One-line text shown in the row's value slot. */\n message: string\n}\n\n/**\n * The value-holding config items — everything except `action`. Functions\n * that produce or validate persisted VALUES take this narrower union;\n * {@link ExtensionConfigItem} is the full declarable set.\n */\nexport type ExtensionConfigValueItem\n = | ExtensionConfigBooleanItem\n | ExtensionConfigNumberItem\n | ExtensionConfigStringItem\n | ExtensionConfigEnumItem\n | ExtensionConfigModelItem\n\n/**\n * Discriminated union of the typed config items an extension can declare.\n * The `type` tag drives both validation ({@link resolveExtensionConfigValue})\n * and rendering (toggle / choice / input / action row).\n */\nexport type ExtensionConfigItem = ExtensionConfigValueItem | ExtensionConfigActionItem\n\n/**\n * A config category — a labelled grouping the Settings UIs render as a\n * sub-header. Declared via `ctx.registerConfigCategory`. An item that\n * names no category lands in its extension's implicit category (id =\n * extension name); register a category with that id to give the implicit\n * grouping a friendlier label.\n */\nexport interface ExtensionConfigCategory {\n /** Category id. */\n id: string\n /** Sub-header text. */\n label: string\n /** One-line gloss shown under the label. */\n description?: string\n}\n\n/**\n * A config item as STORED on the registry / contributions — the authored\n * item plus the resolved `category` id it belongs to. The owning\n * extension is implied by the namespacing key on\n * {@link ExtensionRegistry.configItems}.\n */\nexport type StoredExtensionConfigItem = ExtensionConfigItem & { category: string }\n\n/** The `ctx.config` surface handed to extensions for reading their own config. */\nexport interface ExtensionConfigSurface {\n /**\n * Read the current value of one of THIS extension's config items,\n * default-first. Returns the persisted value when present + valid, the\n * item's `default` when missing / malformed, or `undefined` when `key`\n * was never registered via `ctx.registerConfigItem`.\n *\n * Reads through a host-supplied live settings getter: during `setup`\n * (before the host wires live settings) it returns the default (or the\n * boot snapshot); inside hooks / tools (post-boot) it returns the live\n * value.\n */\n get: (key: string) => ExtensionConfigValue | undefined\n}\n\n// ---------------------------------------------------------------------------\n// Authored-schema validation (registration-time guard)\n// ---------------------------------------------------------------------------\n\n/**\n * Exhaustiveness guard for the `ExtensionConfigItem` union: a future item\n * `type` left unhandled is a COMPILE error (the `never` parameter), while at\n * runtime an unrecognized / missing type is treated as invalid (`false`) —\n * malformed items reach here via `as never` casts from untyped `.js` extensions.\n */\nfunction unreachableInvalidItem(_item: never): false {\n return false\n}\n\n/**\n * Whether an authored item is well-formed for its declared `type` — used\n * by `ctx.registerConfigItem` to drop malformed declarations (wrong /\n * missing `default`, an `enum` without `options`) before they reach the\n * registry. Cheaper than letting a broken item ride to render time.\n *\n * @param item - Item declared by an extension.\n */\nexport function isValidExtensionConfigItem(item: ExtensionConfigItem): boolean {\n switch (item.type) {\n case 'boolean':\n return typeof item.default === 'boolean'\n case 'number':\n // The default must be finite AND within the declared range, so the\n // resolver never surfaces an out-of-range value (the module's \"every read\n // yields a valid value\" invariant). `step` is a UI affordance, not a hard\n // constraint, so it is NOT enforced on the default.\n return typeof item.default === 'number'\n && Number.isFinite(item.default)\n && (item.min === undefined || item.default >= item.min)\n && (item.max === undefined || item.default <= item.max)\n case 'string':\n // A string `pattern` is intentionally NOT enforced against the default:\n // an empty / unset default (`default: ''`) for an optional patterned\n // field is a legitimate idiom. The pattern still gates user-entered\n // values at read time via `resolveExtensionConfigValue`. The author\n // `validate` is likewise deferred to read time, so registration stays\n // side-effect-free (no `validate(default)` call at register time).\n return typeof item.default === 'string'\n case 'enum':\n // The default MUST be one of the options — otherwise the picker can't\n // represent it and the resolver would surface an off-list value.\n return typeof item.default === 'string'\n && Array.isArray(item.options)\n && item.options.length > 0\n && item.options.every(o => o && typeof o.value === 'string' && typeof o.label === 'string')\n && item.options.some(o => o.value === item.default)\n case 'model':\n // Ids are free-form strings (catalogs are host- and auth-dependent),\n // so only the shape is checked — see the type's docstring for why\n // values are never catalog-validated.\n return typeof item.default === 'string'\n case 'action':\n // No `default` — requires a callable `run`; `status` is optional\n // but must be callable when present.\n return typeof item.run === 'function'\n && (item.status === undefined || typeof item.status === 'function')\n default:\n return unreachableInvalidItem(item)\n }\n}\n\n// ---------------------------------------------------------------------------\n// Validation + resolution — the single graceful-degradation chokepoint\n// ---------------------------------------------------------------------------\n\n/** Build a RegExp from `pattern`, returning `null` when the source is invalid. */\nfunction safeRegExp(pattern: string): RegExp | null {\n try {\n return new RegExp(pattern)\n }\n catch {\n return null\n }\n}\n\n/**\n * Whether `value` is a valid concrete value for `item` — type match plus\n * the item's constraints (number range, enum membership, string pattern)\n * and the optional author `validate`. `step` is intentionally NOT enforced\n * here (it's a UI affordance, not a hard constraint — a persisted value or\n * default that doesn't align to the step is still honored).\n *\n * @param item - Item that defines the type and constraints.\n * @param value - Candidate value.\n */\nexport function isValidExtensionConfigValue(item: ExtensionConfigItem, value: unknown): value is ExtensionConfigValue {\n switch (item.type) {\n case 'boolean':\n if (typeof value !== 'boolean')\n return false\n break\n case 'number':\n if (typeof value !== 'number' || !Number.isFinite(value))\n return false\n if (item.min !== undefined && value < item.min)\n return false\n if (item.max !== undefined && value > item.max)\n return false\n break\n case 'string': {\n if (typeof value !== 'string')\n return false\n if (item.pattern) {\n const re = safeRegExp(item.pattern)\n // A broken author pattern is treated as \"no constraint\" rather\n // than rejecting every value the user types.\n if (re && !re.test(value))\n return false\n }\n break\n }\n case 'enum':\n if (typeof value !== 'string' || !item.options.some(o => o.value === value))\n return false\n break\n case 'model':\n if (typeof value !== 'string')\n return false\n break\n case 'action':\n // Actions hold no persisted value — nothing is ever valid for them.\n return false\n default:\n return unreachableInvalidItem(item)\n }\n if (item.validate) {\n try {\n return item.validate(value)\n }\n catch {\n return false\n }\n }\n return true\n}\n\n/**\n * Resolve the effective value of a config item from its persisted value.\n * THE single place graceful degradation lives: a `persisted` that's\n * `undefined` (never set) OR fails {@link isValidExtensionConfigValue}\n * collapses to `item.default`. Action items hold no value and resolve to\n * `undefined` — the overloads keep value-item call sites exact.\n *\n * @param item - Item that defines the type and constraints.\n * @param persisted - Stored value, if any.\n */\nexport function resolveExtensionConfigValue(\n item: ExtensionConfigValueItem,\n persisted: unknown,\n): ExtensionConfigValue\nexport function resolveExtensionConfigValue(\n item: ExtensionConfigItem,\n persisted: unknown,\n): ExtensionConfigValue | undefined\nexport function resolveExtensionConfigValue(\n item: ExtensionConfigItem,\n persisted: unknown,\n): ExtensionConfigValue | undefined {\n if (item.type === 'action')\n return undefined\n if (persisted === undefined)\n return item.default\n if (!isValidExtensionConfigValue(item, persisted))\n return item.default\n return persisted\n}\n\n/**\n * Clamp a number to the item's `[min, max]` and snap to `step` (when set).\n * Used by the input-row commit paths so a user-typed value is coerced into\n * range before it's persisted.\n *\n * @param item - Number item that supplies `min`, `max` and `step`.\n * @param n - Value to clamp.\n */\nexport function clampExtensionConfigNumber(item: ExtensionConfigNumberItem, n: number): number {\n let v = n\n if (item.min !== undefined)\n v = Math.max(item.min, v)\n if (item.max !== undefined)\n v = Math.min(item.max, v)\n if (item.step !== undefined && item.step > 0) {\n const base = item.min ?? 0\n v = base + Math.round((v - base) / item.step) * item.step\n // Snapping can nudge a boundary value out of range — re-clamp.\n if (item.max !== undefined)\n v = Math.min(item.max, v)\n if (item.min !== undefined)\n v = Math.max(item.min, v)\n }\n return v\n}\n\n/**\n * Coerce a raw input string (from a free number / string input row) into a\n * valid persisted value, or `undefined` when it can't be made valid.\n * Numbers are parsed + clamped; strings are taken verbatim and checked\n * against the pattern; enum / boolean items aren't edited via free input\n * (they use choice / toggle rows) so they return `undefined` here.\n *\n * @param item - Item the input belongs to.\n * @param raw - Text the user typed.\n */\nexport function coerceExtensionConfigInput(\n item: ExtensionConfigItem,\n raw: string,\n): ExtensionConfigValue | undefined {\n switch (item.type) {\n case 'number': {\n const n = Number(raw.trim())\n if (!Number.isFinite(n))\n return undefined\n const clamped = clampExtensionConfigNumber(item, n)\n return isValidExtensionConfigValue(item, clamped) ? clamped : undefined\n }\n case 'string':\n return isValidExtensionConfigValue(item, raw) ? raw : undefined\n case 'model':\n // Fallback path for hosts without a catalog — the value is typed as\n // free text (a comma-separated id list when `multi`).\n return isValidExtensionConfigValue(item, raw) ? raw : undefined\n default:\n // Enum / boolean use choice / toggle rows; actions have no value.\n return undefined\n }\n}\n\n/**\n * Convenience read against a merged {@link ExtensionRegistry} + the user's\n * `Settings`. Looks up the item schema (`extName → key`), reads the\n * persisted value out of `settings.extensionConfig`, and runs it through\n * {@link resolveExtensionConfigValue}. Returns `undefined` only when the\n * `(extName, key)` pair names no registered item.\n *\n * @param registry - Merged registry holding the declared items.\n * @param settings - User settings holding the persisted values.\n * @param extName - Name of the declaring extension.\n * @param key - Item key.\n */\nexport function resolveExtensionConfig(\n registry: Pick<ExtensionRegistry, 'configItems'>,\n settings: Pick<Settings, 'extensionConfig'> | undefined,\n extName: string,\n key: string,\n): ExtensionConfigValue | undefined {\n const item = registry.configItems[extName]?.[key]\n if (!item)\n return undefined\n return resolveExtensionConfigValue(item, settings?.extensionConfig?.[extName]?.[key])\n}\n\n/**\n * Gate the `config` patch an action returned before the host persists it.\n * Per-entry, an item is accepted only when it names a registered VALUE\n * item of the declaring extension and passes that item's schema\n * ({@link isValidExtensionConfigValue}); everything else lands in\n * `rejected` for logging. Pure — the host applies `accepted` through its\n * own settings write path.\n *\n * @param items - Declared items of the extension, keyed by item key.\n * @param patch - Values the action returned.\n */\nexport function sanitizeExtensionConfigActionPatch(\n items: Readonly<Record<string, StoredExtensionConfigItem>> | undefined,\n patch: Readonly<Record<string, ExtensionConfigValue>> | undefined,\n): { accepted: Record<string, ExtensionConfigValue>, rejected: string[] } {\n const accepted: Record<string, ExtensionConfigValue> = {}\n const rejected: string[] = []\n if (!patch || typeof patch !== 'object')\n return { accepted, rejected }\n for (const [key, value] of Object.entries(patch)) {\n const item = items?.[key]\n if (!item || item.type === 'action' || !isValidExtensionConfigValue(item, value)) {\n rejected.push(key)\n continue\n }\n accepted[key] = value\n }\n return { accepted, rejected }\n}\n\n// ---------------------------------------------------------------------------\n// Wire-safe serialization (GUI IPC)\n// ---------------------------------------------------------------------------\n\n/** Fields the wire shape adds on top of the authored item (minus `validate`). */\ninterface WireConfigExtras {\n category: string\n extension: string\n}\n\n/** A config item flattened for the wire — carries `category` + `extension`, drops `validate`. */\nexport type WireExtensionConfigItem\n = | (Omit<ExtensionConfigBooleanItem, 'validate'> & WireConfigExtras)\n | (Omit<ExtensionConfigNumberItem, 'validate'> & WireConfigExtras)\n | (Omit<ExtensionConfigStringItem, 'validate'> & WireConfigExtras)\n | (Omit<ExtensionConfigEnumItem, 'validate'> & WireConfigExtras)\n | (Omit<ExtensionConfigModelItem, 'validate'> & WireConfigExtras)\n\n/** The full extension-config schema in IPC-safe form. */\nexport interface WireExtensionConfigSchema {\n /** Declared categories. */\n categories: readonly ExtensionConfigCategory[]\n /** Declared items, each tagged with its extension and category. */\n items: readonly WireExtensionConfigItem[]\n}\n\n/**\n * Project the merged registry's config schema into a wire-safe shape:\n * categories as a flat array, items flattened to a single list carrying\n * their `extension` + `category`, with the non-serializable `validate`\n * callback stripped. Action items are omitted entirely — their `run`\n * callback only exists in the main process, so a remote renderer (the\n * GUI) has nothing it could do with the row. Pure — factored out so its\n * serialization is unit testable without an Electron / IPC harness.\n *\n * @param registry - Merged registry holding the declared categories and items.\n */\nexport function toWireConfigSchema(\n registry: Pick<ExtensionRegistry, 'configCategories' | 'configItems'>,\n): WireExtensionConfigSchema {\n const items: WireExtensionConfigItem[] = []\n for (const [extension, byKey] of Object.entries(registry.configItems)) {\n for (const stored of Object.values(byKey)) {\n if (stored.type === 'action')\n continue\n // Drop the main-only `validate` callback; keep everything else.\n const { validate: _validate, ...rest } = stored\n items.push({ ...rest, extension } as WireExtensionConfigItem)\n }\n }\n return {\n categories: Object.values(registry.configCategories),\n items,\n }\n}\n","/**\n * Extension config actions (`registerConfigItem` type `'action'`) as an app's\n * Settings lists and runs them: the rows, their passive `status()` probes and\n * a run, with the terminal app's wording. The callbacks stay on the host; the\n * desktop app calls these over its IPC, a host over `extensions.*`.\n */\nimport type { ExtensionConfigActionStatus, ExtensionConfigCategory, ExtensionConfigValue, StoredExtensionConfigItem } from './config'\nimport { sanitizeExtensionConfigActionPatch } from './config'\n\ntype StoredItems = Readonly<Record<string, Readonly<Record<string, StoredExtensionConfigItem>>>>\n\n/** An action row, without its callbacks. */\nexport interface ExtensionActionSummary {\n /** The declaring extension. */\n extension: string\n /** The action's key, unique in its extension. */\n key: string\n /** The row's name. */\n label: string\n /** What it does. */\n description?: string\n /** The config category it sits in. */\n category: string\n /** That category's name. */\n categoryLabel: string\n /** The action declares a passive `status()` probe. */\n hasStatus: boolean\n}\n\n/** What running an action did. */\nexport interface ExtensionActionRunResult {\n /** `result.message`, else `updated <keys>`, else `done`, with `(ignored invalid: …)` when keys were dropped. */\n message: string\n /** The accepted config patch (sanitized against the extension's schema); the app persists it. */\n config?: Record<string, ExtensionConfigValue>\n}\n\n/**\n * The action rows: the counterpart of `toWireConfigSchema`, which strips them.\n *\n * @param categories - The registry's config categories.\n * @param items - The registry's config items, per extension.\n */\nexport function listActionSummaries(\n categories: Readonly<Record<string, ExtensionConfigCategory>>,\n items: StoredItems,\n): ExtensionActionSummary[] {\n const out: ExtensionActionSummary[] = []\n for (const [extension, byKey] of Object.entries(items)) {\n for (const item of Object.values(byKey)) {\n if (item.type !== 'action')\n continue\n out.push({\n extension,\n key: item.key,\n label: item.label,\n ...(item.description !== undefined ? { description: item.description } : {}),\n category: item.category,\n categoryLabel: categories[item.category]?.label ?? item.category,\n hasStatus: typeof item.status === 'function',\n })\n }\n }\n return out.sort((a, b) => a.extension.localeCompare(b.extension) || a.label.localeCompare(b.label))\n}\n\n/** Per-probe cap: a hung `status()` must not hold the rows. */\nconst ACTION_PROBE_TIMEOUT_MS = 3_000\n\n/**\n * Every action's passive `status()`, keyed `extension:key`. A probe that\n * throws, times out or answers no message is left out.\n *\n * @param items - The registry's config items, per extension.\n */\nexport async function probeActionStatuses(items: StoredItems): Promise<Record<string, ExtensionConfigActionStatus>> {\n const out: Record<string, ExtensionConfigActionStatus> = {}\n const probes: Promise<void>[] = []\n for (const [extension, byKey] of Object.entries(items)) {\n for (const item of Object.values(byKey)) {\n if (item.type !== 'action' || typeof item.status !== 'function')\n continue\n const probe = item.status\n probes.push((async () => {\n let timer: ReturnType<typeof setTimeout> | undefined\n try {\n const status = await Promise.race([\n Promise.resolve(probe()),\n new Promise<undefined>((resolve) => {\n timer = setTimeout(resolve, ACTION_PROBE_TIMEOUT_MS, undefined)\n }),\n ])\n if (status && typeof status.message === 'string')\n out[`${extension}:${item.key}`] = { state: status.state, message: status.message }\n }\n catch {\n // A throwing probe means \"no status\".\n }\n finally {\n clearTimeout(timer)\n }\n })())\n }\n }\n await Promise.all(probes)\n return out\n}\n\n/**\n * Runs one action. The config patch it returns is sanitized (unknown keys and\n * values failing the schema are dropped) and returned, not written: the app\n * persists it through its settings writer.\n *\n * @param items - The registry's config items, per extension.\n * @param extensionName - The declaring extension.\n * @param actionId - The action's key.\n */\nexport async function runExtensionAction(\n items: StoredItems,\n extensionName: string,\n actionId: string,\n): Promise<ExtensionActionRunResult> {\n const item = items[extensionName]?.[actionId]\n if (!item || item.type !== 'action')\n throw new Error(`\"${extensionName}\" has no action \"${actionId}\".`)\n const result = (await item.run()) ?? undefined\n const { accepted, rejected } = sanitizeExtensionConfigActionPatch(items[extensionName], result?.config)\n const acceptedKeys = Object.keys(accepted)\n const parts = [result?.message || (acceptedKeys.length > 0 ? `updated ${acceptedKeys.join(', ')}` : 'done')]\n if (rejected.length > 0)\n parts.push(`(ignored invalid: ${rejected.join(', ')})`)\n return { message: parts.join(' '), ...(acceptedKeys.length > 0 ? { config: accepted } : {}) }\n}\n","/**\n * A provider's OAuth flow rides its provider contribution.\n *\n * `ctx.registerProvider(descriptor)` with a `descriptor.oauthProvider` is all\n * an extension declares. When the registry builds, the flow joins the\n * process-wide OAuth registry (`providers/oauth-registry`) that lazy token\n * refresh and usage probes resolve through; when the registry disposes, it\n * leaves. Registering the flow from `setup` instead would run even while the\n * extension is disabled, with nothing to undo it.\n *\n * - Active extensions only. A disabled extension's descriptor is dropped\n * with the rest of its contributions, and its flow with it.\n * - Built-in flow ids (`anthropic`, `openai-codex`, …) are refused: the\n * user's own subscription tokens never refresh through extension code.\n * - Claims are counted per flow object. A host handing the same inline\n * definition to several live registries (or building the next one before\n * disposing the last) keeps the flow until the last claim goes; a reload\n * that re-imports the extension registers a NEW object, which an older\n * registry's release can't remove.\n *\n * `descriptor.oauthProvider` is read once, when the registry builds.\n */\n\nimport type { LogSink } from '../logger'\nimport type { OAuthProviderInterface } from '../providers/oauth-registry'\nimport type { LoadedExtension } from './types'\nimport { createLogger } from '../logger'\nimport { BUILTIN_OAUTH_PROVIDER_IDS, getOAuthProvider, registerOAuthProvider, unregisterOAuthProvider } from '../providers/oauth-registry'\n\n/** Process-wide, like the registry itself: every zidane copy counts the same claims. */\nconst CLAIMS_SLOT = Symbol.for('zidane.extension-oauth-claims')\n\nfunction claims(): WeakMap<object, number> {\n const slots = globalThis as { [key: symbol]: WeakMap<object, number> | undefined }\n slots[CLAIMS_SLOT] ??= new WeakMap()\n return slots[CLAIMS_SLOT]\n}\n\nfunction isFlow(value: unknown): value is OAuthProviderInterface {\n const flow = value as Partial<OAuthProviderInterface> | null\n return !!flow\n && typeof flow.id === 'string'\n && flow.id.length > 0\n && typeof flow.login === 'function'\n && typeof flow.refreshToken === 'function'\n && typeof flow.getApiKey === 'function'\n}\n\n/**\n * Register the OAuth flows of the active extensions' providers.\n *\n * @param active - Extensions whose contributions are live.\n * @param sink - Log sink for the per-extension warnings.\n * @returns Releases this registry's claims. Idempotent.\n */\nexport function claimProviderOAuthFlows(active: readonly LoadedExtension[], sink: LogSink): () => void {\n const claimed: OAuthProviderInterface[] = []\n for (const entry of active) {\n const providers = entry.contributions?.providers\n if (!providers)\n continue\n const logger = createLogger(sink, { extension: entry.name })\n for (const descriptor of Object.values(providers)) {\n const flow: unknown = descriptor.oauthProvider\n if (flow === undefined)\n continue\n if (!isFlow(flow)) {\n logger.warn('registerProvider: oauthProvider needs an id, login, refreshToken and getApiKey; its sign-in won\\'t refresh', { provider: descriptor.key })\n continue\n }\n if (BUILTIN_OAUTH_PROVIDER_IDS.has(flow.id)) {\n if (getOAuthProvider(flow.id) !== flow)\n logger.warn(`registerProvider: OAuth flow id \"${flow.id}\" belongs to a built-in sign-in; refresh keeps using the built-in flow`, { provider: descriptor.key })\n continue\n }\n const credentialKey = descriptor.credentialFileKey ?? descriptor.key\n if (flow.id !== credentialKey)\n logger.warn(`registerProvider: OAuth flow id \"${flow.id}\" differs from the credential key \"${credentialKey}\"; usage probes look the flow up by the credential key`, { provider: descriptor.key })\n const current = getOAuthProvider(flow.id)\n if (current && current !== flow && claims().has(current))\n logger.warn(`registerProvider: OAuth flow \"${flow.id}\" replaces another extension's`, { provider: descriptor.key })\n registerOAuthProvider(flow)\n claims().set(flow, (claims().get(flow) ?? 0) + 1)\n claimed.push(flow)\n }\n }\n\n let released = false\n return () => {\n if (released)\n return\n released = true\n for (const flow of claimed) {\n const left = (claims().get(flow) ?? 1) - 1\n if (left > 0) {\n claims().set(flow, left)\n continue\n }\n claims().delete(flow)\n unregisterOAuthProvider(flow)\n }\n }\n}\n","/**\n * The {@link ExtensionRegistry} hosts read, as a live view of the extension\n * runtime.\n *\n * Each extension's contributions are read from the runtime's registries:\n * tools, skills, MCP servers, agents, providers and sub-agents from the\n * catalogs; `/` commands, palette providers, keybindings and footer hints\n * from the command registry; panels, themes, references, badge actions and\n * context sections from the UI registry; composer providers; settings as\n * config rows; and, when the host wired none of its own, the extension's\n * agent-hook observers and host events as handlers. The view merges them.\n *\n * Reads are cached until one of those registries changes (or an extension\n * loads, fails or unloads); the next read recomputes, so a command or panel\n * registered after `setup` shows up. `registry.subscribe` tells hosts when\n * to read again. Filtered views (`filterExtensionRegistry`,\n * `filterRegistryPlugins`) share the runtime and the change feed.\n */\n\nimport type { AgentHooks } from '../../agent'\nimport type { ContextBreakdownContributor } from '../../chat/context-breakdown'\nimport type { Settings } from '../../chat/types'\nimport type { ToolDef } from '../../tools/types'\nimport type { JsonValue } from '../../types'\nimport type { ExtensionDefinition } from '../api/define'\nimport type { ExtensionConfigActionItem, ExtensionConfigCategory, StoredExtensionConfigItem } from '../config'\nimport type { ExtensionSessionEventHandler } from '../host-runtime'\nimport type { ExtensionPanelEntry } from '../panels'\nimport type { SettingsPort } from '../settings'\nimport type {\n ExtensionContributions,\n ExtensionFooterHint,\n ExtensionKeybinding,\n ExtensionOrderedContribution,\n ExtensionRegistry,\n ExtensionRunSettledHandler,\n ExtensionToolResultMetadataRegistration,\n LoadedExtension,\n LoadedExtensionSource,\n LoadedPluginRecord,\n} from '../types'\nimport type { UiChange } from '../ui/registry'\nimport type { ExtensionRuntime, RuntimeExtension } from './host'\nimport { basename } from 'node:path'\nimport { settingsForDefinition, toWireSettings } from '../settings'\nimport { withProvenance } from '../shared'\n\n/**\n * A settings port over the host's settings bag (`Settings.extensionConfig`),\n * which today's Settings UIs write: it is the `user` layer, and the\n * source of `secret` strings too. Writes are left to the host, which\n * persists what its Settings UI and action results give it.\n *\n * @param readSettings - The host's live settings getter.\n * @returns The port.\n */\nexport function extensionConfigSettingsPort(readSettings: (() => Partial<Settings> | undefined) | undefined): SettingsPort {\n const bag = (ext: string): Readonly<Record<string, unknown>> | undefined => {\n const all = readSettings?.()?.extensionConfig\n return all && Object.hasOwn(all, ext) ? all[ext] : undefined\n }\n return {\n read: (ext, layer) => (layer === 'user' ? bag(ext) : undefined),\n write: () => {},\n secrets: {\n get: (ext, key) => {\n const value = bag(ext)?.[key]\n return typeof value === 'string' && value ? value : undefined\n },\n set: () => {},\n },\n }\n}\n\nfunction emptyContributions(): ExtensionContributions {\n return {\n tools: {},\n hooks: {},\n mcpServers: [],\n skills: [],\n plugins: [],\n runSettled: [],\n sessionEvents: [],\n contextBreakdownSections: [],\n contextPanelSections: [],\n toolResultMetadata: [],\n artifactKinds: [],\n references: [],\n badgeActions: [],\n completionProviders: [],\n inlineAutocompleteProviders: [],\n commands: [],\n themes: {},\n agents: {},\n providers: {},\n subagents: {},\n configCategories: {},\n configItems: {},\n tui: { keybindings: [], footerHints: [] },\n panels: [],\n palette: [],\n }\n}\n\n/** The extension's settings as config categories and rows. Actions run through the settings domain when active. */\nfunction projectSettings(ext: RuntimeExtension, def: ExtensionDefinition): Pick<ExtensionContributions, 'configCategories' | 'configItems'> {\n const instance = ext.settings\n const wire = instance ? instance.wire() : toWireSettings(ext.id, settingsForDefinition(def).schema)\n const configCategories: Record<string, ExtensionConfigCategory> = {}\n for (const category of wire.schema.categories)\n configCategories[category.id] = category\n const configItems: Record<string, StoredExtensionConfigItem> = {}\n for (const item of wire.schema.items) {\n const { extension: _extension, ...rest } = item\n configItems[item.key] = {\n ...rest,\n ...(instance ? { validate: (value: unknown) => instance.check(item.key, value) === undefined } : {}),\n } as StoredExtensionConfigItem\n }\n for (const action of wire.actions) {\n const key = action.key\n const run: ExtensionConfigActionItem['run'] = async () => {\n if (!ext.settings)\n throw new Error('The extension is not active')\n const result = await ext.settings.runAction(key)\n return { ...(result.message !== undefined ? { message: result.message } : {}), ...(result.config ? { config: result.config } : {}) }\n }\n configItems[key] = {\n type: 'action',\n key,\n label: action.label,\n ...(action.description !== undefined ? { description: action.description } : {}),\n category: action.category,\n run,\n ...(action.hasStatus && instance\n ? {\n status: async () => {\n const status = await instance.actionStatuses()\n return status[`${ext.id}:${key}`]\n },\n }\n : {}),\n }\n if (!configCategories[action.category] && action.category !== ext.id)\n configCategories[action.category] = { id: action.category, label: action.categoryLabel }\n }\n return { configCategories, configItems }\n}\n\nfunction ownedBy(id: string, origin: { kind: string, id?: string } | undefined): boolean {\n return origin?.kind === 'extension' && origin.id === id\n}\n\n/** The live contributions of one active extension. */\nfunction projectActive(runtime: ExtensionRuntime, ext: RuntimeExtension, source: LoadedExtensionSource, cwd: string): ExtensionContributions {\n const { outputs } = runtime\n const { catalogs, ui, commands } = outputs\n const id = ext.id\n const out = emptyContributions()\n\n const tools = catalogs.tools.read()\n const toolRecord: Record<string, ToolDef> = {}\n for (const tool of tools.items) {\n if (ownedBy(id, tools.origin(tool.name)))\n toolRecord[tool.name] = tool.def\n }\n out.tools = toolRecord\n\n const agents = catalogs.agents.read().sections\n out.agents = Object.fromEntries(agents.profiles.items.filter(p => ownedBy(id, agents.profiles.origin(p.id))).map(p => [p.id, p]))\n out.subagents = Object.fromEntries(agents.subagents.items.filter(s => ownedBy(id, agents.subagents.origin(s.name))).map(s => [s.name, s]))\n const providers = catalogs.providers.read().sections.providers\n out.providers = Object.fromEntries(providers.items.filter(p => ownedBy(id, providers.origin(p.key))).map(p => [p.key, p]))\n const servers = catalogs.mcp.read().sections.servers\n out.mcpServers = servers.items.filter(s => ownedBy(id, servers.origin(s.name)))\n const skills = catalogs.skills.read().sections.skills\n out.skills = skills.items.filter(s => ownedBy(id, skills.origin(s.name))).map(s => withProvenance(s, source, id))\n\n out.artifactKinds = runtime.artifactKinds(id).map(e => ({ extensionName: id, source, value: e.registration }))\n out.plugins = runtime.plugins(id)\n out.toolResultMetadata = catalogs.tools.metadata.list().filter(m => m.extensionId === id).map((m): ExtensionOrderedContribution<ExtensionToolResultMetadataRegistration> => ({\n extensionName: id,\n source,\n value: {\n namespace: m.namespace,\n ...(m.spec.contextRows ? { contextRows: ctx => catalogs.tools.metadata.contextRows(m.namespace, ctx.entries.map(e => ({ value: e.value as never }))) } : {}),\n ...(m.spec.summarize ? { summarize: metadata => catalogs.tools.metadata.summarize(m.namespace, metadata) as JsonValue | undefined } : {}),\n },\n }))\n\n const handlers = runtime.hookHandlers(id)\n const hooks: Record<string, ((...args: unknown[]) => unknown)[]> = {}\n if (!runtime.hostWired.agentHooks) {\n for (const [name, set] of handlers.agent) {\n if (set.size === 0)\n continue\n hooks[name] = [(...args: unknown[]) => {\n for (const fn of [...set])\n fn(...args)\n }]\n }\n }\n // Artifact detection (`ctx.artifacts.kinds.register` with `detect`) runs on\n // tool results whatever bus the host gave: one dispatcher reading the live kinds.\n if (runtime.artifactKinds(id).some(e => e.detect)) {\n const detect = async (...args: unknown[]): Promise<void> => {\n for (const entry of [...runtime.artifactKinds(id)])\n await (entry.detect as ((...a: unknown[]) => unknown) | undefined)?.(...args)\n }\n for (const name of ['tool:transform', 'child:tool:transform'])\n (hooks[name] ??= []).push(detect)\n }\n out.hooks = hooks as ExtensionContributions['hooks']\n if (!runtime.hostWired.hostEvents) {\n const deliver = (name: 'run:settled' | 'session:event', event: unknown): void => {\n for (const fn of [...handlers.host.get(name) ?? []])\n (fn as (e: unknown) => void)(event)\n }\n const runSettled: ExtensionRunSettledHandler = e => deliver('run:settled', { sessionId: e.sessionId, runId: e.runId, ok: e.ok, aborted: e.aborted, session: e.session })\n const sessionEvent: ExtensionSessionEventHandler = (e) => {\n if (e.status === 'cancelled')\n return\n deliver('session:event', {\n sessionId: e.sessionId,\n kind: e.status,\n ...(e.status === 'error' ? { error: e.error ?? e.summary } : {}),\n ...(e.request ? { requestId: e.request.id } : {}),\n })\n }\n out.runSettled = [runSettled]\n out.sessionEvents = [sessionEvent]\n }\n\n const named = (c: ContextBreakdownContributor): string | undefined => (c as { __zidaneExtensionName?: string }).__zidaneExtensionName\n out.contextBreakdownSections = ui.contextContributors('breakdown').filter(c => named(c) === id)\n out.contextPanelSections = ui.contextContributors('panel').filter(c => named(c) === id)\n\n out.references = ui.list('reference').filter(e => e.extension === id).map(e => ({\n extensionName: id,\n source,\n value: { ...e.item, resolve: async (key: string) => (await ui.resolveReference(e.item.id, key)) ?? undefined },\n }))\n out.badgeActions = ui.list('badge-action').filter(e => e.extension === id).map(e => ({\n extensionName: id,\n source,\n value: {\n id: e.item.id,\n ...(e.item.match ? { match: e.item.match } : {}),\n actions: target => ui.badgeMenu(target).filter(item => item.source === e.item.id).map(({ source: _source, ...action }) => action),\n run: (actionId, target, ctx) => ui.runBadgeAction(e.item.id, actionId, target, { ...(ctx.sessionId !== undefined ? { sessionId: ctx.sessionId } : {}), ...(ctx.cwd !== undefined ? { cwd: ctx.cwd } : {}) }),\n },\n }))\n out.themes = Object.fromEntries(ui.list('theme').filter(e => e.extension === id).map(e => [e.item.id, e.item]))\n out.panels = ui.list('panel').filter(e => e.extension === id).map((e) => {\n const panel = e.item\n return {\n id: panel.id,\n owner: id,\n label: panel.label,\n ...(panel.icon !== undefined ? { icon: panel.icon } : {}),\n ...(panel.scope !== undefined ? { scope: panel.scope } : {}),\n surfaces: panel.surfaces,\n ...(panel.home !== undefined ? { home: panel.home } : {}),\n load: ctx => ui.loadPanel(panel.id, ctx, ctx.cwd ?? cwd),\n ...(panel.live\n ? {\n subscribe: (emit: (change?: { sessionId?: string }) => void) => ui.subscribe((change) => {\n if (change.type === 'panel-changed' && change.panelId === panel.id)\n emit(change.sessionId ? { sessionId: change.sessionId } : undefined)\n }),\n }\n : {}),\n ...(panel.actions ? { onAction: async (actionId: string, payload: JsonValue | undefined, ctx: { cwd: string }) => { await ui.panelAction(panel.id, actionId, payload, ctx, ctx.cwd ?? cwd) } } : {}),\n } satisfies ExtensionPanelEntry\n })\n out.completionProviders = ui.completions.list().filter(p => p.extension === id).map(p => p.provider)\n out.inlineAutocompleteProviders = ui.autocomplete.list().filter(p => p.extension === id).map(p => p.provider)\n\n const mine = (commandId: string): boolean => commands.get(commandId)?.extensionId === id\n out.commands = commands.slashCommands().filter(c => mine(c.commandId)).map(c => (c.group === undefined ? { ...c, group: id } : c))\n out.palette = commands.paletteProviders().filter(p => p.owner === id)\n const hints: ExtensionFooterHint[] = []\n for (const listing of commands.list()) {\n const entry = commands.get(listing.id)\n if (!entry || entry.extensionId !== id || !entry.spec.hint || !entry.enabled())\n continue\n const chord = commands.keymap.bindings(entry.id)[0]\n if (chord)\n hints.push({ key: chord, label: entry.title() })\n }\n out.tui = { keybindings: commands.keybindings().filter(k => mine(k.id)), footerHints: hints }\n return out\n}\n\n/** What a registry view reads from: the runtime, the entries it refused, and the change feed. */\nexport interface RegistryViewSource {\n /** The runtime. Absent when no extension was loaded into one. */\n readonly runtime?: ExtensionRuntime\n /** The host cwd (panel loads without one). */\n readonly cwd: string\n /** Entries refused before the runtime: load errors, modules without a definition, duplicates. */\n readonly refused: readonly LoadedExtension[]\n /**\n * Takes the refused entry of folder `dir` off the list (the folder was\n * deleted, or it loads into the runtime now). Returns whether there was one.\n */\n dropRefused: (dir: string) => boolean\n /**\n * Replaces the rows a host reports under `group` (config install\n * failures, `config:user`), listed after {@link refused}. An empty list\n * clears the group.\n */\n reportRefused: (group: string, entries: readonly LoadedExtension[]) => void\n /** Bumped on every change; views recompute when it moved. */\n version: () => number\n /** Calls `listener` (coalesced per microtask) after a change. */\n subscribe: (listener: () => void) => () => void\n /** Disposes the runtime. Idempotent. */\n dispose: () => Promise<void>\n}\n\n/** UI tokens whose items the view shows (slots, screens and the rest change without affecting it). */\nconst VIEWED_UI_TOKENS: ReadonlySet<string> = new Set(['panel', 'reference', 'badge-action', 'theme', 'context-section'])\n\nfunction uiChangeMatters(change: UiChange): boolean {\n if (change.type === 'providers')\n return true\n if (change.type === 'panel-changed')\n return false\n return VIEWED_UI_TOKENS.has(change.type === 'upsert' ? change.entry.token : change.token)\n}\n\n/**\n * The change feed and disposal of one runtime, shared by every view of it.\n *\n * @param input - The runtime (absent: nothing ever changes), the host cwd, refused entries and the dispose.\n * @param input.runtime - The runtime.\n * @param input.cwd - The host cwd.\n * @param input.refused - Entries that never reached the runtime.\n * @param input.dispose - Releases the runtime and its ports.\n * @returns The source.\n */\nexport function createRegistryViewSource(input: {\n runtime?: ExtensionRuntime\n cwd: string\n refused: readonly LoadedExtension[]\n dispose: () => Promise<void>\n}): RegistryViewSource & { changed: () => void } {\n let version = 0\n const refused = [...input.refused]\n const reported = new Map<string, readonly LoadedExtension[]>()\n const listeners = new Set<() => void>()\n let queued = false\n let disposed = false\n const unsubscribes: (() => void)[] = []\n const changed = (): void => {\n version++\n if (queued || listeners.size === 0)\n return\n queued = true\n queueMicrotask(() => {\n queued = false\n for (const listener of [...listeners]) {\n try {\n listener()\n }\n catch {}\n }\n })\n }\n const runtime = input.runtime\n if (runtime) {\n const { catalogs, ui, commands } = runtime.outputs\n for (const catalog of [catalogs.tools, catalogs.agents, catalogs.providers, catalogs.mcp, catalogs.skills])\n unsubscribes.push(catalog.subscribe(changed))\n unsubscribes.push(commands.subscribe(changed))\n unsubscribes.push(runtime.subscribe(changed))\n unsubscribes.push(ui.subscribe((change) => {\n if (uiChangeMatters(change))\n changed()\n }))\n }\n return {\n ...(runtime ? { runtime } : {}),\n cwd: input.cwd,\n get refused() { return reported.size === 0 ? refused : [...refused, ...[...reported.values()].flat()] },\n reportRefused: (group, entries) => {\n if (entries.length === 0 && !reported.has(group))\n return\n if (entries.length === 0)\n reported.delete(group)\n else\n reported.set(group, [...entries])\n changed()\n },\n dropRefused: (dir) => {\n const at = refused.findIndex(entry => entry.dir === dir)\n if (at === -1)\n return false\n refused.splice(at, 1)\n changed()\n return true\n },\n version: () => version,\n changed,\n subscribe: (listener) => {\n listeners.add(listener)\n return () => {\n listeners.delete(listener)\n }\n },\n dispose: async () => {\n if (disposed)\n return\n disposed = true\n for (const unsubscribe of unsubscribes.splice(0))\n unsubscribe()\n listeners.clear()\n await input.dispose()\n },\n }\n}\n\n/** How a view narrows its source. */\nexport interface RegistryViewFilter {\n /** Names of the extensions to keep active; the rest show as inactive. `undefined`: all. */\n readonly enabled?: ReadonlySet<string>\n /** Agent Plugin names whose skills and MCP servers drop out. */\n readonly droppedPlugins?: ReadonlySet<string>\n}\n\n/** Every known extension as `LoadedExtension` entries, with their live contributions. */\nfunction loadedEntries(source: RegistryViewSource): { active: LoadedExtension[], inactive: LoadedExtension[] } {\n const active: LoadedExtension[] = []\n const inactive: LoadedExtension[] = []\n const runtime = source.runtime\n for (const info of runtime?.extensions() ?? []) {\n const ext = runtime!.get(info.id)\n if (!ext)\n continue\n const def = ext.definition\n // A declaratively installed extension is a user one here.\n const loadedSource: LoadedExtensionSource = ext.entry.source === 'config' ? 'user' : ext.entry.source\n const base: LoadedExtension = {\n // The folder name is the persisted identity (an id that differs from it fails validation).\n name: ext.entry.dir !== undefined ? basename(ext.entry.dir) : ext.id,\n source: loadedSource,\n ...(ext.entry.dir !== undefined ? { dir: ext.entry.dir } : {}),\n ...(ext.entry.manifest ? { manifest: ext.entry.manifest } : {}),\n ...(def ? { definition: def } : {}),\n setupRan: info.status !== 'disabled',\n }\n if (info.status === 'active' && def)\n active.push({ ...base, contributions: { ...projectActive(runtime!, ext, loadedSource, source.cwd), ...projectSettings(ext, def) } })\n else if (info.status === 'disabled' && def)\n inactive.push({ ...base, contributions: { ...emptyContributions(), ...projectSettings(ext, def) } })\n else\n inactive.push({ ...base, error: info.error ?? 'failed to load' })\n }\n inactive.push(...source.refused)\n return { active, inactive }\n}\n\nfunction pruneDroppedPlugins(ext: LoadedExtension, dropped: ReadonlySet<string>, droppedServers: ReadonlySet<unknown>): LoadedExtension {\n const contributions = ext.contributions\n if (!contributions || contributions.plugins.length === 0)\n return ext\n return {\n ...ext,\n contributions: {\n ...contributions,\n skills: contributions.skills.filter((skill) => {\n const owner = skill.metadata?.['zidane.plugin']\n return owner === undefined || !dropped.has(owner)\n }),\n mcpServers: contributions.mcpServers.filter(server => !droppedServers.has(server)),\n },\n }\n}\n\ntype Merged = Omit<ExtensionRegistry, 'runtime' | 'subscribe' | 'dispose'>\n\n/** Folds the active extensions' contributions; inactive ones add only their settings. */\nfunction merge(active: readonly LoadedExtension[], inactive: readonly LoadedExtension[]): Merged {\n const tools: Record<string, ToolDef> = Object.create(null)\n const hooks: { [E in keyof AgentHooks]?: Array<AgentHooks[E]> } = {}\n const out = {\n mcpServers: [] as Merged['mcpServers'][number][],\n skills: [] as Merged['skills'][number][],\n plugins: [] as LoadedPluginRecord[],\n runSettled: [] as ExtensionOrderedContribution<ExtensionRunSettledHandler>[],\n sessionEvents: [] as ExtensionOrderedContribution<ExtensionSessionEventHandler>[],\n contextBreakdownSections: [] as ContextBreakdownContributor[],\n contextPanelSections: [] as ContextBreakdownContributor[],\n toolResultMetadata: [] as Merged['toolResultMetadata'][number][],\n artifactKinds: [] as Merged['artifactKinds'][number][],\n references: [] as Merged['references'][number][],\n badgeActions: [] as Merged['badgeActions'][number][],\n completionProviders: [] as Merged['completionProviders'][number][],\n inlineAutocompleteProviders: [] as Merged['inlineAutocompleteProviders'][number][],\n commands: [] as Merged['commands'][number][],\n keybindings: [] as ExtensionKeybinding[],\n footerHints: [] as ExtensionFooterHint[],\n panels: [] as ExtensionPanelEntry[],\n palette: [] as Merged['palette'][number][],\n }\n const themes: Record<string, Merged['themes'][string]> = {}\n const agents: Record<string, Merged['agents'][string]> = {}\n const providers: Record<string, Merged['providers'][string]> = {}\n const subagents: Record<string, Merged['subagents'][string]> = {}\n const configCategories: Record<string, ExtensionConfigCategory> = {}\n const configItems: Record<string, Readonly<Record<string, StoredExtensionConfigItem>>> = Object.create(null)\n const seen = { kinds: new Set<string>(), references: new Set<string>(), badges: new Set<string>(), inline: new Set<string>(), commands: new Set<string>(), keys: new Set<string>() }\n\n for (const entry of active) {\n const c = entry.contributions\n if (!c)\n continue\n Object.assign(tools, c.tools)\n for (const [event, list] of Object.entries(c.hooks)) {\n if (!list)\n continue\n const bucket = (hooks[event as keyof AgentHooks] ??= []) as unknown[]\n bucket.push(...list)\n }\n out.mcpServers.push(...c.mcpServers)\n out.skills.push(...c.skills)\n out.plugins.push(...c.plugins)\n for (const value of c.runSettled)\n out.runSettled.push({ extensionName: entry.name, source: entry.source, value })\n for (const value of c.sessionEvents)\n out.sessionEvents.push({ extensionName: entry.name, source: entry.source, value })\n out.contextBreakdownSections.push(...c.contextBreakdownSections)\n out.contextPanelSections.push(...c.contextPanelSections)\n out.toolResultMetadata.push(...c.toolResultMetadata)\n for (const kind of c.artifactKinds) {\n if (seen.kinds.has(kind.value.kind))\n continue\n seen.kinds.add(kind.value.kind)\n out.artifactKinds.push(kind)\n }\n for (const reference of c.references) {\n if (!seen.references.has(reference.value.id)) {\n seen.references.add(reference.value.id)\n out.references.push(reference)\n }\n }\n for (const badge of c.badgeActions) {\n if (!seen.badges.has(badge.value.id)) {\n seen.badges.add(badge.value.id)\n out.badgeActions.push(badge)\n }\n }\n out.completionProviders.push(...c.completionProviders)\n for (const provider of c.inlineAutocompleteProviders) {\n if (seen.inline.has(provider.id))\n continue\n seen.inline.add(provider.id)\n out.inlineAutocompleteProviders.push(provider)\n }\n // First wins by name, case-insensitive like `parseCommandInvocation`; aliases share the namespace.\n for (const command of c.commands) {\n const key = command.name.toLowerCase()\n if (seen.commands.has(key))\n continue\n seen.commands.add(key)\n for (const alias of command.aliases ?? [])\n seen.commands.add(alias.toLowerCase())\n out.commands.push(command)\n }\n Object.assign(themes, c.themes)\n Object.assign(agents, c.agents)\n Object.assign(providers, c.providers)\n Object.assign(subagents, c.subagents)\n Object.assign(configCategories, c.configCategories)\n if (Object.keys(c.configItems).length > 0)\n configItems[entry.name] = { ...c.configItems }\n for (const binding of c.tui.keybindings) {\n if (seen.keys.has(binding.id))\n continue\n seen.keys.add(binding.id)\n out.keybindings.push(binding)\n }\n out.footerHints.push(...c.tui.footerHints)\n out.panels.push(...c.panels)\n out.palette.push(...c.palette)\n }\n\n // Disabled extensions keep their settings visible (and editable) before they are enabled.\n for (const entry of inactive) {\n const c = entry.contributions\n if (entry.error || !c)\n continue\n for (const [id, category] of Object.entries(c.configCategories)) {\n if (!(id in configCategories))\n configCategories[id] = category\n }\n if (Object.keys(c.configItems).length > 0 && !(entry.name in configItems))\n configItems[entry.name] = { ...c.configItems }\n }\n\n return {\n loaded: active,\n inactive,\n tools,\n hooks,\n mcpServers: out.mcpServers,\n skills: out.skills,\n plugins: out.plugins,\n runSettled: out.runSettled,\n sessionEvents: out.sessionEvents,\n contextBreakdownSections: out.contextBreakdownSections,\n contextPanelSections: out.contextPanelSections,\n toolResultMetadata: out.toolResultMetadata,\n artifactKinds: out.artifactKinds,\n references: out.references,\n badgeActions: out.badgeActions,\n completionProviders: out.completionProviders,\n inlineAutocompleteProviders: out.inlineAutocompleteProviders,\n commands: out.commands,\n themes,\n agents,\n providers,\n subagents,\n configCategories,\n configItems,\n tuiContributions: { keybindings: out.keybindings, footerHints: out.footerHints },\n panels: out.panels,\n palette: out.palette,\n }\n}\n\nfunction compute(source: RegistryViewSource, filter: RegistryViewFilter): Merged {\n const { active, inactive } = loadedEntries(source)\n const enabled = filter.enabled\n let kept = enabled ? active.filter(e => enabled.has(e.name)) : active\n const off = enabled ? active.filter(e => !enabled.has(e.name)) : []\n const dropped = filter.droppedPlugins\n if (dropped && dropped.size > 0) {\n const records = kept.flatMap(e => e.contributions?.plugins ?? []).filter(r => dropped.has(r.name))\n if (records.length > 0) {\n const droppedServers = new Set<unknown>(records.flatMap(r => r.plugin.mcpServers))\n kept = kept.map(e => pruneDroppedPlugins(e, dropped, droppedServers))\n }\n }\n return merge(kept, [...inactive, ...off])\n}\n\nconst VIEW_STATE = Symbol('zidane.registryView')\n\ninterface ViewState {\n source: RegistryViewSource\n filter: RegistryViewFilter\n}\n\n/**\n * A live {@link ExtensionRegistry} over `source`, narrowed by `filter`.\n *\n * @param source - The runtime and change feed (`createRegistryViewSource`).\n * @param filter - Allowlist and dropped plugins.\n * @returns The view.\n */\nexport function createRegistryView(source: RegistryViewSource, filter: RegistryViewFilter = {}): ExtensionRegistry {\n let cached: { version: number, value: Merged } | undefined\n const read = (): Merged => {\n const version = source.version()\n if (!cached || cached.version !== version)\n cached = { version, value: compute(source, filter) }\n return cached.value\n }\n const view = {\n get loaded() { return read().loaded },\n get inactive() { return read().inactive },\n get tools() { return read().tools },\n get hooks() { return read().hooks },\n get mcpServers() { return read().mcpServers },\n get skills() { return read().skills },\n get plugins() { return read().plugins },\n get runSettled() { return read().runSettled },\n get sessionEvents() { return read().sessionEvents },\n get contextBreakdownSections() { return read().contextBreakdownSections },\n get contextPanelSections() { return read().contextPanelSections },\n get toolResultMetadata() { return read().toolResultMetadata },\n get artifactKinds() { return read().artifactKinds },\n get references() { return read().references },\n get badgeActions() { return read().badgeActions },\n get completionProviders() { return read().completionProviders },\n get inlineAutocompleteProviders() { return read().inlineAutocompleteProviders },\n get commands() { return read().commands },\n get themes() { return read().themes },\n get agents() { return read().agents },\n get providers() { return read().providers },\n get subagents() { return read().subagents },\n get configCategories() { return read().configCategories },\n get configItems() { return read().configItems },\n get tuiContributions() { return read().tuiContributions },\n get panels() { return read().panels },\n get palette() { return read().palette },\n ...(source.runtime ? { runtime: source.runtime.outputs } : {}),\n subscribe: (listener: () => void) => source.subscribe(listener),\n dispose: () => source.dispose(),\n } satisfies ExtensionRegistry\n Object.defineProperty(view, VIEW_STATE, { value: { source, filter } satisfies ViewState })\n return view\n}\n\n/**\n * The source and filter behind a view from {@link createRegistryView}, or\n * `undefined` for any other registry (`EMPTY_EXTENSION_REGISTRY`, a\n * hand-built one).\n *\n * @param registry - A registry.\n */\nexport function registryViewState(registry: ExtensionRegistry): ViewState | undefined {\n return (registry as { [VIEW_STATE]?: ViewState })[VIEW_STATE]\n}\n","/**\n * Load extensions into the runtime and hand hosts the {@link ExtensionRegistry}:\n * a live view of what they contribute (`runtime/registry-view.ts`).\n *\n * Only `apiVersion: 1` modules load. Discovery already turned a module\n * without a definition into an entry with its error; an entry that reaches\n * here with no definition and no error gets `NO_DEFINITION_ERROR`. Isolation, timeouts, error budgets and\n * rollback are the runtime's (`runtime/host.ts`): a failing extension lands\n * in `inactive` with its error and never stops the others.\n */\n\nimport type { Settings } from '../chat/types'\nimport type { LogSink } from '../logger'\nimport type { ExtensionHostKind, ExtensionPaths } from './api/core'\nimport type { ExtensionHostRuntimeBridge } from './host-runtime'\nimport type { ExtensionPromptBridge } from './prompt-bridge'\nimport type { ExtensionRuntime, ExtensionRuntimeOptions, RuntimePorts } from './runtime/host'\nimport type { ExtensionRuntimeOutputs } from './runtime/outputs'\nimport type { ExtensionRegistry, LoadedExtension } from './types'\nimport { homedir } from 'node:os'\nimport { join } from 'node:path'\nimport { resolveStorageDirs } from '../chat/xdg'\nimport { consoleSink, createLogger } from '../logger'\nimport { claimProviderOAuthFlows } from './provider-oauth'\nimport { isRuntimeLoadedExtension, NO_DEFINITION_ERROR, runtimeEntryOf } from './runtime/loaded-entry'\nimport { createRegistryView, createRegistryViewSource, extensionConfigSettingsPort, registryViewState } from './runtime/registry-view'\n\n/** Options for {@link buildExtensionRegistry}. */\nexport interface BuildExtensionRegistryOptions {\n /**\n * Names the user has explicitly disabled. Loaded but not run (their\n * settings stay readable); listed in `inactive` so the Settings panel\n * can show them.\n */\n disabled?: ReadonlySet<string>\n /** Maximum time one extension's setup may take before it is marked inactive. Default: the runtime's. */\n setupTimeoutMs?: number\n /**\n * Override the log sink. Defaults to a `consoleSink` writing to\n * stderr (which the TUI suppresses to keep the renderer clean —\n * only `ZIDANE_DEBUG=1` surfaces the lines).\n */\n sink?: LogSink\n /**\n * Prompt bridge backing `ctx.sessions.submit` without a session id.\n * Hosts with a submit pipeline attach their handler post-mount.\n */\n promptBridge?: ExtensionPromptBridge\n /**\n * Host runtime bridge backing `ctx.sessions`, `ctx.workspace` and\n * `ctx.artifacts` when `runtime.ports.host` is not given. Late-bound: the\n * host attaches its implementation post-mount.\n */\n hostRuntime?: ExtensionHostRuntimeBridge\n /**\n * Live settings getter: the `user` settings layer (`Settings.extensionConfig`)\n * when `runtime.ports.settings` is not given.\n */\n readSettings?: () => Partial<Settings> | undefined\n /** Runtime cwd used for `ctx.paths`. */\n cwd?: string\n /** Project root exposed as `ctx.paths.projectRoot`. */\n projectRoot?: string\n /** Storage directories exposed through `ctx.paths`. Default: resolved from `prefix` and the platform conventions. */\n storageDirs?: {\n configDir?: string\n dataDir: string\n stateDir?: string\n cacheDir: string\n }\n /** Storage prefix used to resolve the storage directories. Default: `ZIDANE_PREFIX`, else `.zidane`. */\n prefix?: string\n /** Host kind, ports and guard options of the runtime. */\n runtime?: BuildRuntimeOptions\n}\n\n/** How {@link buildExtensionRegistry} builds the runtime. */\nexport interface BuildRuntimeOptions {\n /** The host process. Default `'sdk'`. */\n host?: ExtensionHostKind\n /**\n * Host ports. Defaults: settings read from `readSettings` (the\n * `extensionConfig` bag), storage in files under\n * `<dataDir>/extension-storage` (and `<projectRoot>/<prefix>/extension-storage`),\n * the rest in memory.\n */\n ports?: RuntimePorts\n /** Guard and status options passed through to the runtime. */\n runtime?: Pick<ExtensionRuntimeOptions, 'budget' | 'callbackTimeoutMs' | 'onStall' | 'onChange' | 'memory' | 'platform'>\n}\n\n/** The runtime behind each registry. */\nconst registryRuntimes = new WeakMap<ExtensionRuntimeOutputs, ExtensionRuntime>()\n\n/**\n * The runtime behind `registry.runtime` (load, unload, reload, settings), or\n * `undefined` when the registry loaded no extension.\n *\n * @param registry - A registry from {@link buildExtensionRegistry} (or filtered from one).\n */\nexport function extensionRuntimeOf(registry: Pick<ExtensionRegistry, 'runtime'>): ExtensionRuntime | undefined {\n return registry.runtime ? registryRuntimes.get(registry.runtime) : undefined\n}\n\n/**\n * Load the extensions and return the live registry over them.\n * `loaded` typically comes from `discoverExtensions()` plus any inline\n * ones via `inlineLoadedExtension`.\n *\n * Disabled extensions stay in `inactive` (alongside any load errors)\n * so the Settings panel shows the full picture.\n *\n * @param loaded - Discovered and inline extensions.\n * @param options - Logging, bridges, storage paths, setup limits and the runtime's ports.\n * @example\n * ```ts\n * import { buildExtensionRegistry, discoverExtensions } from 'zidane/extensions'\n *\n * const loaded = await discoverExtensions({ cwd: process.cwd() })\n * const registry = await buildExtensionRegistry(loaded, { cwd: process.cwd() })\n * console.log(Object.keys(registry.tools))\n * ```\n */\nexport async function buildExtensionRegistry(\n loaded: readonly LoadedExtension[],\n options: BuildExtensionRegistryOptions = {},\n): Promise<ExtensionRegistry> {\n const sink = options.sink ?? consoleSink({ minLevel: 'warn' })\n const disabled = options.disabled ?? new Set<string>()\n const paths = resolveContextPaths(options)\n\n const refused: LoadedExtension[] = []\n const loadable: LoadedExtension[] = []\n for (const entry of loaded) {\n if (!isRuntimeLoadedExtension(entry)) {\n refused.push(entry.error ? entry : { ...entry, error: NO_DEFINITION_ERROR })\n continue\n }\n if (loadable.some(e => e.name === entry.name))\n refused.push({ ...entry, error: `Duplicate extension name \"${entry.name}\" ignored; the earlier registration wins.` })\n else\n loadable.push(entry)\n }\n\n if (loadable.length === 0) {\n const source = createRegistryViewSource({ cwd: paths.cwd, refused, dispose: async () => {} })\n return createRegistryView(source)\n }\n\n // Loaded on demand: a host with no extensions never pays for the runtime's module graph.\n const [{ createExtensionRuntime }, { createFileStoragePort }] = await Promise.all([\n import('./runtime/host'),\n import('./storage'),\n ])\n const ports = options.runtime?.ports ?? {}\n // Hosts attach their session runtime to these bridges; the runtime reads the same ones.\n const bridge = options.hostRuntime\n const host = ports.host ?? (bridge\n ? {\n sessions: { sessionControl: bridge.sessionControl, ...(options.promptBridge ? { promptBridge: options.promptBridge } : {}) },\n workspace: { current: bridge.current },\n artifacts: { current: bridge.current },\n }\n : undefined)\n const storage = ports.storage\n ? undefined\n : createFileStoragePort({\n root: join(paths.dataDir, 'extension-storage'),\n ...(paths.projectRoot ? { projectRoot: join(paths.projectRoot, options.prefix ?? process.env.ZIDANE_PREFIX ?? '.zidane', 'extension-storage') } : {}),\n watch: false,\n })\n const runtime = createExtensionRuntime({\n ...options.runtime?.runtime,\n host: options.runtime?.host ?? 'sdk',\n paths,\n logger: createLogger(sink),\n ...(options.setupTimeoutMs !== undefined ? { setupTimeoutMs: options.setupTimeoutMs } : {}),\n ports: {\n ...ports,\n ...(storage ? { storage } : {}),\n settings: ports.settings ?? extensionConfigSettingsPort(options.readSettings),\n ...(host ? { host } : {}),\n },\n })\n registryRuntimes.set(runtime.outputs, runtime)\n let releaseOAuthFlows: () => void = () => {}\n const source = createRegistryViewSource({\n runtime,\n cwd: paths.cwd,\n refused,\n dispose: async () => {\n releaseOAuthFlows()\n await runtime.dispose()\n storage?.close()\n },\n })\n await runtime.load(loadable.map(entry => runtimeEntryOf(entry, !disabled.has(entry.name))))\n const registry = createRegistryView(source)\n // Providers' OAuth flows ride their contribution: registered for the active\n // extensions now, released on dispose (see ./provider-oauth).\n releaseOAuthFlows = claimProviderOAuthFlows(registry.loaded, sink)\n return registry\n}\n\n/**\n * Filter the extension registry by the user's enable allowlist. Returns\n * the original registry by reference when `enabled` is `undefined` (the\n * fresh-install default — every loaded extension is active) or when it\n * keeps every active extension; otherwise a live view over the same\n * runtime with the others listed as inactive.\n *\n * The identity check is intentional — callers can compare the result\n * against the input registry to skip recomposing the preset when\n * nothing has changed.\n *\n * @param registry - Registry to filter.\n * @param enabled - Names of the enabled extensions. `undefined` keeps every extension.\n */\nexport function filterExtensionRegistry(\n registry: ExtensionRegistry,\n enabled: readonly string[] | undefined,\n): ExtensionRegistry {\n if (enabled === undefined)\n return registry\n const allow = new Set(enabled)\n if (registry.loaded.every(ext => allow.has(ext.name)))\n return registry\n const state = registryViewState(registry)\n if (!state)\n return registry\n const narrowed = state.filter.enabled ? new Set([...state.filter.enabled].filter(name => allow.has(name))) : allow\n return createRegistryView(state.source, { ...state.filter, enabled: narrowed })\n}\n\n/**\n * Drop the contributions of Agent Plugins the user has disabled.\n *\n * `filterExtensionRegistry` keys on EXTENSION names, so it can't express\n * \"this extension runs, but the plugin it loaded does not\". Plugin skills and\n * MCP servers are fanned into the loading extension's contributions by\n * `ctx.plugins.load`, which means without this pass `enabledPlugins` would\n * render a checkbox that changes nothing for extension-loaded plugins.\n *\n * Skills are matched by `metadata['zidane.plugin']` (stamped by the loader);\n * MCP servers carry no such marker, so they're matched by identity against\n * the server list on each {@link LoadedPluginRecord}.\n *\n * Returns the input registry unchanged when nothing is disabled, so callers\n * can compare identity to skip recomposing.\n *\n * @param registry - Registry to filter.\n * @param enabledPlugins - Names of the enabled plugins. `undefined` keeps every plugin.\n * @param shadowed - Plugin names already provided by another source (in\n * practice: disk discovery), pruned regardless of the allowlist. The\n * settings list dedupes such a plugin to ONE row preferring the disk copy;\n * contributions have to agree, or that single checkbox governs two live\n * copies.\n */\nexport function filterRegistryPlugins(\n registry: ExtensionRegistry,\n enabledPlugins: readonly string[] | undefined,\n shadowed?: ReadonlySet<string>,\n): ExtensionRegistry {\n if (registry.plugins.length === 0)\n return registry\n const allow = enabledPlugins === undefined ? null : new Set(enabledPlugins)\n const dropped = registry.plugins.filter(record =>\n (allow !== null && !allow.has(record.name)) || shadowed?.has(record.name) === true)\n if (dropped.length === 0)\n return registry\n const state = registryViewState(registry)\n if (!state)\n return registry\n const droppedPlugins = new Set([...(state.filter.droppedPlugins ?? []), ...dropped.map(record => record.name)])\n return createRegistryView(state.source, { ...state.filter, droppedPlugins })\n}\n\n/**\n * Dispose resources owned by an extension registry. Idempotent per registry.\n *\n * @param registry - Registry to dispose.\n */\nexport async function disposeExtensionRegistry(registry: ExtensionRegistry): Promise<void> {\n await registry.dispose()\n}\n\n/** Shape returned by {@link partitionExtensionCatalog}. */\nexport interface ExtensionCatalogPartition {\n /**\n * Rows the user can toggle: active extensions plus disabled-but-\n * loadable ones, sorted by name so the list order is stable across\n * boots regardless of where each entry landed in the registry.\n */\n toggleable: readonly LoadedExtension[]\n /** Entries whose import or `setup()` failed — read-only diagnostics. */\n errored: readonly LoadedExtension[]\n /**\n * Every known extension name — toggleable AND errored. Use this as\n * the GC key set for the persisted `enabledExtensions` allowlist so\n * an untrusted / temporarily-broken extension isn't permanently\n * dropped from the allowlist by an unrelated toggle.\n */\n allNames: readonly string[]\n}\n\n/**\n * Partition a registry's `loaded` + `inactive` lists into the shape the\n * Settings toggle UIs render. Pure; shared by the TUI's standalone\n * extensions modal and the Settings-modal tab so the rules (and the\n * allowlist-GC key set) stay in one place.\n *\n * @param loaded - Active extensions.\n * @param inactive - Disabled or failed extensions.\n */\nexport function partitionExtensionCatalog(\n loaded: readonly LoadedExtension[],\n inactive: readonly LoadedExtension[],\n): ExtensionCatalogPartition {\n const errored = inactive.filter(e => !!e.error)\n const disabledOk = inactive.filter(e => !e.error)\n const toggleable = [...loaded, ...disabledOk].sort((a, b) => a.name.localeCompare(b.name))\n return {\n toggleable,\n errored,\n allNames: [...toggleable.map(e => e.name), ...errored.map(e => e.name)],\n }\n}\n\nfunction resolveContextPaths(options: BuildExtensionRegistryOptions): ExtensionPaths {\n const cwd = options.cwd ?? process.cwd()\n const dirs = options.storageDirs ?? resolveStorageDirs({\n prefix: options.prefix ?? process.env.ZIDANE_PREFIX ?? '.zidane',\n home: homedir(),\n })\n return {\n cwd,\n ...(options.projectRoot ? { projectRoot: options.projectRoot } : {}),\n dataDir: dirs.dataDir,\n cacheDir: dirs.cacheDir,\n ...(dirs.configDir ? { configDir: dirs.configDir } : {}),\n ...(dirs.stateDir ? { stateDir: dirs.stateDir } : {}),\n }\n}\n","/**\n * Reloading the extensions whose folders changed, one by one, instead of\n * rebuilding the whole registry: a changed folder is imported again and its\n * extension reloaded in place (`ExtensionRuntime.reload`), a new folder is\n * loaded, a deleted one unloaded. The other extensions keep running, their\n * state untouched. The registry view over the runtime tells its subscribers.\n */\n\nimport type { LogSink } from '../../logger'\nimport type { ExtensionSource } from '../api/core'\nimport type { ExtensionRegistry } from '../types'\nimport type { ExtensionRuntime } from './host'\nimport { existsSync } from 'node:fs'\nimport { resolve } from 'node:path'\nimport { findEntryFile, loadExtensionFolder } from '../discovery'\nimport { extensionRuntimeOf } from '../register'\nimport { runtimeEntryOf } from './loaded-entry'\nimport { registryViewState } from './registry-view'\n\n/** How a folder the runtime does not hold may load. */\nexport interface NewExtensionFolder {\n /** Where it was found. */\n source: ExtensionSource\n /** `false`: listed disabled (not in the user's allowlist). Default `true`. */\n enabled?: boolean\n}\n\n/** Options of {@link reloadChangedExtensions}. */\nexport interface ReloadChangedOptions {\n /**\n * Whether a folder no extension was loaded from may load now, and how.\n * `undefined`: it may not (not under a scan root, an untrusted project\n * folder, shadowed by a folder of the same name that wins). Without\n * `classify`, new folders are ignored.\n */\n classify?: (dir: string) => NewExtensionFolder | undefined\n /** How long one import may take. Default 10 s. */\n importTimeoutMs?: number\n /** Where load warnings go. Default: warnings to stderr. */\n sink?: LogSink\n /** Node hosts: the folder compiled extension code is kept in. */\n compileCache?: string\n}\n\n/** What {@link reloadChangedExtensions} did, by extension id. */\nexport interface ReloadChangedResult {\n /** New folders that loaded (active, disabled or failed). */\n loaded: string[]\n /** Extensions imported again and reloaded in place. */\n reloaded: string[]\n /** Extensions whose folder (or entry file) is gone. */\n unloaded: string[]\n /**\n * A change could not be applied in place: the registry holds no runtime\n * (it loaded no extension), so a new folder needs a full rebuild.\n */\n needsRebuild: boolean\n}\n\nfunction isRuntime(target: ExtensionRuntime | ExtensionRegistry): target is ExtensionRuntime {\n return typeof (target as Partial<ExtensionRuntime>).idOfDir === 'function'\n}\n\n/**\n * Applies folder changes to a runtime: a held folder that changed is\n * imported fresh and reloaded in place; one whose folder or entry file is\n * gone is unloaded (its `ctx.storage.memory` cleared); a new folder loads\n * when `options.classify` allows it. Given a registry, a folder it refused\n * at build time (its import failed, an untrusted project folder) counts as\n * new, and leaves the refused list once it loads or is deleted. Folders are\n * handled one at a time, in the order given (duplicates once). Never rejects\n * for an extension's fault: a module that fails to import is listed\n * `failed` with the error.\n *\n * @param target - A registry from `buildExtensionRegistry` (or a view of one), or its runtime.\n * @param changedDirs - Extension folders that changed (absolute).\n * @param options - How new folders load, import bound, sink and compile cache.\n * @returns The ids loaded, reloaded and unloaded, and whether a rebuild is needed.\n * @example\n * ```ts\n * await reloadChangedExtensions(registry, ['/home/me/.zidane/extensions/notes'], {\n * classify: dir => (loadableExtensionDirs({ cwd }).includes(dir) ? { source: 'user' } : undefined),\n * })\n * ```\n */\nexport async function reloadChangedExtensions(target: ExtensionRuntime | ExtensionRegistry, changedDirs: readonly string[], options: ReloadChangedOptions = {}): Promise<ReloadChangedResult> {\n const runtime = isRuntime(target) ? target : extensionRuntimeOf(target)\n const source = isRuntime(target) ? undefined : registryViewState(target)?.source\n const result: ReloadChangedResult = { loaded: [], reloaded: [], unloaded: [], needsRebuild: false }\n const importOptions = {\n ...(options.importTimeoutMs !== undefined ? { importTimeoutMs: options.importTimeoutMs } : {}),\n ...(options.sink ? { sink: options.sink } : {}),\n ...(options.compileCache !== undefined ? { compileCache: options.compileCache } : {}),\n }\n const refusedDir = (dir: string): string | undefined => source?.refused.find(entry => entry.dir !== undefined && resolve(entry.dir) === dir)?.dir\n for (const dir of [...new Set(changedDirs.map(d => resolve(d)))]) {\n const id = runtime?.idOfDir(dir)\n const present = existsSync(dir) && findEntryFile(dir) !== null\n if (runtime && id !== undefined) {\n if (!present) {\n await runtime.unload(id, { forget: true })\n result.unloaded.push(id)\n continue\n }\n const held = runtime.get(id)!.entry\n const loaded = await loadExtensionFolder(dir, { source: held.source === 'project' ? 'project' : 'user', ...importOptions })\n const info = await runtime.reload(id, { entry: { ...runtimeEntryOf(loaded, held.enabled), source: held.source } })\n if (info)\n result.reloaded.push(info.id)\n continue\n }\n const refused = refusedDir(dir)\n if (!present) {\n if (refused !== undefined)\n source!.dropRefused(refused)\n continue\n }\n const how = options.classify?.(dir)\n if (!how)\n continue\n if (!runtime) {\n result.needsRebuild = true\n continue\n }\n const loaded = await loadExtensionFolder(dir, { source: how.source === 'project' ? 'project' : 'user', ...importOptions })\n const [info] = await runtime.load([{ ...runtimeEntryOf(loaded, how.enabled), source: how.source }])\n if (refused !== undefined)\n source!.dropRefused(refused)\n if (info)\n result.loaded.push(info.id)\n }\n return result\n}\n","/**\n * Declarative extension config: the `extensions` array in a zidane\n * config file (user `<configDir>/config.json`, project\n * `<project-root>/.zidane/config.json`).\n *\n * ```json\n * { \"extensions\": [\n * { \"source\": \"owner/repo\" },\n * { \"source\": \"github:owner/repo@v1.2.0:extensions/goal\", \"settings\": { \"model\": \"opus\" } },\n * { \"source\": \"owner/collection name\", \"enabled\": false },\n * { \"source\": \"@scope/pkg@1.0.0\" },\n * { \"source\": \"./tools/my-extension\" }\n * ] }\n * ```\n *\n * Remote sources use the install grammar of `parseInstallSource`\n * (`src/install/source.ts`), the same one `installExtensionFromSpec` takes. A\n * trailing word after a space picks one extension of a collection\n * (`owner/repo name`), like the `extension` field. Local paths (`./`, `../`, `/`,\n * `~/`, `file:`) are loaded in place, never copied.\n *\n * Everything here is pure: the caller reads the file and passes the parsed\n * JSON in.\n */\n\nimport type { InstallSource } from '../../install/source'\nimport { basename, isAbsolute, resolve } from 'node:path'\nimport { InstallSourceError, parseInstallSource } from '../../install/source'\nimport { isSettingKey } from '../settings/validate'\n\n/** The config file an entry came from. Each scope has its own lock file. */\nexport type ExtensionsConfigScope = 'user' | 'project'\n\n/** A value a config entry may give a setting. Secrets are refused: they belong in the auth store. */\nexport type ConfigSettingValue = string | number | boolean | readonly string[]\n\n/** Where a declared extension comes from. */\nexport type DeclaredLocation\n = | { readonly kind: 'remote', readonly source: InstallSource }\n | { readonly kind: 'local', readonly path: string }\n\n/** One valid entry of the `extensions` array. */\nexport interface DeclaredExtension {\n /**\n * Identity of the entry: the source without its ref or version, plus the\n * picked extension. Keys the lock file, so changing a ref is an update of\n * the same entry, not a new one.\n */\n readonly key: string\n /** The `source` string as written (trimmed). Compared with the lock to detect a changed pin. */\n readonly source: string\n /** The spec handed to the installer: `source` without the trailing extension name. */\n readonly installSpec: string\n /** The extension picked from a collection, when one was. */\n readonly extension?: string\n readonly location: DeclaredLocation\n /** Settings values this entry sets. They show as locked in Settings. */\n readonly settings: Readonly<Record<string, ConfigSettingValue>>\n /** `false` keeps the extension installed but not loaded. Default `true`. */\n readonly enabled: boolean\n readonly scope: ExtensionsConfigScope\n /** Position in the array, for messages. */\n readonly index: number\n}\n\n/** A problem found in a config or lock file. Errors drop the entry; warnings keep it. */\nexport interface ExtensionsConfigDiagnostic {\n readonly level: 'error' | 'warning'\n readonly scope: ExtensionsConfigScope\n /** Index of the entry in the `extensions` array, when the problem is in one. */\n readonly index?: number\n readonly message: string\n}\n\n/** What {@link parseExtensionsConfig} needs besides the JSON. */\nexport interface ParseExtensionsConfigOptions {\n readonly scope: ExtensionsConfigScope\n /** Relative local paths resolve against it (the project root, or the user config dir). */\n readonly baseDir: string\n /** Home directory for `~/` paths. */\n readonly home: string\n}\n\n/** Result of {@link parseExtensionsConfig}. */\nexport interface ParsedExtensionsConfig {\n readonly entries: readonly DeclaredExtension[]\n readonly diagnostics: readonly ExtensionsConfigDiagnostic[]\n}\n\nconst ENTRY_FIELDS = new Set(['source', 'extension', 'settings', 'enabled'])\nconst NAME_RE = /^[\\w.-]+$/\n\n/**\n * Whether `source` names a local directory rather than a GitHub repo or npm\n * package.\n *\n * @param source - A trimmed source string.\n */\nexport function isLocalSource(source: string): boolean {\n return source === '.' || source === '~' || source.startsWith('./') || source.startsWith('../')\n || source.startsWith('/') || source.startsWith('~/') || source.startsWith('file:')\n || /^[a-z]:[\\\\/]/i.test(source)\n}\n\n/**\n * Splits `owner/repo name` into the install spec and the picked extension.\n * Local paths are never split: a space is part of the path.\n *\n * @param source - A trimmed source string.\n */\nexport function splitSourceSpec(source: string): { spec: string, extension?: string } {\n if (isLocalSource(source))\n return { spec: source }\n const m = /^(\\S+)\\s+(\\S+)$/.exec(source)\n return m ? { spec: m[1] as string, extension: m[2] as string } : { spec: source }\n}\n\n/**\n * The identity of a source: GitHub owner/repo and subdir, npm package name,\n * or the local path as written. Ref and version are left out.\n *\n * @param location - The parsed source.\n * @param localSpec - For a local source, the path as written (identity stays stable across machines).\n * @param extension - The extension picked from a collection.\n */\nexport function sourceIdentity(location: DeclaredLocation, localSpec: string, extension?: string): string {\n const base = location.kind === 'local'\n ? `local:${localSpec}`\n : location.source.kind === 'npm'\n ? `npm:${location.source.pkg}`\n : `github:${location.source.owner.toLowerCase()}/${location.source.repo.toLowerCase()}${location.source.subdir ? `:${location.source.subdir}` : ''}`\n return extension ? `${base}#${extension}` : base\n}\n\n/**\n * The identity of an install spec as recorded in `.install.json`, or\n * `undefined` when it does not parse. Lets a planner recognize an extension\n * installed by hand from the same source as a config entry.\n *\n * @param spec - A remote install spec.\n * @param extension - The extension picked from a collection.\n */\nexport function installSpecIdentity(spec: string, extension?: string): string | undefined {\n try {\n return sourceIdentity({ kind: 'remote', source: parseInstallSource(spec) }, spec, extension)\n }\n catch {\n return undefined\n }\n}\n\n/**\n * The local directory `source` points at, absolute.\n *\n * @param source - A local source string.\n * @param baseDir - Directory relative paths resolve against.\n * @param home - Home directory for `~`.\n */\nexport function resolveLocalSource(source: string, baseDir: string, home: string): string {\n const path = source.startsWith('file:') ? source.slice('file:'.length).replace(/^\\/\\/(?=\\/)/, '') : source\n if (path === '~')\n return home\n if (path.startsWith('~/'))\n return resolve(home, path.slice(2))\n return isAbsolute(path) ? resolve(path) : resolve(baseDir, path)\n}\n\n/**\n * The id a local source loads as: its folder name, as discovery requires.\n *\n * @param path - The resolved local directory.\n */\nexport function localExtensionId(path: string): string {\n return basename(path)\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === 'object' && !Array.isArray(value)\n}\n\nfunction isSettingValue(value: unknown): value is ConfigSettingValue {\n if (typeof value === 'string' || typeof value === 'boolean')\n return true\n if (typeof value === 'number')\n return Number.isFinite(value)\n return Array.isArray(value) && value.every(v => typeof v === 'string')\n}\n\n/**\n * Parses the `extensions` field of a config file. Never throws: a bad entry\n * is dropped with an error diagnostic, an odd field kept with a warning.\n * A source declared twice keeps its first entry.\n *\n * @param config - The whole parsed config file (its `extensions` field is read), or `undefined` when there is no file.\n * @param options - Scope, base directory and home.\n */\nexport function parseExtensionsConfig(config: unknown, options: ParseExtensionsConfigOptions): ParsedExtensionsConfig {\n const { scope } = options\n const diagnostics: ExtensionsConfigDiagnostic[] = []\n const entries: DeclaredExtension[] = []\n if (config === undefined || config === null)\n return { entries, diagnostics }\n if (!isRecord(config)) {\n diagnostics.push({ level: 'error', scope, message: 'The config file is not a JSON object.' })\n return { entries, diagnostics }\n }\n const list = config.extensions\n if (list === undefined)\n return { entries, diagnostics }\n if (!Array.isArray(list)) {\n diagnostics.push({ level: 'error', scope, message: '\"extensions\" must be an array of { source, settings?, enabled? }.' })\n return { entries, diagnostics }\n }\n const seen = new Map<string, number>()\n list.forEach((raw, index) => {\n const fail = (message: string): void => {\n diagnostics.push({ level: 'error', scope, index, message })\n }\n const warn = (message: string): void => {\n diagnostics.push({ level: 'warning', scope, index, message })\n }\n if (!isRecord(raw))\n return fail('An entry must be an object with a \"source\".')\n if (typeof raw.source !== 'string' || raw.source.trim() === '')\n return fail('\"source\" must be a non-empty string.')\n for (const field of Object.keys(raw)) {\n if (!ENTRY_FIELDS.has(field))\n warn(`Unknown field \"${field}\" is ignored.`)\n }\n const source = raw.source.trim()\n const split = splitSourceSpec(source)\n let extension = split.extension\n if (raw.extension !== undefined) {\n if (typeof raw.extension !== 'string' || !NAME_RE.test(raw.extension))\n return fail('\"extension\" must be an extension name ([A-Za-z0-9_.-]).')\n if (extension !== undefined && extension !== raw.extension)\n return fail(`\"source\" picks \"${extension}\" but \"extension\" says \"${raw.extension}\".`)\n extension = raw.extension\n }\n if (extension !== undefined && !NAME_RE.test(extension))\n return fail(`\"${extension}\" is not an extension name ([A-Za-z0-9_.-]).`)\n\n let location: DeclaredLocation\n if (isLocalSource(split.spec)) {\n if (extension !== undefined)\n return fail('A local source points at one extension folder; \"extension\" does not apply.')\n location = { kind: 'local', path: resolveLocalSource(split.spec, options.baseDir, options.home) }\n }\n else {\n try {\n location = { kind: 'remote', source: parseInstallSource(split.spec) }\n }\n catch (err) {\n return fail(err instanceof InstallSourceError ? err.message : `\"${source}\" is not a valid source.`)\n }\n }\n\n let enabled = true\n if (raw.enabled !== undefined) {\n if (typeof raw.enabled !== 'boolean')\n return fail('\"enabled\" must be true or false.')\n enabled = raw.enabled\n }\n\n const settings: Record<string, ConfigSettingValue> = {}\n if (raw.settings !== undefined) {\n if (!isRecord(raw.settings))\n return fail('\"settings\" must be an object of setting values.')\n for (const [key, value] of Object.entries(raw.settings)) {\n if (!isSettingKey(key))\n warn(`Setting \"${key}\" is not a valid key and is ignored.`)\n else if (!isSettingValue(value))\n warn(`Setting \"${key}\" must be a string, number, boolean or list of strings. It is ignored.`)\n else\n settings[key] = value\n }\n }\n\n const key = sourceIdentity(location, split.spec, extension)\n const first = seen.get(key)\n if (first !== undefined)\n return fail(`\"${source}\" is the same extension as entry ${first}. Only the first is used.`)\n seen.set(key, index)\n entries.push({\n key,\n source,\n installSpec: split.spec,\n ...(extension !== undefined ? { extension } : {}),\n location,\n settings,\n enabled,\n scope,\n index,\n })\n })\n return { entries, diagnostics }\n}\n","/**\n * Extension import — fetch from GitHub or npm, validate, and install into\n * the roots {@link discoverExtensions} already scans.\n *\n * Host-agnostic by construction: no UI, no settings access, no renderer.\n * The TUI's `Settings → Extensions` install flow (`ctrl+g`) and the GUI\n * call the same {@link installExtensionFromSpec} orchestrator; hosts own scope\n * selection, overwrite confirmation, allowlist updates, and the\n * post-install registry rebuild (the `/reload` path).\n *\n * Pipeline invariants:\n *\n * - **Validate before touching user roots.** The candidate is imported\n * and validated (an `apiVersion: 1` definition, checked like the\n * runtime does with `validateDefinition`) inside the temp dir; a failure installs nothing.\n * Importing executes the extension's top-level code once — the\n * explicit install request is the consent; it's the same code that\n * would run at next boot.\n * - **Folder name = definition name, by construction.** The target dir\n * is named from the validated definition's `id`, so discovery's\n * name-match invariant can't be violated by an install.\n * - **Dependency installs never run lifecycle scripts** (bun's default;\n * the npm/pnpm/yarn fallbacks get `--ignore-scripts`).\n * - Failures throw {@link ExtensionInstallError} with a machine-readable\n * `code` so hosts can react (e.g. `exists` → confirm-and-retry with\n * `overwrite`), never half-install.\n *\n * Recognized package shapes (both fetch targets):\n *\n * - root `index.{ts,tsx,mjs,js}` → a single-extension repo/package\n * - `extensions/<name>/index.*` → a multi-extension collection;\n * `extension` selects one (mandatory when several exist)\n */\n\nimport type { FetchSourceResult, InstallIo, InstallScope, InstallSource } from '../install/source'\nimport { cpSync, existsSync, lstatSync, mkdirSync, mkdtempSync, readdirSync, readFileSync, renameSync, rmSync, writeFileSync } from 'node:fs'\nimport { tmpdir } from 'node:os'\nimport { basename, dirname, join, resolve } from 'node:path'\nimport { projectUserPaths } from '../chat/project-user-paths'\nimport { errorMessage } from '../errors'\nimport { defaultExec, defaultWhich, fetchInstallSource, InstallSourceError, lastLine, parseInstallSource, resolveNpmVersion, resolveSubdirRoot } from '../install/source'\nimport { EXTENSION_API_VERSION } from './api/define'\nimport { definitionExport, findEntryFile, importExtensionEntry, readExtensionManifest, releaseExtensionModules } from './discovery'\nimport { checkZidaneVersion } from './host-version'\nimport { validateDefinition } from './runtime/validate-definition'\nimport { withTimeout } from './with-timeout'\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/** Where an extension is installed: the project or the user directory. */\nexport type ExtensionInstallScope = InstallScope\n\n/** The shared install-source shape — see `src/install/source.ts` for the grammar. */\nexport type ExtensionInstallSource = InstallSource\n\n/** Reason an install, update or removal failed. Matches {@link ExtensionInstallError.code}. */\nexport type ExtensionInstallErrorCode\n = | 'invalid-source'\n | 'fetch-failed'\n | 'no-extension'\n | 'multiple-candidates'\n | 'deps-failed'\n | 'validate-failed'\n | 'exists'\n | 'no-package-manager'\n | 'not-installed'\n | 'no-provenance'\n | 'name-mismatch'\n\n/** Error thrown by the extension installer. `code` says which step failed. */\nexport class ExtensionInstallError extends InstallSourceError {\n /** Machine-readable reason for the failure. */\n declare readonly code: ExtensionInstallErrorCode\n /**\n * Creates an install error.\n * @param code - Reason for the failure.\n * @param message - Human-readable description.\n * @param candidates - Extension names found in the source, set for `multiple-candidates`, `no-extension` and `name-mismatch`.\n */\n constructor(code: ExtensionInstallErrorCode, message: string, candidates?: readonly string[]) {\n super(code, message, candidates)\n this.name = 'ExtensionInstallError'\n }\n}\n\n/**\n * Re-raise a shared-layer {@link InstallSourceError} in the extension\n * error vocabulary so every consumer keeps a single `err.code` switch\n * over {@link ExtensionInstallErrorCode}. The base layer only throws\n * `'invalid-source'` / `'fetch-failed'` — both members of the extension\n * union.\n */\nfunction rethrowAsExtensionError(err: unknown): never {\n if (err instanceof InstallSourceError && !(err instanceof ExtensionInstallError))\n throw new ExtensionInstallError(err.code as ExtensionInstallErrorCode, err.message, err.candidates)\n throw err\n}\n\nconst PROVENANCE_FILE = '.install.json'\n\n/** What `.install.json` records — enough to replay the install for updates. */\nexport interface ExtensionInstallProvenance {\n /** Resolved provenance, e.g. `npm:foo@1.2.3` / `github:owner/repo@main`. */\n source: string\n /** The raw spec the user passed — what an update re-resolves. */\n spec: string\n /** Scope the extension was installed into. */\n scope: ExtensionInstallScope\n /** Candidate selected from a multi-extension source, when one was. */\n extension?: string\n /** Exact commit SHA (GitHub via git clone) — anchors the update no-op check. */\n commit?: string\n /** ISO 8601 timestamp of the install. */\n installedAt: string\n}\n\n/** Where an installed extension came from, from its `.install.json`: what Settings shows (\"Update from <label>\"). */\nexport interface ExtensionInstallOrigin {\n /** The spec it was installed from, what an update re-resolves (`Tahul/zidane#v9.0.4:extensions/goal`). */\n spec: string\n /** A short name of the source: `Tahul/zidane`, `Tahul/zidane@v9.0.4`, `@scope/pkg`. */\n label: string\n /** The resolved provenance (`github:Tahul/zidane@v9.0.4:extensions/goal`, `npm:pkg@1.2.3`). */\n source: string\n /** The exact commit, when the install cloned it. */\n commit?: string\n /** When it was installed (ISO 8601), when recorded. */\n installedAt?: string\n}\n\n/** One installable extension found inside a fetched tree. */\nexport interface ExtensionInstallCandidate {\n /** Proposed name (manifest name, else collection dirname, else repo/pkg basename). */\n name: string\n /** Absolute directory inside the fetched tree. */\n dir: string\n}\n\n/** Outcome of an install or update. */\nexport interface ExtensionInstallResult {\n /** Final name — the validated `definition.name`. */\n name: string\n /** Absolute installed directory. */\n dir: string\n /** Scope the extension was installed into. */\n scope: ExtensionInstallScope\n /** Human-readable provenance, e.g. `npm:foo@1.2.3` / `github:owner/repo@main`. */\n provenance: string\n /** Exact commit SHA when known (GitHub via git clone). */\n commit?: string\n /** Non-fatal problems met during the install, such as dependency install notices. */\n warnings: readonly string[]\n}\n\n/**\n * Injectable side-effect seams — tests swap these to stay offline; hosts\n * normally omit the whole object. Shared shape with the skills installer.\n */\nexport type ExtensionInstallIo = InstallIo\n\n/** Options for {@link installExtensionFromSpec}. */\nexport interface InstallExtensionFromSpecOptions {\n /** Raw source spec — see {@link parseExtensionInstallSource}. */\n source: string\n /** Candidate name to install when the source contains several extensions. */\n extension?: string\n /**\n * The name the install must have: the candidate of that name, else the\n * only candidate, and its definition's id must equal it. Anything else\n * fails with `name-mismatch` (listing the names found) before the target\n * is touched. Used by {@link changeExtensionOrigin}.\n */\n expectName?: string\n /**\n * Candidate to pick when the source contains several and `extension` is unset: an update of an\n * install recorded without one (older hosts did not record it). Unlike `extension`, a source\n * with one candidate, or none of that name, is not an error. The pick is recorded.\n */\n fallbackExtension?: string\n /** Scope to install into. */\n scope: ExtensionInstallScope\n /** Replace an existing install of the same name. Default false → `exists` error. */\n overwrite?: boolean\n /** Working directory used to find the project root. @default process.cwd() */\n cwd?: string\n /** User home directory. @default os.homedir() */\n home?: string\n /** Storage prefix (e.g. `.zidane`). Matches discovery's default. */\n prefix?: string\n /** Called with a short status message as each step runs. */\n onProgress?: (message: string) => void\n /** Overrides for fetch, process execution and executable lookup. Mainly for tests. */\n io?: ExtensionInstallIo\n /** Timeout for the validation import. Default 10s (matches discovery). */\n importTimeoutMs?: number\n /**\n * Advanced: exact extensions root to install into, bypassing the\n * scope → `.{prefix}/extensions` resolution. Used by\n * {@link updateInstalledExtension} to replace an install in place\n * (e.g. one living under `.agents/extensions`).\n */\n installRoot?: string\n}\n\n// ---------------------------------------------------------------------------\n// Source spec parsing + fetch — thin wrappers over the shared install\n// layer (`src/install/source.ts`), re-raised in the extension error\n// vocabulary. The grammar, fetch pipeline, caps, and hardening live\n// there so the skills installer shares them verbatim.\n// ---------------------------------------------------------------------------\n\n/**\n * Classify a raw source string. See `parseInstallSource` for the grammar.\n *\n * @param raw - Source spec such as `owner/repo`, `npm:pkg` or a git URL.\n */\nexport function parseExtensionInstallSource(raw: string): ExtensionInstallSource {\n try {\n return parseInstallSource(raw)\n }\n catch (err) {\n rethrowAsExtensionError(err)\n }\n}\n\n/** Result of {@link fetchExtensionSource}: the provenance string and, for git clones, the commit SHA. */\nexport type ExtensionFetchResult = FetchSourceResult\n\n/**\n * Materialize the source into `destDir` (created by the caller, assumed\n * empty). Returns the provenance string plus, for git clones, the exact\n * commit SHA. See `fetchInstallSource` for transport details and caps.\n *\n * @param source - Parsed install source.\n * @param destDir - Empty directory to fetch into.\n * @param io - Overrides for fetch, process execution and executable lookup.\n * @param onProgress - Called with a short status message as the fetch runs.\n */\nexport async function fetchExtensionSource(\n source: ExtensionInstallSource,\n destDir: string,\n io: ExtensionInstallIo = {},\n onProgress?: (message: string) => void,\n): Promise<ExtensionFetchResult> {\n try {\n return await fetchInstallSource(source, destDir, io, onProgress)\n }\n catch (err) {\n rethrowAsExtensionError(err)\n }\n}\n\n// ---------------------------------------------------------------------------\n// Candidate enumeration\n// ---------------------------------------------------------------------------\n\n/**\n * List the installable extensions inside a fetched tree. `fallbackName`\n * seeds the single-extension case when no manifest names it (repo or\n * unscoped package basename).\n *\n * @param dir - Root of the fetched tree.\n * @param fallbackName - Name to use when no manifest names the extension.\n */\nexport function listExtensionCandidates(dir: string, fallbackName: string): ExtensionInstallCandidate[] {\n if (findEntryFile(dir))\n return [{ name: readExtensionManifest(dir).manifest?.name ?? sanitizeName(fallbackName), dir }]\n const collection = join(dir, 'extensions')\n const out: ExtensionInstallCandidate[] = []\n let children: string[]\n try {\n children = readdirSync(collection)\n }\n catch {\n return out\n }\n for (const child of children.sort()) {\n if (child.startsWith('.'))\n continue\n const childDir = join(collection, child)\n try {\n if (!lstatSync(childDir).isDirectory())\n continue\n }\n catch {\n continue\n }\n if (findEntryFile(childDir))\n out.push({ name: child, dir: childDir })\n }\n return out\n}\n\n/** Basename-ish fallback: strip npm scope, keep folder-safe chars. */\nfunction sanitizeName(raw: string): string {\n const base = raw.includes('/') ? (raw.split('/').pop() as string) : raw\n return base.replace(/[^\\w.-]+/g, '-').replace(/^[.-]+/, '') || 'extension'\n}\n\n// ---------------------------------------------------------------------------\n// Orchestrator\n// ---------------------------------------------------------------------------\n\n/**\n * The full fetch → enumerate → deps → validate → copy pipeline. See the\n * module doc for invariants. Throws {@link ExtensionInstallError}; a throw\n * means nothing was written to the target roots.\n *\n * @param opts - Source, scope and install options.\n */\nexport async function installExtensionFromSpec(opts: InstallExtensionFromSpecOptions): Promise<ExtensionInstallResult> {\n const io = opts.io ?? {}\n const onProgress = opts.onProgress\n const source = parseExtensionInstallSource(opts.source)\n const warnings: string[] = []\n\n const stage = mkdtempSync(join(tmpdir(), 'zidane-ext-install-'))\n try {\n const fetchedInto = join(stage, 'fetched')\n mkdirSync(fetchedInto, { recursive: true })\n const { provenance, commit } = await fetchExtensionSource(source, fetchedInto, io, onProgress)\n\n // A `:subdir` source re-roots the candidate search. Physical (not\n // just string-level) containment lives in `resolveSubdirRoot` — a\n // malicious repo shipping a symlink (`evil -> /`) must not walk the\n // candidate search (and the validation IMPORT) onto the local\n // filesystem. Structural escapes are already rejected at parse time;\n // this is the belt-and-braces layer.\n let candidateRoot = fetchedInto\n let fallbackName = source.kind === 'github' ? source.repo : source.pkg\n if (source.kind === 'github' && source.subdir) {\n const rooted = resolveSubdirRoot(fetchedInto, source.subdir)\n if (!rooted.ok) {\n if (rooted.reason === 'missing')\n throw new ExtensionInstallError('no-extension', `\"${source.subdir}\" is not a directory in ${source.owner}/${source.repo}${source.ref ? `@${source.ref}` : ''}.`)\n throw new ExtensionInstallError(\n 'invalid-source',\n rooted.reason === 'escape-symlink'\n ? `Subdirectory \"${source.subdir}\" escapes the repository root through a symlink.`\n : `Subdirectory \"${source.subdir}\" escapes the repository root.`,\n )\n }\n candidateRoot = rooted.dir\n fallbackName = basename(resolve(fetchedInto, source.subdir))\n }\n const candidates = listExtensionCandidates(candidateRoot, fallbackName)\n if (candidates.length === 0) {\n throw new ExtensionInstallError('no-extension', `No extension found in ${opts.source}. Expected a root index.{ts,tsx,mjs,js} or extensions/<name>/index.* directories.`)\n }\n let candidate: ExtensionInstallCandidate\n if (opts.expectName !== undefined) {\n const match = candidates.find(c => c.name === opts.expectName) ?? (candidates.length === 1 ? candidates[0] : undefined)\n if (!match)\n throw nameMismatch(opts.expectName, opts.source, candidates.map(c => c.name))\n candidate = match\n }\n else if (opts.extension) {\n const match = candidates.find(c => c.name === opts.extension)\n if (!match) {\n throw new ExtensionInstallError(\n 'no-extension',\n `No extension named \"${opts.extension}\" in ${opts.source}. Available: ${candidates.map(c => c.name).join(', ')}`,\n candidates.map(c => c.name),\n )\n }\n candidate = match\n }\n else if (candidates.length > 1 && candidates.some(c => c.name === opts.fallbackExtension)) {\n candidate = candidates.find(c => c.name === opts.fallbackExtension) as ExtensionInstallCandidate\n }\n else if (candidates.length > 1) {\n throw new ExtensionInstallError(\n 'multiple-candidates',\n `${opts.source} contains ${candidates.length} extensions. Pass one of: ${candidates.map(c => c.name).join(', ')}`,\n candidates.map(c => c.name),\n )\n }\n else {\n candidate = candidates[0] as ExtensionInstallCandidate\n }\n\n // Dependencies BEFORE validation — the import may need them.\n const pm = await installDependencies(candidate.dir, io, onProgress)\n if (pm)\n warnings.push(...pm.warnings)\n\n onProgress?.('validating extension module…')\n const definition = await validateCandidate(candidate, opts.importTimeoutMs ?? 10_000)\n if (opts.expectName !== undefined && definition.name !== opts.expectName)\n throw nameMismatch(opts.expectName, opts.source, [definition.name])\n if (definition.warning)\n warnings.push(definition.warning)\n\n const targetRoot = opts.installRoot ?? resolveInstallRoot(opts)\n const targetDir = join(targetRoot, definition.name)\n // Overwrites are fully live: discovery evicts the extension's module\n // graph before each import, so the next reload runs the new code.\n if (existsSync(targetDir) && !opts.overwrite)\n throw new ExtensionInstallError('exists', `${targetDir} already exists. Pass overwrite to replace it.`)\n\n onProgress?.(`installing to ${targetDir}…`)\n mkdirSync(targetRoot, { recursive: true })\n // Transactional target phase — the \"never half-install\" invariant. An\n // overwritten previous version is parked under a dot-name (invisible\n // to the scanner) and restored if anything past this point throws\n // (e.g. the in-place deps install failing on a full disk); on success\n // it is deleted. A fresh install that fails is wiped back to absence.\n const backupDir = existsSync(targetDir)\n ? join(targetRoot, `.${definition.name}.prev-${process.pid}-${Date.now()}`)\n : null\n if (backupDir)\n renameSync(targetDir, backupDir)\n try {\n cpSync(candidate.dir, targetDir, {\n recursive: true,\n // Materialize symlinked files: the stage dir they'd point into is\n // deleted after install, so copied links would dangle. (The\n // extension's code already ran at validation with the user's\n // consent — dereferencing discloses nothing new.)\n dereference: true,\n filter: src => !/(?:^|[\\\\/])(?:\\.git|node_modules)(?:$|[\\\\/])/.test(src),\n })\n // Re-install deps in place (node_modules excluded from the copy —\n // symlink layouts don't survive a cp).\n await installDependencies(targetDir, io, onProgress)\n\n const provenanceRecord: ExtensionInstallProvenance = {\n source: provenance,\n spec: opts.source,\n scope: opts.scope,\n // Picked from several (named or by fallback): recorded, so its update needs no fallback.\n ...(opts.extension !== undefined && opts.expectName === undefined ? { extension: opts.extension } : candidates.length > 1 ? { extension: candidate.name } : {}),\n ...(commit !== undefined ? { commit } : {}),\n installedAt: new Date().toISOString(),\n }\n writeFileSync(join(targetDir, PROVENANCE_FILE), `${JSON.stringify(provenanceRecord, null, 2)}\\n`)\n }\n catch (err) {\n rmSync(targetDir, { recursive: true, force: true })\n if (backupDir)\n renameSync(backupDir, targetDir)\n throw err\n }\n if (backupDir)\n rmSync(backupDir, { recursive: true, force: true })\n\n return { name: definition.name, dir: targetDir, scope: opts.scope, provenance, ...(commit !== undefined ? { commit } : {}), warnings }\n }\n finally {\n rmSync(stage, { recursive: true, force: true })\n }\n}\n\n/**\n * Read `.install.json` provenance from an installed extension dir, or null.\n *\n * @param dir - Installed extension directory.\n */\nexport function readExtensionInstallProvenance(dir: string): ExtensionInstallProvenance | null {\n const raw = readJson(join(dir, PROVENANCE_FILE)) as Partial<ExtensionInstallProvenance> | null\n if (!raw || typeof raw.spec !== 'string' || typeof raw.source !== 'string')\n return null\n return {\n source: raw.source,\n spec: raw.spec,\n scope: raw.scope === 'project' ? 'project' : 'user',\n ...(typeof raw.extension === 'string' ? { extension: raw.extension } : {}),\n ...(typeof raw.commit === 'string' ? { commit: raw.commit } : {}),\n installedAt: typeof raw.installedAt === 'string' ? raw.installedAt : '',\n }\n}\n\n/**\n * A short name of an install spec: `owner/repo` with `@ref` when one is\n * pinned (the folder in the repository left out), an npm package with\n * `@version` when one is pinned. A spec that does not parse is returned as is.\n *\n * @param spec - An install spec (`Tahul/zidane#v9.0.4:extensions/goal`, `@scope/pkg`).\n * @example\n * ```ts\n * extensionSourceLabel('Tahul/zidane#v9.0.4:extensions/goal') // 'Tahul/zidane@v9.0.4'\n * extensionSourceLabel('@scope/pkg') // '@scope/pkg'\n * ```\n */\nexport function extensionSourceLabel(spec: string): string {\n try {\n const source = parseInstallSource(spec)\n return source.kind === 'github'\n ? `${source.owner}/${source.repo}${source.ref ? `@${source.ref}` : ''}`\n : `${source.pkg}${source.version ? `@${source.version}` : ''}`\n }\n catch {\n return spec.trim()\n }\n}\n\n/**\n * Where an installed extension came from (its `.install.json`), or `null`\n * for one not installed from a source (hand-written, linked, built in).\n *\n * @param dir - Installed extension directory.\n */\nexport function readExtensionInstallOrigin(dir: string): ExtensionInstallOrigin | null {\n const provenance = readExtensionInstallProvenance(dir)\n if (!provenance)\n return null\n return {\n spec: provenance.spec,\n label: extensionSourceLabel(provenance.spec),\n source: provenance.source,\n ...(provenance.commit !== undefined ? { commit: provenance.commit } : {}),\n ...(provenance.installedAt ? { installedAt: provenance.installedAt } : {}),\n }\n}\n\nfunction nameMismatch(expected: string, source: string, found: readonly string[]): ExtensionInstallError {\n const names = found.length > 0 ? `Found: ${found.join(', ')}.` : 'It holds no extension.'\n return new ExtensionInstallError('name-mismatch', `${source} has no extension named \"${expected}\". ${names}`, found)\n}\n\n/** Identifies an installed extension and where to look for extension folders. Used by {@link updateInstalledExtension} and {@link removeInstalledExtension}. */\nexport interface InstalledExtensionTargetOptions {\n /** The installed extension's directory (e.g. `LoadedExtension.dir`). */\n dir: string\n /** Working directory used to find the project root. @default process.cwd() */\n cwd?: string\n /** User home directory. @default os.homedir() */\n home?: string\n /** Storage prefix. @default '.zidane' */\n prefix?: string\n /** Extra trusted roots (`ZIDANE_EXTENSION_DIRS` / host scan paths). */\n extensionScanPaths?: readonly string[]\n}\n\n/**\n * Containment guard shared by update/remove: `dir` must be a DIRECT child\n * of a recognized extensions root (the four `.{agents,prefix}/extensions`\n * search paths, plus any host scan roots). Refuses anything else — these\n * functions delete directories and must never be pointable at arbitrary\n * paths (an inline/builtin extension has no dir; a hand-typed path is not\n * an install).\n */\nfunction assertInstalledExtensionDir(opts: InstalledExtensionTargetOptions): { dir: string, root: string, scope: ExtensionInstallScope } {\n const dir = resolve(opts.dir)\n const roots: Array<{ path: string, scope: ExtensionInstallScope }> = [\n ...projectUserPaths({\n subPath: 'extensions',\n ...(opts.cwd !== undefined ? { cwd: opts.cwd } : {}),\n ...(opts.home !== undefined ? { home: opts.home } : {}),\n ...(opts.prefix !== undefined ? { prefix: opts.prefix } : {}),\n }).map(p => ({ path: p.path, scope: p.source })),\n // Host scan roots are user-opted-in — user scope by convention.\n ...(opts.extensionScanPaths ?? []).map(p => ({ path: resolve(p), scope: 'user' as const })),\n ]\n const root = roots.find(r => dirname(dir) === r.path)\n if (!root)\n throw new ExtensionInstallError('not-installed', `${dir} is not inside an extensions folder, so it was left alone.`)\n return { dir, root: root.path, scope: root.scope }\n}\n\n/**\n * Delete an installed extension's directory. Works on any on-disk\n * extension (hand-authored ones too — no provenance required); the\n * containment guard is the safety boundary. The caller owns follow-up\n * (allowlist cleanup, registry reload).\n *\n * @param opts - The installed extension to remove.\n */\nexport function removeInstalledExtension(opts: InstalledExtensionTargetOptions): { dir: string } {\n const { dir } = assertInstalledExtensionDir(opts)\n if (!existsSync(dir))\n throw new ExtensionInstallError('not-installed', `${dir} does not exist.`)\n rmSync(dir, { recursive: true, force: true })\n return { dir }\n}\n\n/**\n * Cheap \"is there anything new?\" probe, no fetch of content:\n *\n * - GitHub (with a recorded commit): `git ls-remote` resolves the ref's\n * current SHA in one round-trip — equal SHA means up to date.\n * - npm: one registry metadata GET re-resolves the version/dist-tag —\n * an unchanged resolved provenance string means up to date.\n *\n * `null` = \"can't tell cheaply\" (no recorded commit, git missing,\n * ls-remote/parse failure) — the caller falls through to a full update,\n * which errors honestly if the network is actually down.\n */\nasync function checkRemoteUnchanged(\n source: ExtensionInstallSource,\n previous: ExtensionInstallProvenance,\n io: ExtensionInstallIo,\n): Promise<boolean | null> {\n if (source.kind === 'npm') {\n try {\n const { version } = await resolveNpmVersion(source, io.fetch ?? fetch)\n return `npm:${source.pkg}@${version}` === previous.source\n }\n catch {\n return null\n }\n }\n if (!previous.commit)\n return null\n const which = io.which ?? defaultWhich\n const exec = io.exec ?? defaultExec\n if (!which('git'))\n return null\n const url = `https://github.com/${source.owner}/${source.repo}.git`\n const refspecs = source.ref ? [`refs/heads/${source.ref}`, `refs/tags/${source.ref}`] : ['HEAD']\n // GIT_TERMINAL_PROMPT=0 — never let git prompt for credentials from\n // inside the TUI; an unreachable remote degrades to \"can't tell\" (null).\n const res = await exec('git', ['ls-remote', url, ...refspecs], { env: { GIT_TERMINAL_PROMPT: '0' } })\n if (!res.ok)\n return null\n const sha = res.stdout.trim().split('\\n')[0]?.split('\\t')[0]?.trim()\n if (!sha || !/^[0-9a-f]{40}$/.test(sha))\n return null\n return sha === previous.commit\n}\n\n/**\n * Re-run the recorded install for an extension: re-resolves the original\n * spec (so `owner/repo` follows the branch and `pkg` follows `latest`,\n * while pinned refs/versions stay pinned) and replaces the install\n * IN PLACE (same root the extension currently lives in, even a\n * `.agents/extensions` one). Requires `.install.json` provenance —\n * hand-authored extensions have nothing to update from.\n *\n * When the remote is provably unchanged (recorded commit matches\n * `git ls-remote`, or the npm version re-resolves identically), the\n * reinstall is skipped entirely and the result carries `upToDate: true`.\n *\n * @param opts - The installed extension to update, plus progress and IO overrides.\n */\nexport async function updateInstalledExtension(\n opts: InstalledExtensionTargetOptions & {\n onProgress?: (message: string) => void\n io?: ExtensionInstallIo\n },\n): Promise<ExtensionInstallResult & { previous: ExtensionInstallProvenance, upToDate: boolean }> {\n const { dir, root, scope } = assertInstalledExtensionDir(opts)\n const provenance = readExtensionInstallProvenance(dir)\n if (!provenance)\n throw new ExtensionInstallError('no-provenance', `${dir} has no .install.json. It was not installed from a source, so there is nothing to update from.`)\n\n const source = parseExtensionInstallSource(provenance.spec)\n opts.onProgress?.(`checking ${provenance.source} for changes…`)\n if (await checkRemoteUnchanged(source, provenance, opts.io ?? {}) === true) {\n return {\n name: basename(dir),\n dir,\n scope,\n provenance: provenance.source,\n ...(provenance.commit !== undefined ? { commit: provenance.commit } : {}),\n warnings: [],\n previous: provenance,\n upToDate: true,\n }\n }\n\n const result = await installExtensionFromSpec({\n source: provenance.spec,\n // Recorded without one (older hosts): the folder it was installed as, when the source holds several.\n ...(provenance.extension !== undefined ? { extension: provenance.extension } : { fallbackExtension: basename(dir) }),\n // Scope from where the extension ACTUALLY lives (the containment\n // root), not the recorded field — a stale/corrupt provenance scope\n // would otherwise self-perpetuate through every future update.\n scope,\n overwrite: true,\n installRoot: root,\n ...(opts.cwd !== undefined ? { cwd: opts.cwd } : {}),\n ...(opts.home !== undefined ? { home: opts.home } : {}),\n ...(opts.prefix !== undefined ? { prefix: opts.prefix } : {}),\n ...(opts.onProgress !== undefined ? { onProgress: opts.onProgress } : {}),\n ...(opts.io !== undefined ? { io: opts.io } : {}),\n })\n // The upstream may have renamed its definition — the fresh install then\n // landed in a sibling folder. Remove the superseded dir so an update\n // never leaves two generations installed side by side.\n if (result.dir !== dir)\n rmSync(dir, { recursive: true, force: true })\n return { ...result, previous: provenance, upToDate: false }\n}\n\n/**\n * Installs an extension again from another source, in place: the source\n * must hold an extension with the same name (else `name-mismatch`, with the\n * names found), the folder is replaced only once the new copy fetched,\n * installed its dependencies and validated (the install's transaction), and\n * `.install.json` records the new source, which later updates follow.\n * Works on any installed folder, with or without a recorded source.\n *\n * @param opts - The installed extension, the new source, progress and IO overrides.\n * @returns The install's result, the source it had (`null` when none was recorded) and the one it has now.\n */\nexport async function changeExtensionOrigin(\n opts: InstalledExtensionTargetOptions & {\n /** The new source spec (GitHub or npm, as {@link installExtensionFromSpec} takes it). */\n source: string\n onProgress?: (message: string) => void\n io?: ExtensionInstallIo\n },\n): Promise<ExtensionInstallResult & { previous: ExtensionInstallOrigin | null, origin: ExtensionInstallOrigin }> {\n const { dir, root, scope } = assertInstalledExtensionDir(opts)\n if (!existsSync(dir))\n throw new ExtensionInstallError('not-installed', `${dir} does not exist.`)\n const previous = readExtensionInstallOrigin(dir)\n const result = await installExtensionFromSpec({\n source: opts.source,\n expectName: basename(dir),\n scope,\n overwrite: true,\n installRoot: root,\n ...(opts.cwd !== undefined ? { cwd: opts.cwd } : {}),\n ...(opts.home !== undefined ? { home: opts.home } : {}),\n ...(opts.prefix !== undefined ? { prefix: opts.prefix } : {}),\n ...(opts.onProgress !== undefined ? { onProgress: opts.onProgress } : {}),\n ...(opts.io !== undefined ? { io: opts.io } : {}),\n })\n const origin = readExtensionInstallOrigin(result.dir)\n if (!origin)\n throw new Error(`unreachable: ${result.dir} was installed without .install.json`)\n return { ...result, previous, origin }\n}\n\n/** The scope's canonical `.{prefix}/extensions` write root. */\nfunction resolveInstallRoot(opts: { scope: ExtensionInstallScope, cwd?: string, home?: string, prefix?: string }): string {\n const prefix = (opts.prefix ?? '.zidane').replace(/^\\./, '')\n const paths = projectUserPaths({\n subPath: 'extensions',\n ...(opts.cwd !== undefined ? { cwd: opts.cwd } : {}),\n ...(opts.home !== undefined ? { home: opts.home } : {}),\n ...(opts.prefix !== undefined ? { prefix: opts.prefix } : {}),\n })\n const root = paths.find(p => p.source === opts.scope && p.path.includes(`.${prefix}`))\n if (!root)\n throw new Error(`unreachable: projectUserPaths yields a .${prefix} root per scope`)\n return root.path\n}\n\nasync function validateCandidate(\n candidate: ExtensionInstallCandidate,\n timeoutMs: number,\n): Promise<{ name: string, warning?: string }> {\n const entry = findEntryFile(candidate.dir)\n if (!entry)\n throw new ExtensionInstallError('no-extension', `${candidate.dir} has no index.{ts,tsx,mjs,js} entry.`)\n const version = checkZidaneVersion(candidate.dir)\n if (version?.level === 'error')\n throw new ExtensionInstallError('validate-failed', version.message)\n let mod: unknown\n try {\n mod = await withTimeout(\n importExtensionEntry(entry, candidate.dir),\n timeoutMs,\n `Timed out importing ${entry} after ${timeoutMs}ms.`,\n )\n }\n catch (err) {\n throw new ExtensionInstallError('validate-failed', `Cannot import the extension: ${errorMessage(err)}`)\n }\n finally {\n // The staged dir moves or is deleted next: nothing may stay cached under it.\n releaseExtensionModules(candidate.dir)\n }\n const m = (mod ?? {}) as Record<string, unknown>\n const exported = [m.default, m.extension].filter(value => value !== undefined)\n const candidateDef = definitionExport(exported)\n if (candidateDef === undefined) {\n throw new ExtensionInstallError('validate-failed', `Module at ${entry} does not export an extension definition (expected \\`default\\` or named \\`extension\\` with \\`apiVersion: 1\\`).`)\n }\n const validation = validateDefinition(candidateDef)\n if (!validation.ok)\n throw new ExtensionInstallError('validate-failed', validation.errors.map(issue => (issue.path ? `${issue.path}: ${issue.message}` : issue.message)).join('; '))\n const definition = { name: validation.definition.id }\n if (!/^[\\w.-]+$/.test(definition.name) || definition.name.startsWith('.'))\n throw new ExtensionInstallError('validate-failed', `Extension id \"${definition.name}\" is not folder-safe ([A-Za-z0-9_.-], no leading dot).`)\n const manifest = readExtensionManifest(candidate.dir).manifest\n if (manifest?.apiVersion !== undefined && manifest.apiVersion !== EXTENSION_API_VERSION)\n throw new ExtensionInstallError('validate-failed', `Unsupported extension API version \"${manifest.apiVersion}\" in manifest. This runtime supports apiVersion 1.`)\n if (manifest?.name && manifest.name !== definition.name)\n throw new ExtensionInstallError('validate-failed', `Manifest name \"${manifest.name}\" does not match the module's exported id \"${definition.name}\".`)\n return { name: definition.name, ...(version ? { warning: version.message } : {}) }\n}\n\n// ---------------------------------------------------------------------------\n// Dependency install\n// ---------------------------------------------------------------------------\n\nconst PM_COMMANDS: ReadonlyArray<{ cmd: string, args: readonly string[] }> = [\n // bun skips lifecycle scripts by default (trustedDependencies opt-in).\n { cmd: 'bun', args: ['install'] },\n { cmd: 'npm', args: ['install', '--ignore-scripts', '--no-audit', '--no-fund'] },\n { cmd: 'pnpm', args: ['install', '--ignore-scripts'] },\n { cmd: 'yarn', args: ['install', '--ignore-scripts'] },\n]\n\n/** Install deps when `dir/package.json` declares any. Returns null when skipped. */\nasync function installDependencies(\n dir: string,\n io: ExtensionInstallIo,\n onProgress?: (message: string) => void,\n): Promise<{ warnings: string[] } | null> {\n const pkg = readJson(join(dir, 'package.json')) as { dependencies?: Record<string, string> } | null\n if (!pkg?.dependencies || Object.keys(pkg.dependencies).length === 0)\n return null\n const exec = io.exec ?? defaultExec\n const which = io.which ?? defaultWhich\n const pm = PM_COMMANDS.find(p => which(p.cmd))\n if (!pm) {\n throw new ExtensionInstallError('no-package-manager', 'The extension has dependencies, but no package manager (bun, npm, pnpm or yarn) is on PATH.')\n }\n onProgress?.(`installing dependencies with ${pm.cmd}…`)\n const res = await exec(pm.cmd, pm.args, { cwd: dir })\n if (!res.ok)\n throw new ExtensionInstallError('deps-failed', `${pm.cmd} install failed: ${lastLine(res.stderr) || lastLine(res.stdout)}`)\n return { warnings: [] }\n}\n\n// ---------------------------------------------------------------------------\n// Shared helpers\n// ---------------------------------------------------------------------------\n\nfunction readJson(path: string): unknown {\n try {\n return JSON.parse(readFileSync(path, 'utf8')) as unknown\n }\n catch {\n return null\n }\n}\n","/**\n * `extensions.lock.json`: what the declarative config installed, next to the\n * config file it belongs to. One lock per config file (user, project), so a\n * project lock can be committed and replayed on another machine.\n *\n * Entries are keyed by {@link DeclaredExtension.key} (source identity\n * without ref or version). Directories are not recorded: they follow from\n * the scope and the id, and differ between machines.\n */\n\nimport type { ExtensionsConfigDiagnostic, ExtensionsConfigScope } from './config'\nimport { existsSync, readFileSync } from 'node:fs'\nimport { dirname, join } from 'node:path'\nimport { writeJsonFileAtomic } from '../../atomic-write'\n\n/** File name of the lock, beside `config.json`. */\nexport const EXTENSIONS_LOCK_FILE = 'extensions.lock.json'\n\n/** Format version written in every lock. A lock with another version is read as empty. */\nexport const EXTENSIONS_LOCK_VERSION = 1\n\n/** What the lock records for one declared extension. */\nexport interface ExtensionsLockEntry {\n /** The config `source` it was installed from, as written. A different one means the pin changed. */\n readonly source: string\n /** The extension picked from a collection, when one was. */\n readonly extension?: string\n /** The installed extension id (its folder name). */\n readonly id: string\n /** Resolved provenance: `npm:pkg@1.2.3`, `github:owner/repo@ref`, `local:./path`. */\n readonly resolved: string\n /** The extension's own version (package.json), when it has one. */\n readonly version?: string\n /** Exact commit SHA, for GitHub installs made with git. */\n readonly commit?: string\n /** `sha256-<base64>` of the installed files, when the host computed it. */\n readonly integrity?: string\n /** ISO 8601 time of the install. */\n readonly installedAt: string\n}\n\n/** The whole lock file. */\nexport interface ExtensionsLock {\n readonly lockfileVersion: typeof EXTENSIONS_LOCK_VERSION\n /** Entries by {@link DeclaredExtension.key}. */\n readonly extensions: Readonly<Record<string, ExtensionsLockEntry>>\n}\n\n/** A lock with no entries. */\nexport function emptyExtensionsLock(): ExtensionsLock {\n return { lockfileVersion: EXTENSIONS_LOCK_VERSION, extensions: {} }\n}\n\n/**\n * The lock path for a config file: `extensions.lock.json` in the same\n * directory.\n *\n * @param configPath - Path of the `config.json` the lock belongs to.\n */\nexport function extensionsLockPath(configPath: string): string {\n return join(dirname(configPath), EXTENSIONS_LOCK_FILE)\n}\n\nfunction optionalString(raw: Record<string, unknown>, key: string): Record<string, string> {\n const value = raw[key]\n return typeof value === 'string' && value !== '' ? { [key]: value } : {}\n}\n\n/**\n * Reads parsed lock JSON. Never throws: a lock with another version or a\n * broken shape reads as empty, a broken entry is dropped, each with a\n * warning (the next reconcile rewrites the lock).\n *\n * @param raw - The parsed JSON, or `undefined` when there is no file.\n * @param scope - The scope the lock belongs to, for diagnostics.\n */\nexport function parseExtensionsLock(raw: unknown, scope: ExtensionsConfigScope): { lock: ExtensionsLock, diagnostics: ExtensionsConfigDiagnostic[] } {\n const diagnostics: ExtensionsConfigDiagnostic[] = []\n if (raw === undefined)\n return { lock: emptyExtensionsLock(), diagnostics }\n const record = raw !== null && typeof raw === 'object' && !Array.isArray(raw) ? raw as Record<string, unknown> : null\n if (!record || record.lockfileVersion !== EXTENSIONS_LOCK_VERSION || record.extensions === null || typeof record.extensions !== 'object' || Array.isArray(record.extensions)) {\n diagnostics.push({ level: 'warning', scope, message: `${EXTENSIONS_LOCK_FILE} is not a version ${EXTENSIONS_LOCK_VERSION} lock. It is ignored and will be rewritten.` })\n return { lock: emptyExtensionsLock(), diagnostics }\n }\n const extensions: Record<string, ExtensionsLockEntry> = {}\n for (const [key, value] of Object.entries(record.extensions as Record<string, unknown>)) {\n const entry = value !== null && typeof value === 'object' && !Array.isArray(value) ? value as Record<string, unknown> : null\n if (!entry || typeof entry.source !== 'string' || typeof entry.id !== 'string' || typeof entry.resolved !== 'string') {\n diagnostics.push({ level: 'warning', scope, message: `Lock entry \"${key}\" is incomplete. It is ignored.` })\n continue\n }\n extensions[key] = {\n source: entry.source,\n id: entry.id,\n resolved: entry.resolved,\n installedAt: typeof entry.installedAt === 'string' ? entry.installedAt : '',\n ...optionalString(entry, 'extension'),\n ...optionalString(entry, 'version'),\n ...optionalString(entry, 'commit'),\n ...optionalString(entry, 'integrity'),\n }\n }\n return { lock: { lockfileVersion: EXTENSIONS_LOCK_VERSION, extensions }, diagnostics }\n}\n\n/**\n * Reads the lock at `path`. A missing file is an empty lock; unreadable\n * JSON is an empty lock with a warning.\n *\n * @param path - The lock file.\n * @param scope - The scope the lock belongs to, for diagnostics.\n */\nexport function readExtensionsLock(path: string, scope: ExtensionsConfigScope): { lock: ExtensionsLock, diagnostics: ExtensionsConfigDiagnostic[] } {\n if (!existsSync(path))\n return parseExtensionsLock(undefined, scope)\n let raw: unknown\n try {\n raw = JSON.parse(readFileSync(path, 'utf8'))\n }\n catch {\n raw = null\n }\n return parseExtensionsLock(raw, scope)\n}\n\n/**\n * Writes the lock atomically (`writeJsonFileAtomic`), entries and fields\n * in a stable order so a committed lock diffs cleanly.\n *\n * @param path - The lock file. Its directory is created when missing.\n * @param lock - The lock to write.\n */\nexport function writeExtensionsLock(path: string, lock: ExtensionsLock): void {\n const extensions: Record<string, ExtensionsLockEntry> = {}\n for (const key of Object.keys(lock.extensions).sort()) {\n const e = lock.extensions[key] as ExtensionsLockEntry\n extensions[key] = {\n source: e.source,\n ...(e.extension !== undefined ? { extension: e.extension } : {}),\n id: e.id,\n resolved: e.resolved,\n ...(e.version !== undefined ? { version: e.version } : {}),\n ...(e.commit !== undefined ? { commit: e.commit } : {}),\n ...(e.integrity !== undefined ? { integrity: e.integrity } : {}),\n installedAt: e.installedAt,\n }\n }\n writeJsonFileAtomic(path, { lockfileVersion: EXTENSIONS_LOCK_VERSION, extensions }, { ensureDir: true })\n}\n","/**\n * The reconcile planner: config entries + lock + what is on disk → the\n * actions that bring the disk in line with the config. Pure; {@link\n * reconcile} runs the plan through a port.\n *\n * Rules:\n *\n * - The lock pins. An entry already in the lock with the same `source`\n * is kept as it is; nothing is re-resolved unless `update` is set.\n * - A changed `source` (new ref, version or pick) reinstalls in place.\n * - A locked entry missing on disk (a fresh clone of a project) installs\n * the locked version: npm exactly, GitHub from the source (a commit\n * mismatch is reported by reconcile).\n * - An extension already installed from the same source, not in the\n * lock, is adopted without a fetch.\n * - Removing an entry removes only what the lock owns, and only when the\n * folder on disk still comes from that source; anything else is just\n * dropped from the lock.\n * - `enabled: false` stays installed (Settings still shows it).\n */\n\nimport type { DeclaredExtension, ExtensionsConfigDiagnostic, ExtensionsConfigScope } from './config'\nimport type { ExtensionsLock, ExtensionsLockEntry } from './lock'\nimport type { InstalledExtensionInfo } from './port'\nimport { installSpecIdentity } from './config'\n\n/** Why an install runs. */\nexport type InstallReason = 'new' | 'locked' | 'changed'\n\n/** One step of a plan. */\nexport type ReconcileAction\n = | {\n readonly kind: 'install'\n readonly entry: DeclaredExtension\n /** The spec to install: the entry's, or the locked npm version. */\n readonly spec: string\n readonly reason: InstallReason\n /** The previous install this one replaces, for `changed`. */\n readonly replaces?: InstalledExtensionInfo\n /** The lock entry being replayed or replaced. */\n readonly lock?: ExtensionsLockEntry\n }\n | { readonly kind: 'adopt', readonly entry: DeclaredExtension, readonly installed: InstalledExtensionInfo }\n | { readonly kind: 'update', readonly entry: DeclaredExtension, readonly installed: InstalledExtensionInfo, readonly lock: ExtensionsLockEntry }\n | { readonly kind: 'keep', readonly entry: DeclaredExtension, readonly installed: InstalledExtensionInfo, readonly lock: ExtensionsLockEntry }\n | { readonly kind: 'link', readonly entry: DeclaredExtension, readonly path: string }\n | { readonly kind: 'remove', readonly key: string, readonly lock: ExtensionsLockEntry, readonly installed: InstalledExtensionInfo }\n | { readonly kind: 'forget', readonly key: string, readonly lock: ExtensionsLockEntry }\n\n/** The actions for one scope, in run order. */\nexport interface ReconcilePlan {\n readonly scope: ExtensionsConfigScope\n readonly actions: readonly ReconcileAction[]\n readonly diagnostics: readonly ExtensionsConfigDiagnostic[]\n}\n\n/** Input of {@link planReconcile}. */\nexport interface PlanReconcileInput {\n readonly scope: ExtensionsConfigScope\n /** The scope's valid entries (`parseExtensionsConfig`). */\n readonly entries: readonly DeclaredExtension[]\n readonly lock: ExtensionsLock\n /** The scope's install root as it is now (`port.listInstalled`). */\n readonly installed: readonly InstalledExtensionInfo[]\n /** Re-resolve every remote entry (follow branches and dist-tags). Default `false`. */\n readonly update?: boolean\n}\n\n/**\n * The npm spec pinned to the locked version, or the entry's own spec.\n *\n * @param entry - The config entry.\n * @param lock - Its lock entry.\n */\nexport function pinnedSpec(entry: DeclaredExtension, lock: ExtensionsLockEntry): string {\n if (entry.location.kind !== 'remote' || entry.location.source.kind !== 'npm')\n return entry.installSpec\n const prefix = `npm:${entry.location.source.pkg}@`\n return lock.resolved.startsWith(prefix) ? `${entry.location.source.pkg}@${lock.resolved.slice(prefix.length)}` : entry.installSpec\n}\n\nfunction sameOrigin(installed: InstalledExtensionInfo, key: string): boolean {\n return installed.spec !== undefined && installSpecIdentity(installed.spec, installed.extension) === key\n}\n\n/**\n * Plans the reconcile of one scope. Removals come first, so a folder freed\n * by a removed entry can be reused by a new one.\n *\n * @param input - Entries, lock and the install root's contents.\n */\nexport function planReconcile(input: PlanReconcileInput): ReconcilePlan {\n const byId = new Map(input.installed.map(i => [i.id, i]))\n const declared = new Set(input.entries.map(e => e.key))\n const removals: ReconcileAction[] = []\n const actions: ReconcileAction[] = []\n const diagnostics: ExtensionsConfigDiagnostic[] = []\n\n for (const [key, lock] of Object.entries(input.lock.extensions)) {\n if (declared.has(key))\n continue\n const installed = lock.resolved.startsWith('local:') ? undefined : byId.get(lock.id)\n if (installed && sameOrigin(installed, key))\n removals.push({ kind: 'remove', key, lock, installed })\n else\n removals.push({ kind: 'forget', key, lock })\n }\n\n for (const entry of input.entries) {\n if (entry.location.kind === 'local') {\n actions.push({ kind: 'link', entry, path: entry.location.path })\n continue\n }\n const lock = input.lock.extensions[entry.key]\n const lockedDir = lock ? byId.get(lock.id) : undefined\n if (lock && (lock.source !== entry.source || lock.extension !== entry.extension)) {\n actions.push({ kind: 'install', entry, spec: entry.installSpec, reason: 'changed', lock, ...(lockedDir ? { replaces: lockedDir } : {}) })\n continue\n }\n if (lock && lockedDir) {\n actions.push(input.update ? { kind: 'update', entry, installed: lockedDir, lock } : { kind: 'keep', entry, installed: lockedDir, lock })\n continue\n }\n if (lock) {\n actions.push({ kind: 'install', entry, spec: pinnedSpec(entry, lock), reason: 'locked', lock })\n continue\n }\n const existing = input.installed.find(i => sameOrigin(i, entry.key))\n if (existing) {\n actions.push({ kind: 'adopt', entry, installed: existing })\n if (input.update)\n diagnostics.push({ level: 'warning', scope: input.scope, index: entry.index, message: `\"${entry.source}\" was already installed; it is adopted as is. Update again to re-resolve it.` })\n continue\n }\n actions.push({ kind: 'install', entry, spec: entry.installSpec, reason: 'new' })\n }\n return { scope: input.scope, actions: [...removals, ...actions], diagnostics }\n}\n","/**\n * Runs a {@link ReconcilePlan} through an {@link ExtensionsInstallPort} and\n * returns the next lock. One action at a time, in plan order. A failed\n * action keeps its previous lock entry (or none), so the lock always\n * describes what is really on disk; the caller writes it.\n */\n\nimport type { DeclaredExtension, ExtensionsConfigScope } from './config'\nimport type { ExtensionsLock, ExtensionsLockEntry } from './lock'\nimport type { ReconcileAction, ReconcilePlan } from './plan'\nimport type { ExtensionsInstallPort } from './port'\nimport { errorMessage } from '../../errors'\nimport { EXTENSIONS_LOCK_VERSION } from './lock'\nimport { planReconcile } from './plan'\n\n/** What happened to one action. */\nexport type ReconcileOutcome\n = | {\n readonly action: ReconcileAction\n readonly ok: true\n /** The extension id it concerns. */\n readonly id: string\n /** Non-fatal notices: host-version warnings, a moved GitHub pin. */\n readonly warnings: readonly string[]\n /** For `update`: the remote had nothing new. */\n readonly upToDate?: boolean\n /** For `install` and `update`: the folder installed. */\n readonly dir?: string\n }\n | {\n readonly action: ReconcileAction\n readonly ok: false\n readonly error: string\n /** The installer's error code (`ExtensionInstallError.code`), when it had one. */\n readonly code?: string\n }\n\n/** Result of {@link reconcile}. */\nexport interface ReconcileResult {\n readonly scope: ExtensionsConfigScope\n /** The lock to write. */\n readonly lock: ExtensionsLock\n readonly outcomes: readonly ReconcileOutcome[]\n /** Whether `lock` differs from the lock the run started from. */\n readonly changed: boolean\n}\n\n/** Options of {@link reconcile}. */\nexport interface ReconcileOptions {\n /** The lock the plan was made from. */\n readonly lock: ExtensionsLock\n /** Clock for `installedAt`. Default `() => new Date()`. */\n readonly now?: () => Date\n /** Stops the run: the current install rolls back, the rest are skipped. */\n readonly signal?: AbortSignal\n /** Status lines while an action runs. */\n readonly onProgress?: (action: ReconcileAction, message: string) => void\n}\n\nfunction lockEntryFor(\n entry: DeclaredExtension,\n rec: { id: string, resolved: string, version?: string | undefined, commit?: string | undefined, integrity?: string | undefined },\n installedAt: string,\n): ExtensionsLockEntry {\n return {\n source: entry.source,\n ...(entry.extension !== undefined ? { extension: entry.extension } : {}),\n id: rec.id,\n resolved: rec.resolved,\n ...(rec.version !== undefined ? { version: rec.version } : {}),\n ...(rec.commit !== undefined ? { commit: rec.commit } : {}),\n ...(rec.integrity !== undefined ? { integrity: rec.integrity } : {}),\n installedAt,\n }\n}\n\nfunction errorCode(err: unknown): string | undefined {\n const code = (err as { code?: unknown } | null)?.code\n return typeof code === 'string' ? code : undefined\n}\n\nfunction sameEntry(a: ExtensionsLockEntry | undefined, b: ExtensionsLockEntry | undefined): boolean {\n return JSON.stringify(a) === JSON.stringify(b)\n}\n\n/**\n * Runs `plan` and returns the next lock with one outcome per action.\n * Never throws for a failed action; it reports it.\n *\n * @param plan - From {@link planReconcile}.\n * @param port - The host effects.\n * @param options - The starting lock, clock, signal and progress.\n */\nexport async function reconcile(plan: ReconcilePlan, port: ExtensionsInstallPort, options: ReconcileOptions): Promise<ReconcileResult> {\n const now = options.now ?? (() => new Date())\n const next: Record<string, ExtensionsLockEntry> = { ...options.lock.extensions }\n const outcomes: ReconcileOutcome[] = []\n\n for (const action of plan.actions) {\n if (options.signal?.aborted) {\n outcomes.push({ action, ok: false, error: 'The reconcile was stopped.' })\n continue\n }\n const onProgress = options.onProgress ? (message: string): void => options.onProgress?.(action, message) : undefined\n const signalOpt = options.signal ? { signal: options.signal } : {}\n const progressOpt = onProgress ? { onProgress } : {}\n try {\n switch (action.kind) {\n case 'forget': {\n delete next[action.key]\n outcomes.push({ action, ok: true, id: action.lock.id, warnings: [] })\n break\n }\n case 'remove': {\n await port.remove({ dir: action.installed.dir })\n delete next[action.key]\n outcomes.push({ action, ok: true, id: action.lock.id, warnings: [] })\n break\n }\n case 'keep': {\n outcomes.push({ action, ok: true, id: action.lock.id, warnings: [] })\n break\n }\n case 'link': {\n const described = await port.describe({ dir: action.path })\n if (!described) {\n outcomes.push({ action, ok: false, error: `${action.path} is not an extension folder.` })\n break\n }\n if (described.hostVersion?.level === 'error') {\n outcomes.push({ action, ok: false, error: described.hostVersion.message, code: 'validate-failed' })\n break\n }\n const previous = next[action.entry.key]\n const resolved = `local:${action.entry.installSpec}`\n const installedAt = previous && previous.resolved === resolved ? previous.installedAt : now().toISOString()\n next[action.entry.key] = lockEntryFor(action.entry, { id: described.id, resolved, version: described.version }, installedAt)\n outcomes.push({ action, ok: true, id: described.id, warnings: described.hostVersion ? [described.hostVersion.message] : [] })\n break\n }\n case 'adopt': {\n const described = await port.describe({ dir: action.installed.dir })\n const id = described?.id ?? action.installed.id\n next[action.entry.key] = lockEntryFor(action.entry, {\n id,\n resolved: described?.resolved ?? action.installed.spec ?? action.entry.installSpec,\n version: described?.version,\n commit: described?.commit ?? action.installed.commit,\n integrity: described?.integrity,\n }, now().toISOString())\n outcomes.push({ action, ok: true, id, warnings: described?.hostVersion ? [described.hostVersion.message] : [] })\n break\n }\n case 'update': {\n const { entry, installed } = action\n if (installed.spec === entry.installSpec && installed.extension === entry.extension) {\n const rec = await port.update({ dir: installed.dir, ...signalOpt, ...progressOpt })\n next[entry.key] = lockEntryFor(entry, rec, rec.upToDate ? action.lock.installedAt : now().toISOString())\n outcomes.push({ action, ok: true, id: rec.id, warnings: rec.warnings, upToDate: rec.upToDate, dir: rec.dir })\n }\n else {\n // Installed from the locked pin (npm exact version): re-resolve the config's own spec.\n const rec = await port.install({ source: entry.installSpec, ...(entry.extension !== undefined ? { extension: entry.extension } : {}), scope: plan.scope, overwrite: true, ...signalOpt, ...progressOpt })\n next[entry.key] = lockEntryFor(entry, rec, now().toISOString())\n if (rec.id !== installed.id)\n await port.remove({ dir: installed.dir })\n outcomes.push({ action, ok: true, id: rec.id, warnings: rec.warnings, dir: rec.dir })\n }\n break\n }\n case 'install': {\n const { entry } = action\n const rec = await port.install({\n source: action.spec,\n ...(entry.extension !== undefined ? { extension: entry.extension } : {}),\n scope: plan.scope,\n overwrite: action.replaces !== undefined,\n ...signalOpt,\n ...progressOpt,\n })\n const warnings = [...rec.warnings]\n next[entry.key] = lockEntryFor(entry, rec, now().toISOString())\n if (action.replaces && action.replaces.id !== rec.id) {\n try {\n await port.remove({ dir: action.replaces.dir })\n }\n catch (err) {\n warnings.push(`The previous install at ${action.replaces.dir} could not be removed: ${errorMessage(err)}`)\n }\n }\n if (action.reason === 'locked' && action.lock?.commit && rec.commit && rec.commit !== action.lock.commit)\n warnings.push(`The lock pins commit ${action.lock.commit.slice(0, 12)}, but ${entry.source} now resolves to ${rec.commit.slice(0, 12)}. The lock was updated.`)\n outcomes.push({ action, ok: true, id: rec.id, warnings, dir: rec.dir })\n break\n }\n }\n }\n catch (err) {\n const code = errorCode(err)\n outcomes.push({ action, ok: false, error: errorMessage(err), ...(code !== undefined ? { code } : {}) })\n }\n }\n\n const keys = new Set([...Object.keys(options.lock.extensions), ...Object.keys(next)])\n const changed = [...keys].some(k => !sameEntry(options.lock.extensions[k], next[k]))\n return { scope: plan.scope, lock: { lockfileVersion: EXTENSIONS_LOCK_VERSION, extensions: next }, outcomes, changed }\n}\n\n/** Input of {@link syncDeclaredExtensions}. */\nexport interface SyncDeclaredExtensionsInput extends Omit<ReconcileOptions, 'lock'> {\n readonly scope: ExtensionsConfigScope\n readonly entries: readonly DeclaredExtension[]\n readonly lock: ExtensionsLock\n readonly port: ExtensionsInstallPort\n /** Re-resolve every remote entry. */\n readonly update?: boolean\n}\n\n/**\n * Lists the install root, plans and reconciles one scope.\n *\n * @param input - Scope, entries, lock, port and run options.\n */\nexport async function syncDeclaredExtensions(input: SyncDeclaredExtensionsInput): Promise<ReconcileResult & { readonly plan: ReconcilePlan }> {\n const installed = await input.port.listInstalled(input.scope)\n const plan = planReconcile({ scope: input.scope, entries: input.entries, lock: input.lock, installed, ...(input.update !== undefined ? { update: input.update } : {}) })\n const result = await reconcile(plan, input.port, {\n lock: input.lock,\n ...(input.now !== undefined ? { now: input.now } : {}),\n ...(input.signal !== undefined ? { signal: input.signal } : {}),\n ...(input.onProgress !== undefined ? { onProgress: input.onProgress } : {}),\n })\n return { ...result, plan }\n}\n","/**\n * The Node side of declarative install: where the config files live,\n * reading them, the default {@link ExtensionsInstallPort} over\n * `src/extensions/install.ts`, and a one-call sync of both scopes that\n * writes the locks.\n *\n * Config files:\n *\n * - user: `<configDir>/config.json` (the file `loadUserConfig` reads)\n * - project: `<project-root>/.zidane/config.json` (project root = git\n * root, else cwd, as in `projectUserPaths`)\n *\n * Each has its `extensions.lock.json` beside it. Relative local sources\n * resolve against the project root (project) or the config dir (user).\n */\n\nimport type { InstallIo } from '../../install/source'\nimport type { ZidaneVersionCheckOptions } from '../host-version'\nimport type { DeclaredExtension, ExtensionsConfigDiagnostic, ExtensionsConfigScope } from './config'\nimport type { ExtensionsLock } from './lock'\nimport type { ReconcileAction, ReconcilePlan } from './plan'\nimport type { DescribedExtension, ExtensionsInstallPort, InstalledExtensionInfo, InstalledExtensionRecord } from './port'\nimport type { ReconcileResult } from './reconcile'\nimport { createHash } from 'node:crypto'\nimport { existsSync, lstatSync, readdirSync, readFileSync, statSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { basename, dirname, join, relative, resolve } from 'node:path'\nimport { findGitRoot } from '../../chat/project-root'\nimport { projectUserPaths } from '../../chat/project-user-paths'\nimport { abortableInstallIo } from '../../install/source'\nimport { findEntryFile } from '../discovery'\nimport { checkZidaneVersion } from '../host-version'\nimport { installExtensionFromSpec, readExtensionInstallProvenance, removeInstalledExtension, updateInstalledExtension } from '../install'\nimport { parseExtensionsConfig } from './config'\nimport { extensionsLockPath, readExtensionsLock, writeExtensionsLock } from './lock'\nimport { syncDeclaredExtensions } from './reconcile'\n\n/** Where the two config files and their locks are. */\nexport interface ExtensionsConfigPaths {\n readonly user: { readonly config: string, readonly lock: string, readonly baseDir: string }\n readonly project: { readonly config: string, readonly lock: string, readonly baseDir: string }\n}\n\n/** Where to look: the user config dir, the working directory, the storage prefix. */\nexport interface ExtensionsConfigLocation {\n /** The user config dir (`ResolvedConfig.configDir`). */\n readonly configDir: string\n /** Default `process.cwd()`. */\n readonly cwd?: string\n /** Default `os.homedir()`. */\n readonly home?: string\n /** Default `.zidane`. */\n readonly prefix?: string\n}\n\n/**\n * The config and lock paths of both scopes.\n *\n * @param location - Config dir, cwd and prefix.\n */\nexport function extensionsConfigPaths(location: ExtensionsConfigLocation): ExtensionsConfigPaths {\n const cwd = location.cwd ?? process.cwd()\n const projectRoot = findGitRoot(cwd) ?? cwd\n const prefix = (location.prefix ?? '.zidane').replace(/^\\./, '')\n const userConfig = resolve(location.configDir, 'config.json')\n const projectConfig = resolve(projectRoot, `.${prefix}`, 'config.json')\n return {\n user: { config: userConfig, lock: extensionsLockPath(userConfig), baseDir: dirname(userConfig) },\n project: { config: projectConfig, lock: extensionsLockPath(projectConfig), baseDir: projectRoot },\n }\n}\n\n/**\n * Reads a config file as JSON. A missing file is `undefined`; unreadable\n * JSON is `undefined` with an error diagnostic.\n *\n * @param path - The config file.\n * @param scope - Its scope, for diagnostics.\n */\nexport function readExtensionsConfigFile(path: string, scope: ExtensionsConfigScope): { config: unknown, diagnostics: ExtensionsConfigDiagnostic[] } {\n if (!existsSync(path))\n return { config: undefined, diagnostics: [] }\n try {\n return { config: JSON.parse(readFileSync(path, 'utf8')) as unknown, diagnostics: [] }\n }\n catch (err) {\n return { config: undefined, diagnostics: [{ level: 'error', scope, message: `${path} is not valid JSON: ${err instanceof Error ? err.message : String(err)}` }] }\n }\n}\n\n/** One scope's parsed entries and lock. */\nexport interface LoadedExtensionsScope {\n readonly scope: ExtensionsConfigScope\n readonly configPath: string\n readonly lockPath: string\n readonly entries: readonly DeclaredExtension[]\n readonly lock: ExtensionsLock\n}\n\n/** Result of {@link loadExtensionsConfig}. */\nexport interface LoadedExtensionsConfig {\n readonly user: LoadedExtensionsScope\n readonly project: LoadedExtensionsScope\n readonly diagnostics: readonly ExtensionsConfigDiagnostic[]\n}\n\n/**\n * Reads and parses both config files and their locks. Feed `[user,\n * project]` to `createConfigSettingsLayer`.\n *\n * @param location - Config dir, cwd, home and prefix.\n */\nexport function loadExtensionsConfig(location: ExtensionsConfigLocation): LoadedExtensionsConfig {\n const paths = extensionsConfigPaths(location)\n const home = location.home ?? homedir()\n const diagnostics: ExtensionsConfigDiagnostic[] = []\n const load = (scope: ExtensionsConfigScope): LoadedExtensionsScope => {\n const p = paths[scope]\n const file = readExtensionsConfigFile(p.config, scope)\n const parsed = parseExtensionsConfig(file.config, { scope, baseDir: p.baseDir, home })\n const lock = readExtensionsLock(p.lock, scope)\n diagnostics.push(...file.diagnostics, ...parsed.diagnostics, ...lock.diagnostics)\n return { scope, configPath: p.config, lockPath: p.lock, entries: parsed.entries, lock: lock.lock }\n }\n return { user: load('user'), project: load('project'), diagnostics }\n}\n\nconst HASH_SKIP = new Set(['.git', 'node_modules', '.install.json'])\n\n/**\n * `sha256-<base64>` over the extension's files (paths and contents, in\n * sorted order), without `node_modules`, `.git` and `.install.json`.\n * Symlinked folders are not followed.\n *\n * @param dir - The extension directory.\n */\nexport function hashExtensionDir(dir: string): string {\n const hash = createHash('sha256')\n const walk = (current: string): void => {\n for (const name of readdirSync(current).sort()) {\n if (HASH_SKIP.has(name))\n continue\n const path = join(current, name)\n const link = lstatSync(path)\n const stat = link.isSymbolicLink() ? safeStat(path) : link\n if (!stat)\n continue\n if (stat.isDirectory()) {\n if (!link.isSymbolicLink())\n walk(path)\n }\n else if (stat.isFile()) {\n hash.update(relative(dir, path).split('\\\\').join('/'))\n hash.update('\\0')\n hash.update(readFileSync(path))\n hash.update('\\0')\n }\n }\n }\n walk(dir)\n return `sha256-${hash.digest('base64')}`\n}\n\nfunction safeStat(path: string): ReturnType<typeof statSync> | undefined {\n try {\n return statSync(path)\n }\n catch {\n return undefined\n }\n}\n\nfunction readVersion(dir: string): string | undefined {\n try {\n const pkg = JSON.parse(readFileSync(join(dir, 'package.json'), 'utf8')) as { version?: unknown }\n return typeof pkg.version === 'string' && pkg.version ? pkg.version : undefined\n }\n catch {\n return undefined\n }\n}\n\n/** Options of {@link createNodeInstallPort}. */\nexport interface NodeInstallPortOptions {\n /** Default `process.cwd()`. */\n readonly cwd?: string\n /** Default `os.homedir()`. */\n readonly home?: string\n /** Default `.zidane`. */\n readonly prefix?: string\n /** Extra trusted extension roots (`ZIDANE_EXTENSION_DIRS`), for update and remove. */\n readonly extensionScanPaths?: readonly string[]\n /** Network and process seams, for tests. */\n readonly io?: InstallIo\n /** Host-version check seams, for tests. */\n readonly hostVersion?: ZidaneVersionCheckOptions\n}\n\n/**\n * The default port: `installExtensionFromSpec`, `updateInstalledExtension`\n * and `removeInstalledExtension`, plus `checkZidaneVersion` for local\n * folders and a content hash for the lock's `integrity`.\n *\n * @param options - cwd, home, prefix, scan roots and test seams.\n */\nexport function createNodeInstallPort(options: NodeInstallPortOptions = {}): ExtensionsInstallPort {\n const where = {\n ...(options.cwd !== undefined ? { cwd: options.cwd } : {}),\n ...(options.home !== undefined ? { home: options.home } : {}),\n ...(options.prefix !== undefined ? { prefix: options.prefix } : {}),\n }\n const prefix = (options.prefix ?? '.zidane').replace(/^\\./, '')\n // The root installs write to: the scope's `.{prefix}/extensions` (same choice as install.ts' resolveInstallRoot).\n const installRoot = (scope: ExtensionsConfigScope): string => {\n const root = projectUserPaths({ subPath: 'extensions', ...where }).find(p => p.source === scope && p.path.includes(`.${prefix}/`))\n if (!root)\n throw new Error(`unreachable: projectUserPaths yields a .${prefix} root per scope`)\n return root.path\n }\n const record = (r: { name: string, dir: string, provenance: string, commit?: string, warnings: readonly string[] }): InstalledExtensionRecord => {\n const version = readVersion(r.dir)\n return {\n id: r.name,\n dir: r.dir,\n resolved: r.provenance,\n ...(version !== undefined ? { version } : {}),\n ...(r.commit !== undefined ? { commit: r.commit } : {}),\n integrity: hashExtensionDir(r.dir),\n warnings: r.warnings,\n }\n }\n const ioFor = (signal: AbortSignal | undefined): InstallIo | undefined => signal ? abortableInstallIo(options.io, signal) : options.io\n return {\n listInstalled: async (scope) => {\n const root = installRoot(scope)\n let names: string[]\n try {\n names = readdirSync(root).sort()\n }\n catch {\n return []\n }\n const out: InstalledExtensionInfo[] = []\n for (const name of names) {\n const dir = join(root, name)\n if (name.startsWith('.') || !safeStat(dir)?.isDirectory())\n continue\n const prov = readExtensionInstallProvenance(dir)\n out.push({\n id: name,\n dir,\n ...(prov ? { spec: prov.spec } : {}),\n ...(prov?.extension !== undefined ? { extension: prov.extension } : {}),\n ...(prov?.commit !== undefined ? { commit: prov.commit } : {}),\n })\n }\n return out\n },\n install: async (req) => {\n const io = ioFor(req.signal)\n const result = await installExtensionFromSpec({\n source: req.source,\n ...(req.extension !== undefined ? { extension: req.extension } : {}),\n scope: req.scope,\n overwrite: req.overwrite,\n ...where,\n ...(req.onProgress !== undefined ? { onProgress: req.onProgress } : {}),\n ...(io !== undefined ? { io } : {}),\n })\n return record(result)\n },\n update: async (req) => {\n const io = ioFor(req.signal)\n const result = await updateInstalledExtension({\n dir: req.dir,\n ...where,\n ...(options.extensionScanPaths !== undefined ? { extensionScanPaths: options.extensionScanPaths } : {}),\n ...(req.onProgress !== undefined ? { onProgress: req.onProgress } : {}),\n ...(io !== undefined ? { io } : {}),\n })\n return { ...record(result), upToDate: result.upToDate }\n },\n remove: async (req) => {\n removeInstalledExtension({\n dir: req.dir,\n ...where,\n ...(options.extensionScanPaths !== undefined ? { extensionScanPaths: options.extensionScanPaths } : {}),\n })\n },\n describe: async (req) => {\n if (!safeStat(req.dir)?.isDirectory() || !findEntryFile(req.dir))\n return null\n const prov = readExtensionInstallProvenance(req.dir)\n const version = readVersion(req.dir)\n const hostVersion = checkZidaneVersion(req.dir, options.hostVersion)\n const described: DescribedExtension = {\n id: basename(req.dir),\n ...(version !== undefined ? { version } : {}),\n integrity: hashExtensionDir(req.dir),\n ...(prov ? { resolved: prov.source } : {}),\n ...(prov?.commit !== undefined ? { commit: prov.commit } : {}),\n hostVersion,\n }\n return described\n },\n }\n}\n\n/** Options of {@link syncExtensionsConfigFiles}. */\nexport interface SyncExtensionsConfigFilesOptions extends ExtensionsConfigLocation {\n /**\n * Scopes to reconcile. Installing runs the extension's code once (the\n * validation import), so a host passes `'project'` only for a trusted\n * project.\n */\n readonly scopes: readonly ExtensionsConfigScope[]\n /** Default `createNodeInstallPort` over the same location. */\n readonly port?: ExtensionsInstallPort\n /** Re-resolve every remote entry. */\n readonly update?: boolean\n readonly signal?: AbortSignal\n readonly now?: () => Date\n readonly onProgress?: (scope: ExtensionsConfigScope, action: ReconcileAction, message: string) => void\n}\n\n/** Result of {@link syncExtensionsConfigFiles}. */\nexport interface SyncExtensionsConfigFilesResult {\n readonly config: LoadedExtensionsConfig\n /** One result per reconciled scope. */\n readonly results: ReadonlyArray<ReconcileResult & { readonly plan: ReconcilePlan }>\n}\n\n/**\n * Loads both config files, reconciles the requested scopes and writes each\n * lock that changed (atomically). A scope with no entries and no lock\n * writes nothing.\n *\n * @param options - Location, scopes, port and run options.\n */\nexport async function syncExtensionsConfigFiles(options: SyncExtensionsConfigFilesOptions): Promise<SyncExtensionsConfigFilesResult> {\n const config = loadExtensionsConfig(options)\n const port = options.port ?? createNodeInstallPort({\n ...(options.cwd !== undefined ? { cwd: options.cwd } : {}),\n ...(options.home !== undefined ? { home: options.home } : {}),\n ...(options.prefix !== undefined ? { prefix: options.prefix } : {}),\n })\n const results: Array<ReconcileResult & { plan: ReconcilePlan }> = []\n for (const scope of options.scopes) {\n const loaded = config[scope]\n const onProgress = options.onProgress\n const result = await syncDeclaredExtensions({\n scope,\n entries: loaded.entries,\n lock: loaded.lock,\n port,\n ...(options.update !== undefined ? { update: options.update } : {}),\n ...(options.signal !== undefined ? { signal: options.signal } : {}),\n ...(options.now !== undefined ? { now: options.now } : {}),\n ...(onProgress ? { onProgress: (action: ReconcileAction, message: string) => onProgress(scope, action, message) } : {}),\n })\n if (result.changed)\n writeExtensionsLock(loaded.lockPath, result.lock)\n results.push(result)\n }\n return { config, results }\n}\n","/**\n * Declarative install inside a running host. A host that owns an extension\n * set (the daemon per folder, the TUI and the desktop app in local mode)\n * attaches each registry it builds to one {@link ExtensionsConfigSync}:\n *\n * - it reconciles the `extensions` entries of the user and project\n * `config.json` in the background (`syncExtensionsConfigFiles`), once at\n * the first attach and again when a config or lock file changes, one run\n * at a time per scope. Project entries run only for a target whose\n * project is trusted (installing runs the extension's code);\n * - it hands each target the result ({@link ExtensionsConfigSyncReport}),\n * which the host applies to its registry with\n * {@link applyExtensionsConfigReport}: installed, updated and removed\n * folders go through `reloadChangedExtensions`, unlinked ones unload,\n * `enabled` flags follow the config, and failures become inactive rows\n * (where Settings shows install errors).\n *\n * A failed fetch (offline) leaves the previous install and lock entry in\n * place: `reconcile` keeps the lock of a failed action.\n *\n * At build time {@link configuredExtensions} gives the folders config\n * entries link in place and the ids they keep disabled, for\n * `discoverAndBuildExtensionRegistry`.\n */\n\nimport type { LogSink } from '../../logger'\nimport type { LinkedExtensionDir } from '../discovery'\nimport type { NewExtensionFolder, ReloadChangedResult } from '../runtime/reload'\nimport type { ExtensionRegistry, LoadedExtension } from '../types'\nimport type { ExtensionsConfigDiagnostic, ExtensionsConfigScope } from './config'\nimport type { ExtensionsConfigLocation, LoadedExtensionsConfig } from './node'\nimport type { ReconcilePlan } from './plan'\nimport type { ExtensionsInstallPort } from './port'\nimport type { ReconcileResult } from './reconcile'\nimport { existsSync, readFileSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { basename, resolve } from 'node:path'\nimport { errorMessage } from '../../errors'\nimport { extensionRuntimeOf } from '../register'\nimport { registryViewState } from '../runtime/registry-view'\nimport { reloadChangedExtensions } from '../runtime/reload'\nimport { localExtensionId, resolveLocalSource } from './config'\nimport { extensionsConfigPaths, loadExtensionsConfig, syncExtensionsConfigFiles } from './node'\n\n/** What config entries change in a registry build: linked folders and disabled ids. */\nexport interface ConfiguredExtensions {\n /** Folders local entries link in place, once a reconcile recorded them in the lock. */\n readonly links: readonly LinkedExtensionDir[]\n /** Ids of entries with `enabled: false` (the lock's id, or a local folder's name). */\n readonly disabled: readonly string[]\n}\n\n/**\n * Reads both config files and their locks: the folders to load in place and\n * the ids to load disabled. Project entries count only when `trustProject`.\n * Never throws (a broken file reads as no entries).\n *\n * @param location - Config dir, cwd, home and prefix.\n * @param options - Whether the project's entries apply.\n * @param options.trustProject - The project-extensions trust of the build.\n */\nexport function configuredExtensions(location: ExtensionsConfigLocation, options: { trustProject: boolean }): ConfiguredExtensions {\n let loaded: LoadedExtensionsConfig\n try {\n loaded = loadExtensionsConfig(location)\n }\n catch {\n return { links: [], disabled: [] }\n }\n const links: LinkedExtensionDir[] = []\n const disabled: string[] = []\n for (const scope of options.trustProject ? [loaded.project, loaded.user] : [loaded.user]) {\n for (const entry of scope.entries) {\n const lock = scope.lock.extensions[entry.key]\n if (entry.location.kind === 'local' && lock?.resolved.startsWith('local:'))\n links.push({ dir: entry.location.path, source: scope.scope })\n const id = lock?.id ?? (entry.location.kind === 'local' ? localExtensionId(entry.location.path) : undefined)\n if (!entry.enabled && id !== undefined)\n disabled.push(id)\n }\n }\n return { links, disabled }\n}\n\n/** What happened to one config entry (or lock entry) in a reconcile. */\nexport type ConfigSyncStatus = 'installed' | 'updated' | 'up-to-date' | 'kept' | 'adopted' | 'linked' | 'removed' | 'unlinked' | 'forgotten' | 'failed'\n\n/** One entry's outcome, as hosts log and show it. */\nexport interface ConfigSyncItem {\n /** What the reconcile did with the entry. */\n readonly status: ConfigSyncStatus\n /** The config `source` (or the lock's, for a dropped entry). */\n readonly source: string\n /** The extension id, when known. */\n readonly id?: string\n /** For `failed`: why. */\n readonly error?: string\n /** Non-fatal notices (host-version warnings, a moved GitHub pin). */\n readonly warnings: readonly string[]\n}\n\n/** The result of one scope's reconcile, handed to every attached target. */\nexport interface ExtensionsConfigSyncReport {\n /** The config scope that was reconciled (user or project). */\n readonly scope: ExtensionsConfigScope\n /** The `config.json` the entries came from. */\n readonly configPath: string\n /** Each entry's outcome, in config order. */\n readonly items: readonly ConfigSyncItem[]\n /** Folders installed, updated, replaced or removed: reload them. */\n readonly changedDirs: readonly string[]\n /** Folders local entries link in place. */\n readonly linkedDirs: readonly string[]\n /** Folders whose entry was dropped from the config: unload them. */\n readonly unlinkedDirs: readonly string[]\n /** The scope's entries with a known id, and whether they may load. */\n readonly entries: ReadonlyArray<{ readonly id: string, readonly enabled: boolean }>\n /** Problems found in the config file itself (bad entries, unknown keys). */\n readonly diagnostics: readonly ExtensionsConfigDiagnostic[]\n /**\n * `true`: the result of an earlier run, given to a target that attached\n * after it (its registry was built from the disk the run left). Folders\n * the registry already holds are not reloaded.\n */\n readonly replay: boolean\n}\n\n/**\n * The inactive rows of a report's failures: named after the entry's source,\n * carrying the reason.\n *\n * @param report - A reconcile report.\n */\nexport function configSyncFailures(report: ExtensionsConfigSyncReport): LoadedExtension[] {\n return report.items.filter(item => item.status === 'failed').map(item => ({\n name: item.source,\n source: report.scope,\n error: `Installing \"${item.source}\" from ${report.configPath} failed: ${item.error ?? 'unknown error'}`,\n }))\n}\n\n/** Converts a reconcile result into the report hosts apply. */\nfunction toReport(scope: ExtensionsConfigScope, config: LoadedExtensionsConfig, result: ReconcileResult & { readonly plan: ReconcilePlan }, baseDir: string, home: string): ExtensionsConfigSyncReport {\n const items: ConfigSyncItem[] = []\n const changedDirs: string[] = []\n const linkedDirs: string[] = []\n const unlinkedDirs: string[] = []\n for (const outcome of result.outcomes) {\n const action = outcome.action\n const source = 'entry' in action ? action.entry.source : action.lock.source\n const lockId = 'lock' in action ? action.lock?.id : undefined\n if (!outcome.ok) {\n items.push({ status: 'failed', source, ...(lockId !== undefined ? { id: lockId } : {}), error: outcome.error, warnings: [] })\n continue\n }\n const item = (status: ConfigSyncStatus): void => {\n items.push({ status, source, id: outcome.id, warnings: outcome.warnings })\n }\n switch (action.kind) {\n case 'install':\n item('installed')\n if (outcome.dir !== undefined)\n changedDirs.push(outcome.dir)\n if (action.replaces && action.replaces.dir !== outcome.dir)\n changedDirs.push(action.replaces.dir)\n break\n case 'update':\n item(outcome.upToDate ? 'up-to-date' : 'updated')\n if (!outcome.upToDate && outcome.dir !== undefined)\n changedDirs.push(outcome.dir)\n if (outcome.dir !== undefined && outcome.dir !== action.installed.dir)\n changedDirs.push(action.installed.dir)\n break\n case 'keep':\n item('kept')\n break\n case 'adopt':\n item('adopted')\n break\n case 'link':\n item('linked')\n linkedDirs.push(action.path)\n break\n case 'remove':\n item('removed')\n changedDirs.push(action.installed.dir)\n break\n case 'forget':\n if (action.lock.resolved.startsWith('local:')) {\n item('unlinked')\n unlinkedDirs.push(resolveLocalSource(action.lock.resolved.slice('local:'.length), baseDir, home))\n }\n else {\n item('forgotten')\n }\n break\n }\n }\n const loaded = config[scope]\n const entries = loaded.entries.flatMap((entry) => {\n const id = result.lock.extensions[entry.key]?.id ?? (entry.location.kind === 'local' ? localExtensionId(entry.location.path) : undefined)\n return id !== undefined ? [{ id, enabled: entry.enabled }] : []\n })\n const diagnostics = [...config.diagnostics.filter(d => d.scope === scope), ...result.plan.diagnostics]\n return { scope, configPath: loaded.configPath, items, changedDirs, linkedDirs, unlinkedDirs, entries, diagnostics, replay: false }\n}\n\n/** A registry a host keeps in line with the config. */\nexport interface ExtensionsConfigSyncTarget {\n /** The folder the registry was built for: picks the project config. */\n readonly cwd: string\n /** Whether the project's entries apply (the build's project-extensions trust). */\n readonly trustProject: () => boolean\n /**\n * Applies a report to the registry (usually {@link applyExtensionsConfigReport}). Its errors are logged.\n * Called without awaiting the previous apply (the scope's next run does not wait for it): a host that\n * waits (for runs to end) queues the reports itself, in call order.\n */\n readonly apply: (report: ExtensionsConfigSyncReport) => void | Promise<void>\n}\n\n/** A level and a line, for the host's log. */\nexport type ConfigSyncLog = (level: 'info' | 'warn' | 'error', message: string) => void\n\n/** Options of {@link createExtensionsConfigSync}. */\nexport interface ExtensionsConfigSyncOptions {\n /** The user config dir (`ResolvedConfig.paths.configDir`). */\n readonly configDir: string\n /** Default `.zidane`. */\n readonly prefix?: string\n /** Default `os.homedir()`. */\n readonly home?: string\n /** The install port of a scope run from `cwd`. Default `createNodeInstallPort`. A test seam. */\n readonly port?: (scope: ExtensionsConfigScope, cwd: string) => ExtensionsInstallPort\n /** Where outcomes and errors go. Default: warnings and errors to the console. */\n readonly log?: ConfigSyncLog\n /**\n * Calls `onChange` after `file` changes (hosts pass `watchFileChanges`,\n * which follows atomic replaces and polls). Returns the stop. Absent or\n * `false`: no watching, the config applies at attach only.\n */\n readonly watch?: false | ((file: string, onChange: () => void) => () => void)\n /** Clock for the lock's `installedAt`. */\n readonly now?: () => Date\n}\n\n/** The process's declarative-install coordinator. */\nexport interface ExtensionsConfigSync {\n /**\n * Follows the config for one registry. Reconciles in the background the\n * scopes no run covered yet; a scope already reconciled replays its last\n * report to the target. Returns the detach.\n */\n attach: (target: ExtensionsConfigSyncTarget) => () => void\n /** Resolves once no scope run (and no apply it started) is in flight. */\n settled: () => Promise<void>\n /** Stops watching; runs in flight finish but apply nothing. */\n close: () => void\n}\n\ninterface ScopeState {\n readonly scope: ExtensionsConfigScope\n readonly configPath: string\n readonly lockPath: string\n readonly baseDir: string\n readonly targets: Set<ExtensionsConfigSyncTarget>\n running?: Promise<void>\n again: boolean\n /** Targets attached while a run was in flight and not yet handed its report: replayed when the run ends. */\n readonly pending: Set<ExtensionsConfigSyncTarget>\n last?: ExtensionsConfigSyncReport\n /** The config and lock contents the last run left: a change event that matches is the run's own write. */\n stamp?: string\n stopWatch?: () => void\n}\n\nfunction readText(path: string): string {\n try {\n return readFileSync(path, 'utf8')\n }\n catch {\n return ''\n }\n}\n\nconst defaultLog: ConfigSyncLog = (level, message) => {\n if (level !== 'info')\n console.warn(`[extensions] ${message}`)\n}\n\nfunction logReport(report: ExtensionsConfigSyncReport, log: ConfigSyncLog): void {\n for (const d of report.diagnostics)\n log(d.level === 'error' ? 'error' : 'warn', `${report.configPath}${d.index !== undefined ? ` entry ${d.index}` : ''}: ${d.message}`)\n for (const item of report.items) {\n const name = item.id !== undefined && item.id !== item.source ? `${item.id} (${item.source})` : item.source\n if (item.status === 'failed')\n log('error', `config extension ${name} failed: ${item.error}`)\n else if (item.status !== 'kept' && item.status !== 'linked' && item.status !== 'up-to-date')\n log('info', `config extension ${name} ${item.status}`)\n for (const warning of item.warnings)\n log('warn', `config extension ${name}: ${warning}`)\n }\n}\n\n/**\n * Creates the coordinator. One per process: scopes are keyed by config file,\n * so every registry of the same user (and project) shares one run.\n *\n * @param options - Config dir, prefix, home, and the port, log and watch seams.\n * @returns The coordinator.\n */\nexport function createExtensionsConfigSync(options: ExtensionsConfigSyncOptions): ExtensionsConfigSync {\n const log = options.log ?? defaultLog\n const home = options.home ?? homedir()\n const watchFile = options.watch === false ? undefined : options.watch\n const states = new Map<string, ScopeState>()\n /** Applies in flight, for {@link ExtensionsConfigSync.settled}. */\n const applies = new Set<Promise<void>>()\n let closed = false\n\n const location = (cwd: string): ExtensionsConfigLocation => ({\n configDir: options.configDir,\n cwd,\n home,\n ...(options.prefix !== undefined ? { prefix: options.prefix } : {}),\n })\n const stampOf = (s: ScopeState): string => `${readText(s.configPath)}\\0${readText(s.lockPath)}`\n const eligible = (s: ScopeState): ExtensionsConfigSyncTarget[] => [...s.targets].filter(t => s.scope === 'user' || t.trustProject())\n\n // Starts every apply at once, in order, without awaiting: one target waiting for its runs must not hold the scope.\n const deliver = (report: ExtensionsConfigSyncReport, targets: readonly ExtensionsConfigSyncTarget[]): void => {\n for (const target of targets) {\n if (closed)\n return\n const apply: Promise<void> = (async () => target.apply(report))()\n .catch((err: unknown) => log('error', `applying ${report.configPath} failed: ${errorMessage(err)}`))\n .finally(() => applies.delete(apply))\n applies.add(apply)\n }\n }\n\n const runOnce = async (s: ScopeState): Promise<void> => {\n const first = eligible(s)[0]\n if (!first)\n return\n let report: ExtensionsConfigSyncReport\n // Read before the sync: an edit saved during it must not pass for the run's own write.\n const configBefore = readText(s.configPath)\n try {\n const { config, results } = await syncExtensionsConfigFiles({\n ...location(first.cwd),\n scopes: [s.scope],\n ...(options.port ? { port: options.port(s.scope, first.cwd) } : {}),\n ...(options.now ? { now: options.now } : {}),\n })\n report = toReport(s.scope, config, results[0]!, s.baseDir, home)\n }\n catch (err) {\n // Reading or writing the files failed: nothing changed on disk that a target must reload.\n report = { scope: s.scope, configPath: s.configPath, items: [{ status: 'failed', source: s.configPath, error: errorMessage(err), warnings: [] }], changedDirs: [], linkedDirs: [], unlinkedDirs: [], entries: [], diagnostics: [], replay: false }\n }\n s.stamp = `${configBefore}\\0${readText(s.lockPath)}`\n if (readText(s.configPath) !== configBefore)\n s.again = true\n s.last = report\n logReport(report, log)\n const targets = eligible(s)\n for (const target of targets)\n s.pending.delete(target)\n deliver(report, targets)\n }\n\n const kick = (s: ScopeState): void => {\n if (closed)\n return\n if (s.running) {\n s.again = true\n return\n }\n s.running = (async () => {\n try {\n for (;;) {\n s.again = false\n await runOnce(s)\n if (!s.again || closed)\n return\n }\n }\n catch (err) {\n log('error', `reconciling ${s.configPath} failed: ${errorMessage(err)}`)\n }\n finally {\n // In the same step that ends the run: a later attach sees no run and replays by itself.\n s.running = undefined\n const missed = [...s.pending].filter(t => s.targets.has(t) && (s.scope === 'user' || t.trustProject()))\n s.pending.clear()\n if (missed.length > 0 && !closed) {\n if (s.last)\n deliver({ ...s.last, replay: true }, missed)\n else\n kick(s)\n }\n }\n })()\n }\n\n const stateFor = (scope: ExtensionsConfigScope, paths: { config: string, lock: string, baseDir: string }): ScopeState => {\n const key = `${scope}\\0${paths.config}`\n let s = states.get(key)\n if (!s) {\n s = { scope, configPath: paths.config, lockPath: paths.lock, baseDir: paths.baseDir, targets: new Set(), again: false, pending: new Set() }\n states.set(key, s)\n }\n return s\n }\n\n const startWatch = (s: ScopeState): void => {\n if (!watchFile || s.stopWatch)\n return\n const onChange = (): void => {\n if (stampOf(s) !== s.stamp && eligible(s).length > 0)\n kick(s)\n }\n const stops = [watchFile(s.configPath, onChange), watchFile(s.lockPath, onChange)]\n s.stopWatch = () => {\n for (const stop of stops) stop()\n }\n }\n\n const stopWatch = (s: ScopeState): void => {\n s.stopWatch?.()\n s.stopWatch = undefined\n }\n\n return {\n attach: (target) => {\n if (closed)\n return () => undefined\n const paths = extensionsConfigPaths(location(target.cwd))\n const scopes = [stateFor('user', paths.user), stateFor('project', paths.project)]\n for (const s of scopes) {\n s.targets.add(target)\n startWatch(s)\n if (s.scope === 'project' && !target.trustProject())\n continue\n if (s.running) {\n // The run hands it its report, or replays the last one when it ends.\n s.pending.add(target)\n continue\n }\n if (s.last && s.stamp === stampOf(s)) {\n deliver({ ...s.last, replay: true }, [target])\n }\n else {\n kick(s)\n }\n }\n return () => {\n for (const s of scopes) {\n s.targets.delete(target)\n s.pending.delete(target)\n if (s.targets.size === 0)\n stopWatch(s)\n }\n }\n },\n settled: async () => {\n for (;;) {\n const running = [...applies, ...[...states.values()].flatMap(s => (s.running ? [s.running] : []))]\n if (running.length === 0)\n return\n await Promise.all(running)\n }\n },\n close: () => {\n closed = true\n for (const s of states.values())\n stopWatch(s)\n },\n }\n}\n\n/** Options of {@link applyExtensionsConfigReport}. */\nexport interface ApplyConfigReportOptions {\n /** How a new folder under a scan root loads (the host's watcher rule). Linked folders load without it. */\n readonly classify?: (dir: string) => NewExtensionFolder | undefined\n /** Whether the host lets `id` run (its allowlist). Default: every id. */\n readonly allowed?: (id: string) => boolean\n /** How long one extension import may take. Default 10 s. */\n readonly importTimeoutMs?: number\n /** Where load warnings go. */\n readonly sink?: LogSink\n /** Node hosts: the folder compiled extension code is kept in. */\n readonly compileCache?: string\n}\n\n/**\n * Applies a report to a live registry, one extension at a time: changed\n * folders through `reloadChangedExtensions` (loaded, reloaded or unloaded\n * in place), linked folders it does not hold yet loaded, unlinked ones\n * unloaded, each held entry's `enabled` set to what the config and\n * `allowed` say (a reload of that extension), and the report's failures\n * listed as inactive rows (`config:<scope>`). Never rejects for an\n * extension's fault.\n *\n * @param registry - A registry from `buildExtensionRegistry` (or a view of one).\n * @param report - From an {@link ExtensionsConfigSync} target's `apply`.\n * @param options - Classify, allowlist, import bound, sink and compile cache.\n * @returns What loaded, reloaded and unloaded; `needsRebuild` when the registry holds no runtime to load into.\n */\nexport async function applyExtensionsConfigReport(registry: ExtensionRegistry, report: ExtensionsConfigSyncReport, options: ApplyConfigReportOptions = {}): Promise<ReloadChangedResult> {\n registryViewState(registry)?.source.reportRefused(`config:${report.scope}`, configSyncFailures(report))\n const runtime = extensionRuntimeOf(registry)\n const result: ReloadChangedResult = { loaded: [], reloaded: [], unloaded: [], needsRebuild: false }\n const enabledOf = new Map(report.entries.map(e => [e.id, e.enabled]))\n const wants = (id: string): boolean => (options.allowed?.(id) ?? true) && enabledOf.get(id) !== false\n const held = (dir: string): boolean => runtime?.idOfDir(dir) !== undefined\n\n for (const dir of report.unlinkedDirs.map(d => resolve(d))) {\n const id = runtime?.idOfDir(dir)\n if (runtime && id !== undefined) {\n await runtime.unload(id, { forget: true })\n result.unloaded.push(id)\n }\n }\n\n const linked = new Set(report.linkedDirs.map(d => resolve(d)))\n const dirs = [\n ...report.changedDirs.map(d => resolve(d)).filter(d => !report.replay || !held(d) || !existsSync(d)),\n ...[...linked].filter(d => !held(d)),\n ]\n if (dirs.length > 0) {\n const classify = (dir: string): NewExtensionFolder | undefined => {\n if (linked.has(dir))\n return { source: report.scope, enabled: wants(basename(dir)) }\n const how = options.classify?.(dir)\n return how ? { ...how, enabled: how.enabled !== false && wants(basename(dir)) } : undefined\n }\n const done = await reloadChangedExtensions(registry, dirs, {\n classify,\n ...(options.importTimeoutMs !== undefined ? { importTimeoutMs: options.importTimeoutMs } : {}),\n ...(options.sink ? { sink: options.sink } : {}),\n ...(options.compileCache !== undefined ? { compileCache: options.compileCache } : {}),\n })\n result.loaded.push(...done.loaded)\n result.reloaded.push(...done.reloaded)\n result.unloaded.push(...done.unloaded)\n result.needsRebuild = done.needsRebuild\n }\n\n for (const { id } of runtime ? report.entries : []) {\n const ext = runtime!.get(id)\n const want = wants(id)\n if (!ext || (ext.entry.enabled !== false) === want)\n continue\n const info = await runtime!.reload(id, { entry: { ...ext.entry, enabled: want } })\n if (info && !result.reloaded.includes(id))\n result.reloaded.push(id)\n }\n return result\n}\n","/**\n * The `config` settings layer: values set by declarative config entries,\n * by extension id. The settings domain reads it between the user layer and\n * the schema default (session ` project ` user ` config ` default) and\n * shows every key it holds as locked.\n *\n * Built from the parsed entries and the locks (which map a source to the\n * id it installed as). Rebuild it when a config file or lock changes; the\n * layer itself is an immutable snapshot.\n */\n\nimport type { SettingsSchema } from '../api/settings'\nimport type { ConfigSettingValue, DeclaredExtension, ExtensionsConfigScope } from './config'\nimport type { ExtensionsLock } from './lock'\nimport { localExtensionId } from './config'\n\n/** One config file's entries and its lock. */\nexport interface ConfigSettingsSource {\n readonly entries: readonly DeclaredExtension[]\n readonly lock: ExtensionsLock\n}\n\n/** A config entry that applies to an extension id. */\nexport interface ConfigLayerEntry {\n readonly id: string\n readonly scope: ExtensionsConfigScope\n /** The entry's `source`, for \"set by …\" hints in Settings. */\n readonly source: string\n readonly enabled: boolean\n readonly settings: Readonly<Record<string, ConfigSettingValue>>\n}\n\n/** Read access to the config layer. */\nexport interface ConfigSettingsLayer {\n /** The value config sets for `key`, or `undefined`. */\n get: (extensionId: string, key: string) => ConfigSettingValue | undefined\n /** Whether config sets `key` (Settings shows it locked). */\n locked: (extensionId: string, key: string) => boolean\n /** The config file that set `key`, when one did. */\n origin: (extensionId: string, key: string) => ExtensionsConfigScope | undefined\n /** Every value config sets for the extension. */\n values: (extensionId: string) => Readonly<Record<string, ConfigSettingValue>>\n /** `enabled` from config, or `undefined` when no entry declares the extension. */\n enabled: (extensionId: string) => boolean | undefined\n /** The entries that apply to the extension, in precedence order (last wins). */\n entries: (extensionId: string) => readonly ConfigLayerEntry[]\n /** Ids config declares. */\n ids: () => readonly string[]\n}\n\n/**\n * The id a config entry stands for: from its lock entry, or the folder name\n * of a local source. `undefined` for a remote entry not installed yet.\n *\n * @param entry - The config entry.\n * @param lock - Its scope's lock.\n */\nexport function resolveDeclaredId(entry: DeclaredExtension, lock: ExtensionsLock): string | undefined {\n const locked = lock.extensions[entry.key]\n if (locked && locked.source === entry.source)\n return locked.id\n return entry.location.kind === 'local' ? localExtensionId(entry.location.path) : undefined\n}\n\n/**\n * Builds the layer. Pass the user source first and the project source\n * after: a later source wins per key and for `enabled`.\n *\n * @param sources - Config entries with their locks, lowest precedence first.\n */\nexport function createConfigSettingsLayer(sources: readonly ConfigSettingsSource[]): ConfigSettingsLayer {\n const byId = new Map<string, ConfigLayerEntry[]>()\n for (const { entries, lock } of sources) {\n for (const entry of entries) {\n const id = resolveDeclaredId(entry, lock)\n if (id === undefined)\n continue\n const list = byId.get(id) ?? []\n list.push({ id, scope: entry.scope, source: entry.source, enabled: entry.enabled, settings: entry.settings })\n byId.set(id, list)\n }\n }\n const merged = new Map<string, { values: Record<string, ConfigSettingValue>, origins: Record<string, ExtensionsConfigScope> }>()\n for (const [id, list] of byId) {\n const values: Record<string, ConfigSettingValue> = {}\n const origins: Record<string, ExtensionsConfigScope> = {}\n for (const e of list) {\n for (const [key, value] of Object.entries(e.settings)) {\n values[key] = value\n origins[key] = e.scope\n }\n }\n merged.set(id, { values, origins })\n }\n const own = (record: Record<string, unknown> | undefined, key: string): boolean => record !== undefined && Object.hasOwn(record, key)\n return {\n get: (id, key) => {\n const m = merged.get(id)\n return m && own(m.values, key) ? m.values[key] : undefined\n },\n locked: (id, key) => own(merged.get(id)?.values, key),\n origin: (id, key) => {\n const m = merged.get(id)\n return m && own(m.origins, key) ? m.origins[key] : undefined\n },\n values: id => ({ ...merged.get(id)?.values }),\n enabled: id => byId.get(id)?.at(-1)?.enabled,\n entries: id => byId.get(id) ?? [],\n ids: () => [...byId.keys()],\n }\n}\n\n/** A config value the schema refused. */\nexport interface ConfigSettingIssue {\n readonly key: string\n readonly message: string\n}\n\n/**\n * Checks config values against an extension's settings schema. Refused\n * values are dropped (the setting falls back to the next layer) and\n * reported. Secret settings are always refused: they live in the auth\n * store, never in a config file. A setting's own `validate` callback is\n * extension code and is left to the settings domain, which runs it under\n * its guard.\n *\n * @param schema - The extension's `settings`.\n * @param values - What config sets (`layer.values(id)`).\n */\nexport function validateConfigSettings(schema: SettingsSchema | undefined, values: Readonly<Record<string, ConfigSettingValue>>): { values: Record<string, ConfigSettingValue>, issues: ConfigSettingIssue[] } {\n const out: Record<string, ConfigSettingValue> = {}\n const issues: ConfigSettingIssue[] = []\n for (const [key, value] of Object.entries(values)) {\n const item = schema?.items[key]\n const refuse = (message: string): void => {\n issues.push({ key, message })\n }\n if (!item) {\n refuse(`\"${key}\" is not a setting of this extension.`)\n continue\n }\n switch (item.type) {\n case 'action':\n refuse(`\"${key}\" is a button, not a value.`)\n continue\n case 'boolean':\n if (typeof value !== 'boolean')\n refuse(`\"${key}\" must be true or false.`)\n break\n case 'number':\n if (typeof value !== 'number')\n refuse(`\"${key}\" must be a number.`)\n else if ((item.min !== undefined && value < item.min) || (item.max !== undefined && value > item.max))\n refuse(`\"${key}\" must be between ${item.min ?? '-∞'} and ${item.max ?? '∞'}.`)\n break\n case 'string':\n if (item.secret)\n refuse(`\"${key}\" is a secret. Set it in Settings, not in a config file.`)\n else if (typeof value !== 'string')\n refuse(`\"${key}\" must be text.`)\n else if (item.pattern !== undefined && !safeTest(item.pattern, value))\n refuse(`\"${key}\" does not match ${item.pattern}.`)\n break\n case 'enum':\n if (typeof value !== 'string' || !item.options.some(o => o.value === value))\n refuse(`\"${key}\" must be one of: ${item.options.map(o => o.value).join(', ')}.`)\n break\n case 'model':\n if (item.multi ? !Array.isArray(value) : typeof value !== 'string')\n refuse(item.multi ? `\"${key}\" must be a list of models.` : `\"${key}\" must be a model id.`)\n break\n }\n if (!issues.some(i => i.key === key))\n out[key] = value\n }\n return { values: out, issues }\n}\n\n/** A pattern that does not compile refuses nothing (the schema is at fault, not the value). */\nfunction safeTest(pattern: string, value: string): boolean {\n try {\n return new RegExp(pattern).test(value)\n }\n catch {\n return true\n }\n}\n","/**\n * Shared discover → disabled-set → build pipeline.\n *\n * Every host runs the identical sequence: the TUI launcher (`runTui`),\n * the TUI's cwd-change rebuild, the daemon's per-cwd runtime cache and the\n * GUI's per-cwd registry cache.\n * Centralizing it keeps the allowlist-gating contract — the `disabled`\n * set spans BOTH disk-discovered and inline candidates — in one place\n * so the callers can't drift on it.\n */\n\nimport type { Settings } from '../chat/types'\nimport type { LogSink } from '../logger'\nimport type { LinkedExtensionDir } from './discovery'\nimport type { ExtensionHostRuntimeBridge } from './host-runtime'\nimport type { ExtensionPromptBridge } from './prompt-bridge'\nimport type { BuildRuntimeOptions } from './register'\nimport type { ExtensionRegistry, LoadedExtension } from './types'\nimport { discoverExtensions } from './discovery'\nimport { registerExtensionApiHostModules } from './host-modules'\nimport { buildExtensionRegistry } from './register'\n\n/** Options for {@link discoverAndBuildExtensionRegistry}. */\nexport interface DiscoverAndBuildExtensionRegistryOptions {\n /** Discovery cwd — project roots are walked up from here. Defaults to `process.cwd()`. */\n cwd?: string\n /** User home directory. Defaults to `os.homedir()`. Mainly a test seam. */\n home?: string\n /** Storage prefix (e.g. `.zidane`). Defaults to `.zidane` inside discovery. */\n prefix?: string\n /**\n * Extra extension scan roots, prepended ahead of the default project/user\n * roots. Each root contains extension package dirs (`<root>/<name>/index.ts`).\n * Treated as user-scoped/trusted because the host/user opted into them\n * explicitly.\n */\n extensionScanPaths?: readonly string[]\n /**\n * Extension folders a config entry links in place (`configuredExtensions`,\n * `./declarative/host-sync`). Each is one extension, ahead of every scan root.\n */\n linkedExtensionDirs?: readonly LinkedExtensionDir[]\n /** Ids a config entry keeps installed but off (`enabled: false`): they load disabled, like ones the allowlist leaves out. */\n configDisabled?: readonly string[]\n /**\n * User enable allowlist (`Settings.enabledExtensions`). `undefined`\n * means \"fresh install — everything enabled\". When set it gates BOTH\n * disk and inline candidates: a name absent from the list lands in the\n * build's `disabled` set, so it classifies as `inactive` and its\n * contributions never reach the registry's active surface. Its\n * `setup()` does not run; its settings stay browsable in Settings\n * before enabling.\n */\n enabledAllowlist?: readonly string[]\n /** Whether project-scoped extensions are trusted (allowed to run their code). */\n trustProjectExtensions?: boolean\n /** Host-supplied inline extensions, already `inlineLoadedExtension()`-wrapped. */\n inlineExtensions?: readonly LoadedExtension[]\n /** Log sink for the runtime. Defaults to stderr inside `buildExtensionRegistry`. */\n sink?: LogSink\n /** Prompt bridge for `ctx.sessions.submit` (hosts with a submit pipeline). */\n promptBridge?: ExtensionPromptBridge\n /** Host runtime bridge for `ctx.sessions` / `ctx.workspace` / `ctx.artifacts`. */\n hostRuntime?: ExtensionHostRuntimeBridge\n /**\n * Live settings getter: the `user` settings layer, threaded verbatim to\n * {@link BuildExtensionRegistryOptions.readSettings}. Hosts pass a getter\n * returning their current `Settings` (TUI: a live mirror; GUI: the DB\n * reader) so extension settings reads are live.\n */\n readSettings?: () => Partial<Settings> | undefined\n /** Abort discovery before its imports dispatch. */\n signal?: AbortSignal\n /** Node hosts: the folder compiled extension code is kept in, so only a changed file compiles again (`./compile-cache`). */\n compileCache?: string\n /** Host kind and ports of the runtime (`registry.runtime`). */\n runtime?: BuildRuntimeOptions\n}\n\n/**\n * Discover disk extensions, fold in the inline ones, compute the\n * allowlist-driven `disabled` set, and build the merged\n * {@link ExtensionRegistry}.\n *\n * The `disabled` set honors the allowlist for inline extensions too:\n * the TUI treats inline as toggleable everywhere else (Settings tab,\n * live filtering), so both ride the same inactive-classification path.\n *\n * @param opts - Discovery, trust, allowlist and bridge options.\n */\nexport async function discoverAndBuildExtensionRegistry(\n opts: DiscoverAndBuildExtensionRegistryOptions = {},\n): Promise<ExtensionRegistry> {\n // Core entrypoints, mapped BEFORE discovery's imports dispatch. An extension\n // contributing a provider (`ctx.providers`) needs the host's live\n // factories and credential helpers at runtime; a bare `import { anthropic }\n // from 'zidane'` would otherwise resolve from the EXTENSION's directory —\n // nothing inside a compiled binary, or a second zidane copy with its own\n // module state (and its own OAuth registry). Renderer-neutral, so it lives\n // here rather than in the TUI: headless / ACP / GUI hosts get it too.\n // pi-ai is NOT mapped: a lazy mapping would re-import the very specifier it\n // intercepts. Extensions reach the host's provider plumbing through zidane\n // instead (`googleCompatible`).\n registerCoreExtensionHostModules()\n\n const discovered = await discoverExtensions({\n ...(opts.cwd !== undefined ? { cwd: opts.cwd } : {}),\n ...(opts.home !== undefined ? { home: opts.home } : {}),\n ...(opts.prefix !== undefined ? { prefix: opts.prefix } : {}),\n ...(opts.extensionScanPaths !== undefined ? { extensionScanPaths: opts.extensionScanPaths } : {}),\n ...(opts.linkedExtensionDirs !== undefined ? { linkedExtensionDirs: opts.linkedExtensionDirs } : {}),\n ...(opts.trustProjectExtensions !== undefined ? { trustProjectExtensions: opts.trustProjectExtensions } : {}),\n ...(opts.signal !== undefined ? { signal: opts.signal } : {}),\n ...(opts.sink !== undefined ? { sink: opts.sink } : {}),\n ...(opts.compileCache !== undefined ? { compileCache: opts.compileCache } : {}),\n })\n const candidates = [...discovered, ...(opts.inlineExtensions ?? [])]\n const allowlist = opts.enabledAllowlist\n const configDisabled = new Set(opts.configDisabled ?? [])\n const disabled = allowlist === undefined && configDisabled.size === 0\n ? undefined\n : new Set(candidates.map(e => e.name).filter(name => configDisabled.has(name) || (allowlist !== undefined && !allowlist.includes(name))))\n return buildExtensionRegistry(candidates, {\n ...(opts.sink !== undefined ? { sink: opts.sink } : {}),\n ...(opts.promptBridge !== undefined ? { promptBridge: opts.promptBridge } : {}),\n ...(opts.hostRuntime !== undefined ? { hostRuntime: opts.hostRuntime } : {}),\n ...(disabled ? { disabled } : {}),\n ...(opts.readSettings !== undefined ? { readSettings: opts.readSettings } : {}),\n ...(opts.cwd !== undefined ? { cwd: opts.cwd } : {}),\n ...(opts.prefix !== undefined ? { prefix: opts.prefix } : {}),\n ...(opts.runtime !== undefined ? { runtime: opts.runtime } : {}),\n })\n}\n\n/**\n * Maps every zidane entrypoint extensions import at runtime\n * (`hostModuleSpecifiers()`) to this process's live modules, so an\n * installed extension (or one inside a compiled binary) gets the host's\n * copy. Idempotent; call before importing an extension. Same as\n * `registerExtensionApiHostModules`.\n */\nexport function registerCoreExtensionHostModules(): void {\n registerExtensionApiHostModules()\n}\n","/**\n * {@link integrationMethodFromOAuthProvider}: a `zidane/oauth` provider flow\n * (`OAuthProviderInterface`: `login`, `refreshToken`, `getApiKey`) as an\n * integration's `custom` method, so a bespoke flow (Bolt's device flow\n * with its Access headers) signs in through `ctx.integrations`.\n *\n * Type imports only: authors import it from `zidane`, and it must not pull\n * the provider graph in.\n */\n\nimport type { OAuthCredentials } from '@earendil-works/pi-ai/oauth'\nimport type { OAuthProviderInterface } from '../../providers/oauth-registry'\nimport type { Credential, IntegrationCustomMethod, IntegrationFlowIO } from '../api/sessions'\n\n/** Fields of a grant the credential carries elsewhere. */\nconst GRANT_FIELDS = new Set(['access', 'refresh', 'expires', 'kind', 'type'])\n\nfunction toCredential(provider: OAuthProviderInterface, grant: OAuthCredentials): Extract<Credential, { type: 'oauth' }> {\n const extra: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(grant)) {\n if (!GRANT_FIELDS.has(key))\n extra[key] = value\n }\n const apiKey = provider.getApiKey(grant)\n // The credential hands out the API key; keep the raw access token for the next refresh.\n if (apiKey !== grant.access)\n extra.access = grant.access\n return {\n type: 'oauth',\n accessToken: apiKey,\n ...(typeof grant.expires === 'number' && Number.isFinite(grant.expires) ? { expiresAt: grant.expires } : {}),\n ...(typeof grant.refresh === 'string' && grant.refresh ? { refreshToken: grant.refresh } : {}),\n ...(Object.keys(extra).length ? { extra } : {}),\n }\n}\n\nfunction toGrant(credential: Credential): OAuthCredentials {\n if (credential.type !== 'oauth')\n throw new Error('This sign-in has no OAuth grant to refresh.')\n const { access, ...extra } = (credential.extra ?? {}) as Record<string, unknown>\n return {\n ...extra,\n access: typeof access === 'string' ? access : credential.accessToken,\n refresh: credential.refreshToken ?? '',\n expires: credential.expiresAt ?? 0,\n }\n}\n\nfunction labelOf(grant: OAuthCredentials): string | undefined {\n for (const key of ['email', 'account', 'label']) {\n const value = grant[key]\n if (typeof value === 'string' && value.trim())\n return value.trim()\n }\n return undefined\n}\n\nasync function promptOrCancel(io: IntegrationFlowIO, opts: Parameters<IntegrationFlowIO['prompt']>[0]): Promise<string> {\n const value = await io.prompt(opts)\n if (value === undefined)\n throw new Error('Sign-in cancelled.')\n return value\n}\n\n/**\n * Adapts a `zidane/oauth` provider flow to an integration method of type\n * `custom`. `connect` runs `provider.login` with the host's flow UI\n * (links, device codes, prompts and choices go through {@link IntegrationFlowIO});\n * the credential's `accessToken` is `provider.getApiKey(grant)`, the\n * refresh token is kept by the store, and other grant fields ride in\n * `credential.extra`. `refresh` runs `provider.refreshToken`. The account\n * is the grant's `email`, `account` or `label` when it has one.\n *\n * @param provider - The flow (`OAuthProviderInterface` from `zidane/oauth`).\n * @param opts - Method id (default `provider.id`), label (default `Sign in with <name>`) and help.\n * @param opts.id - The method id.\n * @param opts.label - The button label.\n * @param opts.help - A line under it.\n */\nexport function integrationMethodFromOAuthProvider(provider: OAuthProviderInterface, opts: { id?: string, label?: string, help?: string } = {}): IntegrationCustomMethod {\n return {\n type: 'custom',\n id: opts.id ?? provider.id,\n label: opts.label ?? `Sign in with ${provider.name}`,\n ...(opts.help ? { help: opts.help } : {}),\n connect: async (io) => {\n const grant = await provider.login({\n onAuth: (info) => {\n if (info.instructions)\n io.log(info.instructions)\n io.openUrl(info.url)\n },\n onDeviceCode: info => io.showCode(info.userCode, info.verificationUri),\n onPrompt: prompt => promptOrCancel(io, { message: prompt.message, ...(prompt.placeholder ? { placeholder: prompt.placeholder } : {}), ...(prompt.allowEmpty ? { allowEmpty: true } : {}) }),\n onSelect: prompt => io.prompt({ message: prompt.message, options: prompt.options.map(o => ({ id: o.id, label: o.label })) }),\n onProgress: message => io.log(message),\n signal: io.signal,\n })\n const label = labelOf(grant)\n return { credential: toCredential(provider, grant), ...(label ? { account: label, label } : {}) }\n },\n refresh: async credential => toCredential(provider, await provider.refreshToken(toGrant(credential))),\n }\n}\n","/**\n * Hosting extension side panels and palette providers for an app that paints\n * them elsewhere (the desktop app's renderer, a zidane-server's clients):\n * a folder's panels as summaries, a panel's `load()` and `onAction` run with\n * a hard timeout and their results normalised, a provider's items and runs\n * the same way, and their `subscribe` debounced into one change call. One\n * broken extension yields an empty panel or an error row, never a rejection.\n *\n * A panel runs in a read-only host scope ({@link panelHostRuntime}): the\n * folder's project, and the session when one is bound.\n */\nimport type { PaletteContext, PaletteItem, PaletteRunResult } from '../chat/palette'\nimport type { SessionArtifact } from '../session/artifacts'\nimport type { ExtensionHostRuntimeBridge, ExtensionHostRuntimeImpl } from './host-runtime'\nimport type { ExtensionPanelEntry, ExtensionPanelScope, PanelContent, PanelHomeLayout, PanelIcon, PanelLoadContextInput, PanelSurface } from './panels'\nimport type { ExtensionPaletteProviderEntry } from './types'\nimport { normalizePaletteItems, normalizePaletteRunResult } from '../chat/palette'\nimport { normalizePanelContent, panelSurfaces, resolvePanelLoadContext } from './panels'\nimport { withTimeout } from './with-timeout'\n\nconst LOAD_TIMEOUT_MS = 10_000\nconst ACTION_TIMEOUT_MS = 30_000\nconst ITEMS_TIMEOUT_MS = 3_000\nconst CHANGE_DEBOUNCE_MS = 150\n\nfunction timed<T>(work: () => T | Promise<T>, ms: number): Promise<T> {\n return withTimeout(Promise.resolve().then(work), ms, `timed out after ${ms}ms`)\n}\n\nfunction messageOf(err: unknown): string {\n return err instanceof Error ? err.message : String(err)\n}\n\n/** One panel a folder offers, as an app lists it. */\nexport interface PanelSummary {\n /** The panel's id, unique in the folder. */\n id: string\n /** Its tab title. */\n label: string\n /** The extension that registered it. */\n owner: string\n /** Its tab icon, when the extension gave one. */\n icon?: PanelIcon\n /** Where its side tab shows (`ExtensionPanel.scope`, `'session'` when unset). */\n scope: ExtensionPanelScope\n /** The surfaces it shows on (`ExtensionPanel.surfaces`, `['side']` when unset). */\n surfaces: readonly PanelSurface[]\n /** Its default place on the project home, when it gave one. */\n home?: PanelHomeLayout\n}\n\n/** A panel action's or a palette run's failure: the extension's own words. */\nexport interface PanelHostFailure {\n /** Always `false`: the call did not go through. */\n ok: false\n /** What the extension said went wrong. */\n error: string\n}\n\n/** What a panel's scope reads from its host. */\nexport interface PanelScopeDeps {\n /** A session's artifacts, or a project's. */\n listArtifacts: (query: { sessionId: string } | { projectRoot: string }) => Promise<SessionArtifact[]>\n /** Whether artifacts are on: off, the scope reads none. */\n artifactsEnabled: () => boolean\n /** The project a folder belongs to (its checkout's root). */\n projectRootOf: (cwd: string) => string\n}\n\n/** Where panels run: the scope's reads, and the bridge extension code reads its host from (absent: detached). */\nexport interface PanelHostDeps extends PanelScopeDeps {\n /** The bridge extension code reads its host from; absent, panels run detached. */\n hostRuntime?: ExtensionHostRuntimeBridge\n}\n\n/**\n * Summaries of a folder's panels.\n *\n * @param panels - The registry's panels.\n */\nexport function panelSummaries(panels: readonly ExtensionPanelEntry[]): PanelSummary[] {\n return panels.map(p => ({\n id: p.id,\n label: p.label,\n owner: p.owner,\n ...(p.icon ? { icon: p.icon } : {}),\n scope: p.scope ?? 'session',\n surfaces: panelSurfaces(p),\n ...(p.home ? { home: p.home } : {}),\n }))\n}\n\n/**\n * The host runtime a panel's `load` / `onAction` (or a badge action) runs in,\n * read-only: the folder's project (`projectRootOf(cwd)`), plus the session\n * when one is bound. `ctx.artifacts.list()` answers that session's artifacts\n * (`[]` unbound), `list({ scope: 'project' })` every session's under the\n * project root. Store-wide queries (`scope: 'all'`, `find`) answer `[]`;\n * `record` needs a session, so it answers `undefined` unbound. Everything\n * else reads as detached, as it does for any extension code outside a run.\n *\n * @param ctx - The bound load context.\n * @param deps - The scope's reads.\n */\nexport function panelHostRuntime(ctx: PanelLoadContextInput, deps: PanelScopeDeps): ExtensionHostRuntimeImpl {\n const { sessionId } = ctx\n const projectRoot = ctx.cwd ? deps.projectRootOf(ctx.cwd) : undefined\n const matches = (rows: SessionArtifact[], filter: { kind?: string, uri?: string, since?: number, limit?: number }): SessionArtifact[] => {\n const kept = rows.filter(a =>\n (filter.kind === undefined || a.kind === filter.kind)\n && (filter.uri === undefined || a.uri === filter.uri)\n && (filter.since === undefined || a.updatedAt >= filter.since))\n return filter.limit !== undefined ? kept.slice(0, filter.limit) : kept\n }\n return {\n model: () => null,\n thinking: () => null,\n setThinking: () => false,\n switchSession: async () => false,\n createSession: async () => false,\n appendNote: () => false,\n artifacts: () => !deps.artifactsEnabled()\n ? null\n : {\n ...(sessionId ? { sessionId } : {}),\n ...(projectRoot ? { projectRoot } : {}),\n store: {\n listArtifacts: async (filter = {}) => {\n if (filter.sessionId)\n return sessionId ? matches(await deps.listArtifacts({ sessionId }), filter) : []\n if (filter.projectRoot)\n return matches(await deps.listArtifacts({ projectRoot: filter.projectRoot }), filter)\n return []\n },\n },\n },\n }\n}\n\nfunction inPanelScope<T>(ctx: PanelLoadContextInput, deps: PanelHostDeps, run: () => Promise<T>): Promise<T> {\n return deps.hostRuntime ? deps.hostRuntime.runWith(panelHostRuntime(ctx, deps), run) : run()\n}\n\n/**\n * Runs a panel's `load()` for a context from across the boundary (known\n * string fields only, bound to `cwd`). A missing, throwing or hanging panel\n * yields an empty content naming why.\n *\n * @param panel - The panel, `undefined` when the folder no longer has it.\n * @param rawCtx - The client's context.\n * @param cwd - The folder.\n * @param deps - Where it runs.\n */\nexport async function loadExtensionPanel(panel: ExtensionPanelEntry | undefined, rawCtx: unknown, cwd: string, deps: PanelHostDeps): Promise<PanelContent> {\n if (!panel)\n return { sections: [], empty: 'This panel is no longer registered.' }\n const ctx = resolvePanelLoadContext(rawCtx, cwd)\n try {\n return normalizePanelContent(await timed(() => inPanelScope(ctx, deps, () => Promise.resolve(panel.load(ctx))), LOAD_TIMEOUT_MS))\n }\n catch (err) {\n return { sections: [], empty: `Panel failed to load: ${messageOf(err)}` }\n }\n}\n\n/**\n * Runs a panel's `onAction` as {@link loadExtensionPanel} runs its `load`.\n *\n * @param panel - The panel, `undefined` when the folder no longer has it.\n * @param actionId - The action.\n * @param payload - Its payload, as the panel's content declared it.\n * @param rawCtx - The client's context.\n * @param cwd - The folder.\n * @param deps - Where it runs.\n */\nexport async function runExtensionPanelAction(panel: ExtensionPanelEntry | undefined, actionId: string, payload: unknown, rawCtx: unknown, cwd: string, deps: PanelHostDeps): Promise<{ ok: true } | PanelHostFailure> {\n if (!panel?.onAction)\n return { ok: false, error: 'Panel has no action handler.' }\n const onAction = panel.onAction\n const ctx = resolvePanelLoadContext(rawCtx, cwd)\n try {\n await timed(() => inPanelScope(ctx, deps, () => Promise.resolve(onAction(actionId, payload as never, ctx))), ACTION_TIMEOUT_MS)\n return { ok: true }\n }\n catch (err) {\n return { ok: false, error: messageOf(err) }\n }\n}\n\n/** `onChange` at most once per {@link CHANGE_DEBOUNCE_MS}, and the timer's cancel. */\nfunction debounced(onChange: () => void): { emit: () => void, cancel: () => void } {\n let timer: ReturnType<typeof setTimeout> | null = null\n return {\n emit: () => {\n timer ??= setTimeout(() => {\n timer = null\n onChange()\n }, CHANGE_DEBOUNCE_MS)\n },\n cancel: () => {\n if (timer)\n clearTimeout(timer)\n },\n }\n}\n\n/**\n * Keeps a panel's `subscribe` on, its emits debounced into `onChange`.\n *\n * @param panel - The panel.\n * @param onChange - Called when its content changed.\n * @returns The stop, or `null` when the panel has no live updates.\n */\nexport function subscribeExtensionPanel(panel: ExtensionPanelEntry | undefined, onChange: () => void): (() => void) | null {\n if (!panel?.subscribe)\n return null\n const { emit, cancel } = debounced(onChange)\n const unsubscribe = panel.subscribe(emit)\n return () => {\n cancel()\n unsubscribe()\n }\n}\n\n/**\n * Every provider's items for `cwd`, normalised and stamped with the provider\n * id. A provider that throws or hangs contributes one disabled row naming the\n * failure, so the user sees why an expected command is missing.\n *\n * @param providers - The registry's palette providers.\n * @param cwd - The folder.\n * @param ctx - The client's palette context.\n */\nexport async function listExtensionPaletteItems(providers: readonly ExtensionPaletteProviderEntry[], cwd: string, ctx: PaletteContext): Promise<PaletteItem[]> {\n const results = await Promise.all(providers.map(async (provider) => {\n try {\n return normalizePaletteItems(await timed(() => provider.items({ ...ctx, cwd }), ITEMS_TIMEOUT_MS), provider.id, provider.group)\n }\n catch (err) {\n const failed: PaletteItem = {\n id: `${provider.id}#error`,\n title: `${provider.owner}: palette items failed`,\n description: messageOf(err),\n group: provider.group,\n source: provider.id,\n disabled: 'This extension could not list its commands.',\n }\n return [failed]\n }\n }))\n return results.flat()\n}\n\n/**\n * Runs `itemId` on its provider `source`.\n *\n * @param providers - The registry's palette providers.\n * @param source - The provider's id (`PaletteItem.source`).\n * @param itemId - The item.\n * @param cwd - The folder.\n * @param ctx - The client's palette context.\n */\nexport async function runExtensionPaletteItem(providers: readonly ExtensionPaletteProviderEntry[], source: string, itemId: string, cwd: string, ctx: PaletteContext): Promise<{ ok: true, result: PaletteRunResult } | PanelHostFailure> {\n const provider = providers.find(p => p.id === source)\n if (!provider)\n return { ok: false, error: 'This command is no longer registered.' }\n try {\n const raw = await timed(() => provider.run(itemId, { ...ctx, cwd }), ACTION_TIMEOUT_MS)\n return { ok: true, result: normalizePaletteRunResult(raw, provider.id, provider.group) }\n }\n catch (err) {\n return { ok: false, error: messageOf(err) }\n }\n}\n\n/**\n * Keeps every provider's `subscribe` on, their emits debounced into one `onChange`.\n *\n * @param providers - The registry's palette providers.\n * @param onChange - Called when items may have changed.\n * @returns The stop, or `null` when no provider has live updates.\n */\nexport function subscribeExtensionPalette(providers: readonly ExtensionPaletteProviderEntry[], onChange: () => void): (() => void) | null {\n const { emit, cancel } = debounced(onChange)\n const unsubscribes: (() => void)[] = []\n for (const provider of providers) {\n try {\n if (provider.subscribe)\n unsubscribes.push(provider.subscribe(emit))\n }\n catch {\n // A throwing subscribe just means no live updates from that provider.\n }\n }\n if (unsubscribes.length === 0)\n return null\n return () => {\n cancel()\n for (const unsubscribe of unsubscribes) {\n try {\n unsubscribe()\n }\n catch {\n // An extension's teardown error is its own problem.\n }\n }\n }\n}\n","/**\n * Prompt bridge — the host hand-off behind `ctx.submitPrompt`.\n *\n * Extensions submit prompts at any point in their lifetime; the host (the\n * TUI, post-mount) attaches the single handler that routes them into its\n * real submit machinery (run-or-queue gate, `Agent.steer`, `Agent.followUp`).\n * Same holder idiom as the host runtime bridge. Prompts are deliberately NOT\n * buffered pre-attach: silently replaying stale prompts after mount would\n * be surprising — `submit` returns `false` so callers can react.\n */\n\nexport interface ExtensionPromptDelivery {\n /**\n * `'auto'` (default) — run now when idle, join the follow-up queue when a\n * run is active. `'steer'` — inject into the CURRENT run between turns\n * (falls back to `auto` when idle). `'followUp'` — queue until the current\n * run finishes (falls back to `auto` when idle).\n */\n delivery?: 'auto' | 'steer' | 'followUp'\n}\n\n/** Connects `ctx.submitPrompt` to the host's prompt pipeline. Hosts attach their handler after the UI mounts. */\nexport interface ExtensionPromptBridge {\n /** Route a prompt to the host. `false` when no host handler is attached, the text is blank, or the handler throws. */\n submit: (text: string, opts?: ExtensionPromptDelivery) => boolean\n /** Attach the host handler (last attach wins). Returns a detach fn. */\n attach: (handler: (text: string, opts?: ExtensionPromptDelivery) => void) => () => void\n}\n\n/** Creates a bridge with no handler attached. `submit` returns `false` until a host attaches one. */\nexport function createExtensionPromptBridge(): ExtensionPromptBridge {\n let handler: ((text: string, opts?: ExtensionPromptDelivery) => void) | null = null\n return {\n submit(text, opts) {\n if (!handler || text.trim().length === 0)\n return false\n try {\n handler(text, opts)\n return true\n }\n catch {\n // The host submit path must never throw into extension code.\n return false\n }\n },\n attach(next) {\n handler = next\n return () => {\n if (handler === next)\n handler = null\n }\n },\n }\n}\n","/**\n * Extension API: contracts and registries between extensions.\n *\n * A Contract is an API one extension provides and others use. A Registry\n * is a list one extension owns and others add to. Both are tokens: they\n * carry only an id, so others can import them without the runtime code.\n */\n\nimport type { Disposable, LiveAccessor, Readable } from './core'\n\n/** Token of an API an extension provides. */\nexport interface ContractToken<T> {\n /** Always `'contract'`. */\n readonly kind: 'contract'\n /** `<extension id>.<name>`. */\n readonly id: string\n /** Type-level only. */\n readonly __type?: T\n}\n\n/** Token of a list an extension owns. */\nexport interface RegistryToken<T> {\n /** Always `'registry'`. */\n readonly kind: 'registry'\n /** `<extension id>.<name>`. */\n readonly id: string\n /** Type-level only. */\n readonly __type?: T\n}\n\n/** `ctx.contracts`. */\nexport interface ContractsDomain {\n /** Provides `token`. Its id must be the extension id or start with `<id>.`. */\n provide: <T>(token: ContractToken<T>, impl: T) => Disposable\n /** Follows a contract another extension provides. The same accessor for every call with the token. */\n use: <T>(token: ContractToken<T>) => LiveAccessor<T>\n /** Adds an item to a registry another extension (or this one) owns. */\n add: <T>(registry: RegistryToken<T>, item: T) => Disposable\n /** Every item added to a registry this extension owns, in load order. */\n list: <T>(registry: RegistryToken<T>) => Readable<readonly T[]>\n}\n\n/**\n * Declares a contract token.\n *\n * @param id - `<extension id>.<name>`.\n * @returns The token.\n */\nfunction defineContract<T>(id: string): ContractToken<T> {\n return { kind: 'contract', id }\n}\n\n/**\n * Declares a registry token.\n *\n * @param id - `<extension id>.<name>`.\n * @returns The token.\n */\nfunction defineRegistry<T>(id: string): RegistryToken<T> {\n return { kind: 'registry', id }\n}\n\n/** Helpers to declare contract tokens. */\nexport const Contract = { define: defineContract }\n/** Helpers to declare registry tokens. */\nexport const Registry = { define: defineRegistry }\n","/**\n * Subscriptions shared by the clients that asked for them (an extension\n * panel's or palette's live updates): started on the first request for a\n * key, stopped when the last owner releases it or goes away. Without the\n * count, one window closing a panel would stop the updates of another window\n * showing the same one, and a window that closed without releasing would keep\n * its subscription until the registry was rebuilt.\n */\nexport interface SharedWatches<Owner> {\n /** `start` runs once per key; it resolves to the stop function, or `null` when there is nothing to watch. */\n watch: (key: string, owner: Owner, start: () => Promise<(() => void) | null>) => Promise<void>\n /** Drops one of `owner`'s shares of `key`; the last share stops the watch. */\n unwatch: (key: string, owner: Owner) => void\n /** Every share `owner` holds (it went away). */\n release: (owner: Owner) => void\n /** Stop everything (registry rebuilt, host shutting down). */\n reset: () => void\n /** Who watches `key` now. */\n owners: (key: string) => Owner[]\n}\n\ninterface Entry<Owner> {\n owners: Map<Owner, number>\n stop: (() => void) | null\n}\n\n/** Creates an empty set of shared watches. */\nexport function createSharedWatches<Owner>(): SharedWatches<Owner> {\n const entries = new Map<string, Entry<Owner>>()\n\n const stop = (entry: Entry<Owner>): void => {\n try {\n entry.stop?.()\n }\n catch {\n // An extension's teardown error is its own problem.\n }\n }\n const drop = (key: string, entry: Entry<Owner>, owner: Owner, all: boolean): void => {\n const count = entry.owners.get(owner)\n if (count === undefined)\n return\n if (all || count <= 1)\n entry.owners.delete(owner)\n else\n entry.owners.set(owner, count - 1)\n if (entry.owners.size > 0)\n return\n entries.delete(key)\n stop(entry)\n }\n\n return {\n async watch(key, owner, start) {\n const existing = entries.get(key)\n if (existing) {\n existing.owners.set(owner, (existing.owners.get(owner) ?? 0) + 1)\n return\n }\n const entry: Entry<Owner> = { owners: new Map([[owner, 1]]), stop: null }\n entries.set(key, entry)\n const stopFn = await start().catch(() => null)\n if (entries.get(key) !== entry) {\n // Released (or reset) while starting: nobody is left to see it.\n stop({ ...entry, stop: stopFn })\n return\n }\n if (!stopFn) {\n entries.delete(key)\n return\n }\n entry.stop = stopFn\n },\n unwatch(key, owner) {\n const entry = entries.get(key)\n if (entry)\n drop(key, entry, owner, false)\n },\n release(owner) {\n for (const [key, entry] of [...entries])\n drop(key, entry, owner, true)\n },\n reset() {\n const all = [...entries.values()]\n entries.clear()\n for (const entry of all)\n stop(entry)\n },\n owners: key => [...(entries.get(key)?.owners.keys() ?? [])],\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"extensions-ADlhBQ_1.js","names":[],"sources":["../src/extensions/bundle/policy.ts","../src/extensions/bundle/entries.ts","../src/extensions/completion-providers.ts","../src/extensions/config.ts","../src/extensions/config-actions.ts","../src/extensions/provider-oauth.ts","../src/extensions/runtime/registry-view.ts","../src/extensions/register.ts","../src/extensions/runtime/reload.ts","../src/extensions/declarative/config.ts","../src/extensions/install.ts","../src/extensions/declarative/lock.ts","../src/extensions/declarative/plan.ts","../src/extensions/declarative/reconcile.ts","../src/extensions/declarative/node.ts","../src/extensions/declarative/host-sync.ts","../src/extensions/declarative/settings-layer.ts","../src/extensions/discover-and-build.ts","../src/extensions/integrations/oauth-provider-method.ts","../src/extensions/panel-host.ts","../src/extensions/prompt-bridge.ts","../src/extensions/api/contracts.ts","../src/extensions/shared-watches.ts"],"sourcesContent":["/**\n * What a `ui.tsx` entry may import. The entry runs in the desktop and web\n * renderer, next to the host's own React and zidane-ui, so those stay\n * external (the renderer hands its live modules in); everything else the\n * extension ships is bundled into the one module the renderer loads. App\n * internals, TUI-only, Electron and Node modules do not exist there: an\n * import of one fails the build with a message that says where it belongs.\n *\n * Pure: the bundler backend (`./compile-ui`) asks {@link classifyUiImport}\n * for each import, so another backend (esbuild in a Node host) reuses it.\n */\n\nimport { isBuiltin } from 'node:module'\nimport { isAbsolute, relative, resolve, sep } from 'node:path'\n\n/**\n * Bare specifiers kept external in a bundled `ui` entry: the renderer's\n * shared modules. `zidane` and `zidane/extensions` are usually imported\n * for types only (erased); a value import of them stays external and the\n * renderer must map it.\n */\nexport const UI_HOST_MODULES: readonly string[] = [\n 'react',\n 'react/jsx-runtime',\n 'react/jsx-dev-runtime',\n 'react-dom',\n 'react-dom/client',\n 'zidane-ui',\n 'zidane',\n 'zidane/extensions',\n]\n\n/** Prefixes whose every subpath is a host module (`zidane-ui/extensions/kit`, …). */\nconst HOST_MODULE_PREFIXES: readonly string[] = ['zidane-ui/', 'react-dom/']\n\n/** How the bundler treats one import of a `ui` entry. */\nexport type UiImportVerdict\n = | { kind: 'external' }\n | { kind: 'bundle' }\n | { kind: 'error', message: string }\n\n/**\n * Whether `specifier` names a module the renderer provides.\n *\n * @param specifier - The import specifier as written.\n * @param extra - More host modules the caller allows.\n */\nexport function isUiHostModule(specifier: string, extra: readonly string[] = []): boolean {\n return UI_HOST_MODULES.includes(specifier)\n || extra.includes(specifier)\n || HOST_MODULE_PREFIXES.some(prefix => specifier.startsWith(prefix))\n}\n\nfunction isInside(path: string, root: string): boolean {\n const rel = relative(root, path)\n return rel === '' || (!rel.startsWith('..') && !isAbsolute(rel))\n}\n\nfunction inNodeModules(path: string): boolean {\n return path.split(sep).includes('node_modules')\n}\n\n/**\n * Decides one import of a `ui` entry's graph.\n *\n * - Host modules ({@link UI_HOST_MODULES}) stay external.\n * - Other `zidane/*` entries, `@opentui/*`, `electron`, `bun:*` and Node\n * built-ins are errors: the renderer has none of them.\n * - A relative or absolute path from the extension's own files must stay in\n * the extension folder (app internals such as `../../src/chat` are refused).\n * Files inside `node_modules` may import what they like within their package.\n * - Everything else (local files, packages) is bundled.\n *\n * @param specifier - The import specifier as written.\n * @param importer - The real path of the importing file.\n * @param root - The real path of the extension folder.\n * @param extra - More host modules the caller allows.\n */\nexport function classifyUiImport(specifier: string, importer: string, root: string, extra: readonly string[] = []): UiImportVerdict {\n if (isUiHostModule(specifier, extra))\n return { kind: 'external' }\n const from = importer ? ` (imported by ${relative(root, importer) || importer})` : ''\n if (specifier === 'zidane' || specifier.startsWith('zidane/')) {\n return { kind: 'error', message: `\"${specifier}\"${from} is not available to a ui entry: the renderer only provides ${UI_HOST_MODULES.join(', ')} and zidane-ui/*. Reach the backend through useRpc and useStore.` }\n }\n if (specifier.startsWith('@opentui/'))\n return { kind: 'error', message: `\"${specifier}\"${from} is the terminal renderer: import it from the tui entry, not the ui entry.` }\n if (specifier === 'electron' || specifier.startsWith('electron/'))\n return { kind: 'error', message: `\"${specifier}\"${from} only exists in the desktop main process: use ctx.desktop from the extension's index.` }\n if (specifier.startsWith('bun:') || specifier.startsWith('node:') || isBuiltin(specifier))\n return { kind: 'error', message: `\"${specifier}\"${from} is a server module; the ui entry runs in a browser renderer. Move the code to the extension's index and call it through RPC.` }\n const isPath = specifier.startsWith('./') || specifier.startsWith('../') || specifier === '.' || specifier === '..' || isAbsolute(specifier)\n if (isPath && importer && !inNodeModules(importer)) {\n const target = isAbsolute(specifier) ? specifier : resolve(importer, '..', specifier)\n if (!isInside(target, root))\n return { kind: 'error', message: `\"${specifier}\"${from} resolves outside the extension folder (${target}). A ui entry bundles only the extension's own files and packages.` }\n }\n return { kind: 'bundle' }\n}\n","/**\n * Where an extension's UI entries live: `definition.ui` / `definition.tui`\n * when set, else `ui.tsx` / `tui.tsx` (or `.ts`, `.jsx`, `.js`) next to the\n * extension's index.\n */\n\nimport { existsSync } from 'node:fs'\nimport { isAbsolute, join, relative, resolve } from 'node:path'\n\n/** The files tried, in order, when the definition names no entry. */\nexport const DEFAULT_UI_ENTRY_FILES = {\n ui: ['ui.tsx', 'ui.ts', 'ui.jsx', 'ui.js'],\n tui: ['tui.tsx', 'tui.ts', 'tui.jsx', 'tui.js'],\n} as const\n\n/** What {@link resolveUiEntries} found. */\nexport interface UiEntries {\n /** Absolute path of the desktop and web entry, when there is one. */\n ui?: string\n /** Absolute path of the terminal entry, when there is one. */\n tui?: string\n /** Why a named entry was refused (outside the folder, missing). */\n errors: string[]\n}\n\n/** The definition fields that name UI entries (`ExtensionDefinition.ui` / `.tui`). */\nexport interface UiEntryFields {\n /** The desktop and web entry, relative to the extension folder. */\n ui?: unknown\n /** The terminal entry, relative to the extension folder. */\n tui?: unknown\n}\n\n/** Options of {@link resolveUiEntries}. */\nexport interface ResolveUiEntriesOptions {\n /** Whether a file exists. Default: `existsSync`. */\n exists?: (path: string) => boolean\n}\n\n/**\n * The UI entries of an extension in `dir`.\n *\n * A named entry (`definition.ui`, `definition.tui`) is resolved against\n * `dir`; it must stay inside it and exist, otherwise it is reported in\n * `errors` and left out (the default files are not tried then). Without a\n * named entry the first existing default file is used.\n *\n * @param dir - The extension folder (where its index lives).\n * @param definition - The extension definition's `ui` and `tui` fields.\n * @param options - `exists`, to check files without the disk.\n * @returns The entries found and the errors.\n * @example\n * ```ts\n * const { ui, tui, errors } = resolveUiEntries('/ext/notes', { ui: 'web/ui.tsx' })\n * ```\n */\nexport function resolveUiEntries(dir: string, definition: UiEntryFields = {}, options: ResolveUiEntriesOptions = {}): UiEntries {\n const exists = options.exists ?? existsSync\n const root = resolve(dir)\n const result: UiEntries = { errors: [] }\n for (const kind of ['ui', 'tui'] as const) {\n const named = definition[kind]\n if (named === undefined) {\n const found = DEFAULT_UI_ENTRY_FILES[kind].map(file => join(root, file)).find(path => exists(path))\n if (found)\n result[kind] = found\n continue\n }\n if (typeof named !== 'string' || named.trim() === '') {\n result.errors.push(`${kind}: must be a file path relative to the extension folder`)\n continue\n }\n const path = resolve(root, named)\n const rel = relative(root, path)\n if (rel === '' || rel.startsWith('..') || isAbsolute(rel)) {\n result.errors.push(`${kind}: \"${named}\" is outside the extension folder`)\n continue\n }\n if (!exists(path)) {\n result.errors.push(`${kind}: \"${named}\" does not exist`)\n continue\n }\n result[kind] = path\n }\n return result\n}\n","/**\n * Extension completion providers (`ctx.registerCompletionProvider`) as an app\n * runs them for its composer: the renderable set, one provider's items in a\n * wire-safe shape, and the submit hooks (`resolveReferences`, `onSubmit`).\n * The desktop app runs them over its own IPC, a host over `completions.*`.\n */\nimport type { CompletionProvider } from '../chat/completion-core'\nimport { resolveCompletionSubmit } from '../chat/completion-core'\n\n/** A provider as an app's composer lists it: its trigger opens its popup. */\nexport interface ExtensionCompletionProviderSummary {\n /** The provider's id (`completions.suggest` names it). */\n id: string\n /** One character. */\n trigger: string\n /** The popup's section title (the id when the provider names none). */\n label: string\n}\n\n/** One item of a provider's popup. */\nexport interface ExtensionCompletionItemSummary {\n /** The item's id. */\n id: string\n /** What the row shows. */\n label: string\n /** What picking it inserts (the id when the provider gives none). */\n insertText: string\n /** Short text under the label. */\n description?: string\n}\n\n/** Most items a provider's popup lists. */\nexport const MAX_COMPLETION_ITEMS = 8\n\n/** Triggers owned by the built-in file (`@`), skill (`/`), and chat (`#`) completers. */\nconst RESERVED_COMPLETION_TRIGGERS = ['@', '/', '#'] as const\n\n/**\n * The providers a composer can render: drops invalid ids / triggers / suggest\n * functions and the reserved triggers, first wins on both id and trigger.\n *\n * @param providers - The registry's providers.\n */\nexport function usableCompletionProviders(providers: readonly CompletionProvider[]): CompletionProvider[] {\n const used = new Set<string>(RESERVED_COMPLETION_TRIGGERS)\n const ids = new Set<string>()\n const out: CompletionProvider[] = []\n for (const provider of providers) {\n if (\n typeof provider.id !== 'string'\n || provider.id.trim().length === 0\n || ids.has(provider.id)\n || typeof provider.trigger !== 'string'\n || Array.from(provider.trigger).length !== 1\n || typeof provider.suggest !== 'function'\n || used.has(provider.trigger)\n ) {\n continue\n }\n ids.add(provider.id)\n used.add(provider.trigger)\n out.push(provider)\n }\n return out\n}\n\n/**\n * The usable providers as a composer lists them.\n *\n * @param providers - The registry's providers.\n */\nexport function completionProviderSummaries(providers: readonly CompletionProvider[]): ExtensionCompletionProviderSummary[] {\n return usableCompletionProviders(providers).map(provider => ({\n id: provider.id,\n trigger: provider.trigger,\n label: typeof provider.label === 'string' && provider.label.trim().length > 0 ? provider.label : provider.id,\n }))\n}\n\n/**\n * Runs one provider's `suggest` and keeps the well-formed items, at most\n * {@link MAX_COMPLETION_ITEMS}. A throwing provider or a non-array result\n * answers `[]`; `insertText` falls back to the item id.\n *\n * @param provider - The provider.\n * @param query - The text after the trigger.\n * @param context - The composer's state.\n * @param context.text - Its text.\n * @param context.cursor - The cursor's offset in it.\n * @param signal - Aborted when the query moves on.\n */\nexport async function suggestCompletionItems(\n provider: CompletionProvider,\n query: string,\n context: { text: string, cursor: number },\n signal: AbortSignal,\n): Promise<ExtensionCompletionItemSummary[]> {\n let items: unknown\n try {\n items = await provider.suggest(query, context, signal)\n }\n catch {\n return []\n }\n if (!Array.isArray(items))\n return []\n return (items as (Record<string, unknown> | null)[])\n .filter((item): item is Record<string, unknown> & { id: string, label: string } =>\n !!item && typeof item.id === 'string' && typeof item.label === 'string')\n .slice(0, MAX_COMPLETION_ITEMS)\n .map(item => ({\n id: item.id,\n label: item.label,\n insertText: typeof item.insertText === 'string' ? item.insertText : item.id,\n ...(typeof item.description === 'string' ? { description: item.description } : {}),\n }))\n}\n\n/**\n * Runs the submit hooks of the usable providers that declare one, with the\n * same reference collection as the terminal app (`resolveCompletionSubmit`).\n *\n * @param providers - The registry's providers.\n * @param text - The submitted text.\n * @param cursor - The cursor at submit.\n * @param signal - Aborts the hooks.\n */\nexport async function resolveExtensionCompletionSubmit(\n providers: readonly CompletionProvider[],\n text: string,\n cursor: number,\n signal: AbortSignal,\n): Promise<void> {\n const usable = usableCompletionProviders(providers).filter(\n provider => typeof provider.resolveReferences === 'function' || typeof provider.onSubmit === 'function',\n )\n if (usable.length > 0)\n await resolveCompletionSubmit(text, usable, { cursor, signal })\n}\n\n/** How long a provider's `suggest`, or the submit hooks, may run before the answer is given up. */\nexport const COMPLETION_TIMEOUT_MS = 5_000\n\n/** Runs completion work for a composer: each bounded in time, a newer suggest for the same key aborting the older one. */\nexport interface CompletionRunner {\n /** The items of `provider` for `query`; `[]` once a newer suggest for `key` started or the time is up. */\n suggest: (key: string, provider: CompletionProvider, query: string, context: { text: string, cursor: number }) => Promise<ExtensionCompletionItemSummary[]>\n /** The submit hooks ({@link resolveExtensionCompletionSubmit}); resolves once they ran or the time is up. */\n submit: (providers: readonly CompletionProvider[], text: string, cursor: number) => Promise<void>\n}\n\n/**\n * Creates a {@link CompletionRunner}. A provider that ignores its signal can't\n * hold the answer past `timeoutMs`.\n *\n * @param timeoutMs - The bound of each call. Default {@link COMPLETION_TIMEOUT_MS}.\n */\nexport function createCompletionRunner(timeoutMs = COMPLETION_TIMEOUT_MS): CompletionRunner {\n const suggests = new Map<string, AbortController>()\n const bounded = async <T>(controller: AbortController, run: (signal: AbortSignal) => Promise<T>, fallback: T): Promise<T> => {\n const timer = setTimeout(() => controller.abort(), timeoutMs)\n try {\n return await Promise.race([\n run(controller.signal),\n new Promise<T>(resolve => controller.signal.addEventListener('abort', () => resolve(fallback), { once: true })),\n ])\n }\n finally {\n clearTimeout(timer)\n }\n }\n return {\n async suggest(key, provider, query, context) {\n suggests.get(key)?.abort()\n const controller = new AbortController()\n suggests.set(key, controller)\n try {\n return await bounded(controller, signal => suggestCompletionItems(provider, query, context, signal), [])\n }\n finally {\n if (suggests.get(key) === controller)\n suggests.delete(key)\n }\n },\n submit: (providers, text, cursor) =>\n bounded(new AbortController(), signal => resolveExtensionCompletionSubmit(providers, text, cursor, signal), undefined),\n }\n}\n","/**\n * Typed, extension-contributed configuration.\n *\n * Extensions declare config CATEGORIES and typed config ITEMS during\n * `setup(ctx)` via `ctx.registerConfigCategory` / `ctx.registerConfigItem`.\n * Values are persisted in the user's `Settings.extensionConfig` bag\n * (`extName → itemKey → value`) and read back — default-first, with\n * graceful degradation on missing / malformed values — through a single\n * resolver ({@link resolveExtensionConfigValue}). The same resolver\n * powers `ctx.config.get(key)` inside the extension (hooks / tools) and\n * both Settings UIs (TUI + GUI).\n *\n * Design intent:\n * - **One chokepoint for graceful degradation.** Every read — host,\n * extension, TUI render, GUI render — funnels through\n * {@link resolveExtensionConfigValue}; a value that's missing, the\n * wrong type, out of range, off the enum, or failing the author's\n * `validate` collapses to the item's `default`. The UI therefore\n * never has to special-case a broken `state.json` / DB row.\n * - **Namespacing by extension.** Items are keyed `extName → itemKey`\n * so two extensions can both ship a `verbose` knob without colliding.\n * Categories are a flat global registry (an extension may add items\n * to another extension's category, or to its own implicit category\n * whose id is the extension name).\n * - **Wire-safe schema.** The optional main-side `validate` callback is\n * the only non-serializable field; {@link toWireConfigSchema} drops it\n * so the schema crosses an IPC boundary (the GUI) cleanly.\n */\n\nimport type { Settings } from '../chat/types'\nimport type { ExtensionRegistry } from './types'\n\n// ---------------------------------------------------------------------------\n// Schema types\n// ---------------------------------------------------------------------------\n\n/** Concrete value a config item can hold. */\nexport type ExtensionConfigValue = boolean | number | string\n\n/** Where a config value should be persisted. */\nexport type ExtensionConfigScope = 'user' | 'project' | 'session'\n/** How a host applies a changed config value: read live, rebuild the agent, or restart. */\nexport type ExtensionConfigChangeBehavior = 'live' | 'agent-rebuild' | 'restart'\n\n/** Fields shared by every config-item variant. */\nexport interface ExtensionConfigItemBase {\n /**\n * Stable key, unique within the declaring extension. Used as the\n * persistence key (`extensionConfig[extName][key]`) and the\n * `ctx.config.get(key)` lookup — pick a stable identifier.\n */\n key: string\n /** Short display label rendered in the Settings UIs. */\n label: string\n /** Longer one-line gloss shown under the label. */\n description?: string\n /**\n * Optional main-side validator, run at READ time AFTER the built-in\n * type / range / enum / pattern checks (both must pass). Throwing is\n * treated as \"invalid\" — the read degrades to the item's `default`. It\n * is **never invoked at registration** (declaring an item has no side\n * effects) and is **never serialized over IPC** ({@link toWireConfigSchema}\n * strips it), so it only runs in-process (TUI host + extension reads);\n * the GUI renderer is optimistic and relies on the authoritative core read.\n */\n validate?: (v: unknown) => boolean\n /**\n * Desired persistence scope. Current stores still persist through the\n * existing per-extension settings bag unless a host implements scoped writes;\n * this metadata lets UIs and future stores present the right ownership.\n */\n scope?: ExtensionConfigScope\n /** Whether changing this value requires rebuilding runtime objects. */\n requiresRestart?: boolean\n /** How hosts should apply a changed value. Defaults to live reads through `ctx.config.get`. */\n onChange?: ExtensionConfigChangeBehavior\n}\n\n/** A boolean config item — rendered as a toggle. */\nexport interface ExtensionConfigBooleanItem extends ExtensionConfigItemBase {\n /** Discriminant for a boolean item. */\n type: 'boolean'\n /** Value used until the user sets one. */\n default: boolean\n}\n\n/**\n * A numeric config item — rendered as a free input row, clamped to `[min, max]`\n * and snapped to `step`. The `default` must itself lie within `[min, max]` or\n * the item is rejected at registration.\n */\nexport interface ExtensionConfigNumberItem extends ExtensionConfigItemBase {\n /** Discriminant for a number item. */\n type: 'number'\n /** Value used until the user sets one. Must lie within `[min, max]`. */\n default: number\n /** Smallest accepted value. */\n min?: number\n /** Largest accepted value. */\n max?: number\n /** Increment values snap to. */\n step?: number\n}\n\n/** A string config item — rendered as a free input row (optionally `multiline`), validated against `pattern`. */\nexport interface ExtensionConfigStringItem extends ExtensionConfigItemBase {\n /** Discriminant for a string item. */\n type: 'string'\n /** Value used until the user sets one. */\n default: string\n /**\n * Anchored or unanchored JS-regex source gating user-entered values at read\n * time. An invalid pattern is ignored (treated as \"no constraint\"). The\n * pattern is intentionally NOT applied to the `default`, so an empty / unset\n * default (`default: ''`) for an optional patterned field is valid.\n */\n pattern?: string\n /** Renders a multi-line editor instead of a single-line input. */\n multiline?: boolean\n /**\n * Treat the value as a credential: Settings UIs render it masked\n * (`••••••••`, last 4 characters kept for recognition when the value is\n * longer than 8) and seed the editor\n * EMPTY rather than with the stored value, so the secret never appears on\n * screen or in a screen share.\n *\n * Presentation only — the value still lives in the plain settings bag, so\n * this is for \"don't shoulder-surf my service token\", not for secrets that\n * warrant the credential store. Ignored for `multiline` items.\n */\n secret?: boolean\n}\n\n/**\n * An enum config item — rendered as a cycling choice row. The `default` must be\n * one of the `options` values or the item is rejected at registration.\n */\nexport interface ExtensionConfigEnumItem extends ExtensionConfigItemBase {\n /** Discriminant for an enum item. */\n type: 'enum'\n /** Value used until the user picks one. Must be one of `options`. */\n default: string\n /** Choices the user can pick from. */\n options: readonly { value: string, label: string }[]\n}\n\n/**\n * A model-id config item — rendered as an inline searchable picker over the\n * host's credentialed model catalog (the same interaction grammar as the\n * ctrl+m cross-provider picker: type to filter, `↵` picks — or toggles, in\n * `multi` mode, where `esc` applies the selection).\n *\n * The persisted value is a plain model id, or a comma-separated id list\n * when `multi` — a string either way, so {@link ExtensionConfigValue} and\n * every settings store stay unchanged, and hosts without a catalog\n * (headless, no authed providers) degrade to the free string input.\n * Deliberately catalog-UNvalidated at read time: a stored id whose\n * provider is temporarily unauthed must survive, not silently reset to\n * the default — catalog validation is the consuming extension's call.\n */\nexport interface ExtensionConfigModelItem extends ExtensionConfigItemBase {\n /** Discriminant for a model item. */\n type: 'model'\n /** Value used until the user picks one: a model id, or a comma-separated list when `multi`. */\n default: string\n /** Allow picking MORE than one model (comma-separated persisted value). */\n multi?: boolean\n}\n\n/**\n * What a config ACTION reports back to the host after running. Actions\n * cannot write settings directly — there is deliberately no `config.set`\n * surface for extensions — so a successful run RETURNS the values it wants\n * persisted and the host writes them through its own validated settings\n * path ({@link sanitizeExtensionConfigActionPatch} gates the patch).\n */\nexport interface ExtensionConfigActionResult {\n /** One-line feedback shown in the Settings UI (e.g. \"proxy running at …\"). */\n message?: string\n /**\n * Config values of the DECLARING extension to persist on success, keyed\n * by item key. Entries naming unknown keys, action items, or values that\n * fail the item's schema are dropped (not errors) — a buggy action can\n * degrade but never corrupt the settings bag.\n */\n config?: Record<string, ExtensionConfigValue>\n}\n\n/**\n * An imperative config item — rendered as a \"press ↵ to run\" row instead\n * of a value editor. `run` executes in the extension's own process (it is\n * never serialized — {@link toWireConfigSchema} omits action items\n * entirely), so it can close over the extension's `setup(ctx)` scope.\n *\n * Contract for `run`:\n * - Resolve with an {@link ExtensionConfigActionResult} (or `void`) on\n * success — `message` becomes the row's feedback line, `config`\n * values are persisted by the host.\n * - Throw / reject on failure — the error message is shown on the row.\n * - Bound your own runtime: the host serializes actions (one in flight\n * per modal) but imposes no timeout, so a hanging `run` holds the\n * \"running…\" state until it settles.\n *\n * Actions hold no persisted value: `ctx.config.get(key)` returns\n * `undefined` for an action key and the resolver never yields a value.\n */\nexport interface ExtensionConfigActionItem extends Pick<ExtensionConfigItemBase, 'key' | 'label' | 'description'> {\n /** Discriminant for an action item. */\n type: 'action'\n /** Runs the action. May return values to persist. Throwing shows the error on the row. */\n run: () => ExtensionConfigActionResult | void | Promise<ExtensionConfigActionResult | void>\n /**\n * Optional passive probe — called by the host when the settings panel\n * surfaces the row (and re-called after any action of the panel\n * settles), so the row can show live state (\"running at …\") WITHOUT\n * the user pressing ↵. Contract:\n *\n * - Resolve an {@link ExtensionConfigActionStatus} to show it, or\n * `undefined` for \"no status\" (e.g. the probed tool isn't\n * installed — stay quiet rather than nag).\n * - Throwing is treated as `undefined` — probes must be safe to call\n * at any time and MUST NOT mutate anything.\n * - Be fast: the TUI caps each probe at 3 seconds and discards\n * late results.\n */\n status?: () => ExtensionConfigActionStatus | undefined | Promise<ExtensionConfigActionStatus | undefined>\n}\n\n/**\n * Result of an action's passive `status` probe. `state` drives the row\n * color (`ok` accent / `off` mute / `error` error); `message` is the\n * one-line text rendered in the row's value slot.\n */\nexport interface ExtensionConfigActionStatus {\n /** Row state: `ok`, `off` or `error`. */\n state: 'ok' | 'off' | 'error'\n /** One-line text shown in the row's value slot. */\n message: string\n}\n\n/**\n * The value-holding config items — everything except `action`. Functions\n * that produce or validate persisted VALUES take this narrower union;\n * {@link ExtensionConfigItem} is the full declarable set.\n */\nexport type ExtensionConfigValueItem\n = | ExtensionConfigBooleanItem\n | ExtensionConfigNumberItem\n | ExtensionConfigStringItem\n | ExtensionConfigEnumItem\n | ExtensionConfigModelItem\n\n/**\n * Discriminated union of the typed config items an extension can declare.\n * The `type` tag drives both validation ({@link resolveExtensionConfigValue})\n * and rendering (toggle / choice / input / action row).\n */\nexport type ExtensionConfigItem = ExtensionConfigValueItem | ExtensionConfigActionItem\n\n/**\n * A config category — a labelled grouping the Settings UIs render as a\n * sub-header. Declared via `ctx.registerConfigCategory`. An item that\n * names no category lands in its extension's implicit category (id =\n * extension name); register a category with that id to give the implicit\n * grouping a friendlier label.\n */\nexport interface ExtensionConfigCategory {\n /** Category id. */\n id: string\n /** Sub-header text. */\n label: string\n /** One-line gloss shown under the label. */\n description?: string\n}\n\n/**\n * A config item as STORED on the registry / contributions — the authored\n * item plus the resolved `category` id it belongs to. The owning\n * extension is implied by the namespacing key on\n * {@link ExtensionRegistry.configItems}.\n */\nexport type StoredExtensionConfigItem = ExtensionConfigItem & { category: string }\n\n/** The `ctx.config` surface handed to extensions for reading their own config. */\nexport interface ExtensionConfigSurface {\n /**\n * Read the current value of one of THIS extension's config items,\n * default-first. Returns the persisted value when present + valid, the\n * item's `default` when missing / malformed, or `undefined` when `key`\n * was never registered via `ctx.registerConfigItem`.\n *\n * Reads through a host-supplied live settings getter: during `setup`\n * (before the host wires live settings) it returns the default (or the\n * boot snapshot); inside hooks / tools (post-boot) it returns the live\n * value.\n */\n get: (key: string) => ExtensionConfigValue | undefined\n}\n\n// ---------------------------------------------------------------------------\n// Authored-schema validation (registration-time guard)\n// ---------------------------------------------------------------------------\n\n/**\n * Exhaustiveness guard for the `ExtensionConfigItem` union: a future item\n * `type` left unhandled is a COMPILE error (the `never` parameter), while at\n * runtime an unrecognized / missing type is treated as invalid (`false`) —\n * malformed items reach here via `as never` casts from untyped `.js` extensions.\n */\nfunction unreachableInvalidItem(_item: never): false {\n return false\n}\n\n/**\n * Whether an authored item is well-formed for its declared `type` — used\n * by `ctx.registerConfigItem` to drop malformed declarations (wrong /\n * missing `default`, an `enum` without `options`) before they reach the\n * registry. Cheaper than letting a broken item ride to render time.\n *\n * @param item - Item declared by an extension.\n */\nexport function isValidExtensionConfigItem(item: ExtensionConfigItem): boolean {\n switch (item.type) {\n case 'boolean':\n return typeof item.default === 'boolean'\n case 'number':\n // The default must be finite AND within the declared range, so the\n // resolver never surfaces an out-of-range value (the module's \"every read\n // yields a valid value\" invariant). `step` is a UI affordance, not a hard\n // constraint, so it is NOT enforced on the default.\n return typeof item.default === 'number'\n && Number.isFinite(item.default)\n && (item.min === undefined || item.default >= item.min)\n && (item.max === undefined || item.default <= item.max)\n case 'string':\n // A string `pattern` is intentionally NOT enforced against the default:\n // an empty / unset default (`default: ''`) for an optional patterned\n // field is a legitimate idiom. The pattern still gates user-entered\n // values at read time via `resolveExtensionConfigValue`. The author\n // `validate` is likewise deferred to read time, so registration stays\n // side-effect-free (no `validate(default)` call at register time).\n return typeof item.default === 'string'\n case 'enum':\n // The default MUST be one of the options — otherwise the picker can't\n // represent it and the resolver would surface an off-list value.\n return typeof item.default === 'string'\n && Array.isArray(item.options)\n && item.options.length > 0\n && item.options.every(o => o && typeof o.value === 'string' && typeof o.label === 'string')\n && item.options.some(o => o.value === item.default)\n case 'model':\n // Ids are free-form strings (catalogs are host- and auth-dependent),\n // so only the shape is checked — see the type's docstring for why\n // values are never catalog-validated.\n return typeof item.default === 'string'\n case 'action':\n // No `default` — requires a callable `run`; `status` is optional\n // but must be callable when present.\n return typeof item.run === 'function'\n && (item.status === undefined || typeof item.status === 'function')\n default:\n return unreachableInvalidItem(item)\n }\n}\n\n// ---------------------------------------------------------------------------\n// Validation + resolution — the single graceful-degradation chokepoint\n// ---------------------------------------------------------------------------\n\n/** Build a RegExp from `pattern`, returning `null` when the source is invalid. */\nfunction safeRegExp(pattern: string): RegExp | null {\n try {\n return new RegExp(pattern)\n }\n catch {\n return null\n }\n}\n\n/**\n * Whether `value` is a valid concrete value for `item` — type match plus\n * the item's constraints (number range, enum membership, string pattern)\n * and the optional author `validate`. `step` is intentionally NOT enforced\n * here (it's a UI affordance, not a hard constraint — a persisted value or\n * default that doesn't align to the step is still honored).\n *\n * @param item - Item that defines the type and constraints.\n * @param value - Candidate value.\n */\nexport function isValidExtensionConfigValue(item: ExtensionConfigItem, value: unknown): value is ExtensionConfigValue {\n switch (item.type) {\n case 'boolean':\n if (typeof value !== 'boolean')\n return false\n break\n case 'number':\n if (typeof value !== 'number' || !Number.isFinite(value))\n return false\n if (item.min !== undefined && value < item.min)\n return false\n if (item.max !== undefined && value > item.max)\n return false\n break\n case 'string': {\n if (typeof value !== 'string')\n return false\n if (item.pattern) {\n const re = safeRegExp(item.pattern)\n // A broken author pattern is treated as \"no constraint\" rather\n // than rejecting every value the user types.\n if (re && !re.test(value))\n return false\n }\n break\n }\n case 'enum':\n if (typeof value !== 'string' || !item.options.some(o => o.value === value))\n return false\n break\n case 'model':\n if (typeof value !== 'string')\n return false\n break\n case 'action':\n // Actions hold no persisted value — nothing is ever valid for them.\n return false\n default:\n return unreachableInvalidItem(item)\n }\n if (item.validate) {\n try {\n return item.validate(value)\n }\n catch {\n return false\n }\n }\n return true\n}\n\n/**\n * Resolve the effective value of a config item from its persisted value.\n * THE single place graceful degradation lives: a `persisted` that's\n * `undefined` (never set) OR fails {@link isValidExtensionConfigValue}\n * collapses to `item.default`. Action items hold no value and resolve to\n * `undefined` — the overloads keep value-item call sites exact.\n *\n * @param item - Item that defines the type and constraints.\n * @param persisted - Stored value, if any.\n */\nexport function resolveExtensionConfigValue(\n item: ExtensionConfigValueItem,\n persisted: unknown,\n): ExtensionConfigValue\nexport function resolveExtensionConfigValue(\n item: ExtensionConfigItem,\n persisted: unknown,\n): ExtensionConfigValue | undefined\nexport function resolveExtensionConfigValue(\n item: ExtensionConfigItem,\n persisted: unknown,\n): ExtensionConfigValue | undefined {\n if (item.type === 'action')\n return undefined\n if (persisted === undefined)\n return item.default\n if (!isValidExtensionConfigValue(item, persisted))\n return item.default\n return persisted\n}\n\n/**\n * Clamp a number to the item's `[min, max]` and snap to `step` (when set).\n * Used by the input-row commit paths so a user-typed value is coerced into\n * range before it's persisted.\n *\n * @param item - Number item that supplies `min`, `max` and `step`.\n * @param n - Value to clamp.\n */\nexport function clampExtensionConfigNumber(item: ExtensionConfigNumberItem, n: number): number {\n let v = n\n if (item.min !== undefined)\n v = Math.max(item.min, v)\n if (item.max !== undefined)\n v = Math.min(item.max, v)\n if (item.step !== undefined && item.step > 0) {\n const base = item.min ?? 0\n v = base + Math.round((v - base) / item.step) * item.step\n // Snapping can nudge a boundary value out of range — re-clamp.\n if (item.max !== undefined)\n v = Math.min(item.max, v)\n if (item.min !== undefined)\n v = Math.max(item.min, v)\n }\n return v\n}\n\n/**\n * Coerce a raw input string (from a free number / string input row) into a\n * valid persisted value, or `undefined` when it can't be made valid.\n * Numbers are parsed + clamped; strings are taken verbatim and checked\n * against the pattern; enum / boolean items aren't edited via free input\n * (they use choice / toggle rows) so they return `undefined` here.\n *\n * @param item - Item the input belongs to.\n * @param raw - Text the user typed.\n */\nexport function coerceExtensionConfigInput(\n item: ExtensionConfigItem,\n raw: string,\n): ExtensionConfigValue | undefined {\n switch (item.type) {\n case 'number': {\n const n = Number(raw.trim())\n if (!Number.isFinite(n))\n return undefined\n const clamped = clampExtensionConfigNumber(item, n)\n return isValidExtensionConfigValue(item, clamped) ? clamped : undefined\n }\n case 'string':\n return isValidExtensionConfigValue(item, raw) ? raw : undefined\n case 'model':\n // Fallback path for hosts without a catalog — the value is typed as\n // free text (a comma-separated id list when `multi`).\n return isValidExtensionConfigValue(item, raw) ? raw : undefined\n default:\n // Enum / boolean use choice / toggle rows; actions have no value.\n return undefined\n }\n}\n\n/**\n * Convenience read against a merged {@link ExtensionRegistry} + the user's\n * `Settings`. Looks up the item schema (`extName → key`), reads the\n * persisted value out of `settings.extensionConfig`, and runs it through\n * {@link resolveExtensionConfigValue}. Returns `undefined` only when the\n * `(extName, key)` pair names no registered item.\n *\n * @param registry - Merged registry holding the declared items.\n * @param settings - User settings holding the persisted values.\n * @param extName - Name of the declaring extension.\n * @param key - Item key.\n */\nexport function resolveExtensionConfig(\n registry: Pick<ExtensionRegistry, 'configItems'>,\n settings: Pick<Settings, 'extensionConfig'> | undefined,\n extName: string,\n key: string,\n): ExtensionConfigValue | undefined {\n const item = registry.configItems[extName]?.[key]\n if (!item)\n return undefined\n return resolveExtensionConfigValue(item, settings?.extensionConfig?.[extName]?.[key])\n}\n\n/**\n * Gate the `config` patch an action returned before the host persists it.\n * Per-entry, an item is accepted only when it names a registered VALUE\n * item of the declaring extension and passes that item's schema\n * ({@link isValidExtensionConfigValue}); everything else lands in\n * `rejected` for logging. Pure — the host applies `accepted` through its\n * own settings write path.\n *\n * @param items - Declared items of the extension, keyed by item key.\n * @param patch - Values the action returned.\n */\nexport function sanitizeExtensionConfigActionPatch(\n items: Readonly<Record<string, StoredExtensionConfigItem>> | undefined,\n patch: Readonly<Record<string, ExtensionConfigValue>> | undefined,\n): { accepted: Record<string, ExtensionConfigValue>, rejected: string[] } {\n const accepted: Record<string, ExtensionConfigValue> = {}\n const rejected: string[] = []\n if (!patch || typeof patch !== 'object')\n return { accepted, rejected }\n for (const [key, value] of Object.entries(patch)) {\n const item = items?.[key]\n if (!item || item.type === 'action' || !isValidExtensionConfigValue(item, value)) {\n rejected.push(key)\n continue\n }\n accepted[key] = value\n }\n return { accepted, rejected }\n}\n\n// ---------------------------------------------------------------------------\n// Wire-safe serialization (GUI IPC)\n// ---------------------------------------------------------------------------\n\n/** Fields the wire shape adds on top of the authored item (minus `validate`). */\ninterface WireConfigExtras {\n category: string\n extension: string\n}\n\n/** A config item flattened for the wire — carries `category` + `extension`, drops `validate`. */\nexport type WireExtensionConfigItem\n = | (Omit<ExtensionConfigBooleanItem, 'validate'> & WireConfigExtras)\n | (Omit<ExtensionConfigNumberItem, 'validate'> & WireConfigExtras)\n | (Omit<ExtensionConfigStringItem, 'validate'> & WireConfigExtras)\n | (Omit<ExtensionConfigEnumItem, 'validate'> & WireConfigExtras)\n | (Omit<ExtensionConfigModelItem, 'validate'> & WireConfigExtras)\n\n/** The full extension-config schema in IPC-safe form. */\nexport interface WireExtensionConfigSchema {\n /** Declared categories. */\n categories: readonly ExtensionConfigCategory[]\n /** Declared items, each tagged with its extension and category. */\n items: readonly WireExtensionConfigItem[]\n}\n\n/**\n * Project the merged registry's config schema into a wire-safe shape:\n * categories as a flat array, items flattened to a single list carrying\n * their `extension` + `category`, with the non-serializable `validate`\n * callback stripped. Action items are omitted entirely — their `run`\n * callback only exists in the main process, so a remote renderer (the\n * GUI) has nothing it could do with the row. Pure — factored out so its\n * serialization is unit testable without an Electron / IPC harness.\n *\n * @param registry - Merged registry holding the declared categories and items.\n */\nexport function toWireConfigSchema(\n registry: Pick<ExtensionRegistry, 'configCategories' | 'configItems'>,\n): WireExtensionConfigSchema {\n const items: WireExtensionConfigItem[] = []\n for (const [extension, byKey] of Object.entries(registry.configItems)) {\n for (const stored of Object.values(byKey)) {\n if (stored.type === 'action')\n continue\n // Drop the main-only `validate` callback; keep everything else.\n const { validate: _validate, ...rest } = stored\n items.push({ ...rest, extension } as WireExtensionConfigItem)\n }\n }\n return {\n categories: Object.values(registry.configCategories),\n items,\n }\n}\n","/**\n * Extension config actions (`registerConfigItem` type `'action'`) as an app's\n * Settings lists and runs them: the rows, their passive `status()` probes and\n * a run, with the terminal app's wording. The callbacks stay on the host; the\n * desktop app calls these over its IPC, a host over `extensions.*`.\n */\nimport type { ExtensionConfigActionStatus, ExtensionConfigCategory, ExtensionConfigValue, StoredExtensionConfigItem } from './config'\nimport { sanitizeExtensionConfigActionPatch } from './config'\n\ntype StoredItems = Readonly<Record<string, Readonly<Record<string, StoredExtensionConfigItem>>>>\n\n/** An action row, without its callbacks. */\nexport interface ExtensionActionSummary {\n /** The declaring extension. */\n extension: string\n /** The action's key, unique in its extension. */\n key: string\n /** The row's name. */\n label: string\n /** What it does. */\n description?: string\n /** The config category it sits in. */\n category: string\n /** That category's name. */\n categoryLabel: string\n /** The action declares a passive `status()` probe. */\n hasStatus: boolean\n}\n\n/** What running an action did. */\nexport interface ExtensionActionRunResult {\n /** `result.message`, else `updated <keys>`, else `done`, with `(ignored invalid: …)` when keys were dropped. */\n message: string\n /** The accepted config patch (sanitized against the extension's schema); the app persists it. */\n config?: Record<string, ExtensionConfigValue>\n}\n\n/**\n * The action rows: the counterpart of `toWireConfigSchema`, which strips them.\n *\n * @param categories - The registry's config categories.\n * @param items - The registry's config items, per extension.\n */\nexport function listActionSummaries(\n categories: Readonly<Record<string, ExtensionConfigCategory>>,\n items: StoredItems,\n): ExtensionActionSummary[] {\n const out: ExtensionActionSummary[] = []\n for (const [extension, byKey] of Object.entries(items)) {\n for (const item of Object.values(byKey)) {\n if (item.type !== 'action')\n continue\n out.push({\n extension,\n key: item.key,\n label: item.label,\n ...(item.description !== undefined ? { description: item.description } : {}),\n category: item.category,\n categoryLabel: categories[item.category]?.label ?? item.category,\n hasStatus: typeof item.status === 'function',\n })\n }\n }\n return out.sort((a, b) => a.extension.localeCompare(b.extension) || a.label.localeCompare(b.label))\n}\n\n/** Per-probe cap: a hung `status()` must not hold the rows. */\nconst ACTION_PROBE_TIMEOUT_MS = 3_000\n\n/**\n * Every action's passive `status()`, keyed `extension:key`. A probe that\n * throws, times out or answers no message is left out.\n *\n * @param items - The registry's config items, per extension.\n */\nexport async function probeActionStatuses(items: StoredItems): Promise<Record<string, ExtensionConfigActionStatus>> {\n const out: Record<string, ExtensionConfigActionStatus> = {}\n const probes: Promise<void>[] = []\n for (const [extension, byKey] of Object.entries(items)) {\n for (const item of Object.values(byKey)) {\n if (item.type !== 'action' || typeof item.status !== 'function')\n continue\n const probe = item.status\n probes.push((async () => {\n let timer: ReturnType<typeof setTimeout> | undefined\n try {\n const status = await Promise.race([\n Promise.resolve(probe()),\n new Promise<undefined>((resolve) => {\n timer = setTimeout(resolve, ACTION_PROBE_TIMEOUT_MS, undefined)\n }),\n ])\n if (status && typeof status.message === 'string')\n out[`${extension}:${item.key}`] = { state: status.state, message: status.message }\n }\n catch {\n // A throwing probe means \"no status\".\n }\n finally {\n clearTimeout(timer)\n }\n })())\n }\n }\n await Promise.all(probes)\n return out\n}\n\n/**\n * Runs one action. The config patch it returns is sanitized (unknown keys and\n * values failing the schema are dropped) and returned, not written: the app\n * persists it through its settings writer.\n *\n * @param items - The registry's config items, per extension.\n * @param extensionName - The declaring extension.\n * @param actionId - The action's key.\n */\nexport async function runExtensionAction(\n items: StoredItems,\n extensionName: string,\n actionId: string,\n): Promise<ExtensionActionRunResult> {\n const item = items[extensionName]?.[actionId]\n if (!item || item.type !== 'action')\n throw new Error(`\"${extensionName}\" has no action \"${actionId}\".`)\n const result = (await item.run()) ?? undefined\n const { accepted, rejected } = sanitizeExtensionConfigActionPatch(items[extensionName], result?.config)\n const acceptedKeys = Object.keys(accepted)\n const parts = [result?.message || (acceptedKeys.length > 0 ? `updated ${acceptedKeys.join(', ')}` : 'done')]\n if (rejected.length > 0)\n parts.push(`(ignored invalid: ${rejected.join(', ')})`)\n return { message: parts.join(' '), ...(acceptedKeys.length > 0 ? { config: accepted } : {}) }\n}\n","/**\n * A provider's OAuth flow rides its provider contribution.\n *\n * `ctx.registerProvider(descriptor)` with a `descriptor.oauthProvider` is all\n * an extension declares. When the registry builds, the flow joins the\n * process-wide OAuth registry (`providers/oauth-registry`) that lazy token\n * refresh and usage probes resolve through; when the registry disposes, it\n * leaves. Registering the flow from `setup` instead would run even while the\n * extension is disabled, with nothing to undo it.\n *\n * - Active extensions only. A disabled extension's descriptor is dropped\n * with the rest of its contributions, and its flow with it.\n * - Built-in flow ids (`anthropic`, `openai-codex`, …) are refused: the\n * user's own subscription tokens never refresh through extension code.\n * - Claims are counted per flow object. A host handing the same inline\n * definition to several live registries (or building the next one before\n * disposing the last) keeps the flow until the last claim goes; a reload\n * that re-imports the extension registers a NEW object, which an older\n * registry's release can't remove.\n *\n * `descriptor.oauthProvider` is read once, when the registry builds.\n */\n\nimport type { LogSink } from '../logger'\nimport type { OAuthProviderInterface } from '../providers/oauth-registry'\nimport type { LoadedExtension } from './types'\nimport { createLogger } from '../logger'\nimport { BUILTIN_OAUTH_PROVIDER_IDS, getOAuthProvider, registerOAuthProvider, unregisterOAuthProvider } from '../providers/oauth-registry'\n\n/** Process-wide, like the registry itself: every zidane copy counts the same claims. */\nconst CLAIMS_SLOT = Symbol.for('zidane.extension-oauth-claims')\n\nfunction claims(): WeakMap<object, number> {\n const slots = globalThis as { [key: symbol]: WeakMap<object, number> | undefined }\n slots[CLAIMS_SLOT] ??= new WeakMap()\n return slots[CLAIMS_SLOT]\n}\n\nfunction isFlow(value: unknown): value is OAuthProviderInterface {\n const flow = value as Partial<OAuthProviderInterface> | null\n return !!flow\n && typeof flow.id === 'string'\n && flow.id.length > 0\n && typeof flow.login === 'function'\n && typeof flow.refreshToken === 'function'\n && typeof flow.getApiKey === 'function'\n}\n\n/**\n * Register the OAuth flows of the active extensions' providers.\n *\n * @param active - Extensions whose contributions are live.\n * @param sink - Log sink for the per-extension warnings.\n * @returns Releases this registry's claims. Idempotent.\n */\nexport function claimProviderOAuthFlows(active: readonly LoadedExtension[], sink: LogSink): () => void {\n const claimed: OAuthProviderInterface[] = []\n for (const entry of active) {\n const providers = entry.contributions?.providers\n if (!providers)\n continue\n const logger = createLogger(sink, { extension: entry.name })\n for (const descriptor of Object.values(providers)) {\n const flow: unknown = descriptor.oauthProvider\n if (flow === undefined)\n continue\n if (!isFlow(flow)) {\n logger.warn('registerProvider: oauthProvider needs an id, login, refreshToken and getApiKey; its sign-in won\\'t refresh', { provider: descriptor.key })\n continue\n }\n if (BUILTIN_OAUTH_PROVIDER_IDS.has(flow.id)) {\n if (getOAuthProvider(flow.id) !== flow)\n logger.warn(`registerProvider: OAuth flow id \"${flow.id}\" belongs to a built-in sign-in; refresh keeps using the built-in flow`, { provider: descriptor.key })\n continue\n }\n const credentialKey = descriptor.credentialFileKey ?? descriptor.key\n if (flow.id !== credentialKey)\n logger.warn(`registerProvider: OAuth flow id \"${flow.id}\" differs from the credential key \"${credentialKey}\"; usage probes look the flow up by the credential key`, { provider: descriptor.key })\n const current = getOAuthProvider(flow.id)\n if (current && current !== flow && claims().has(current))\n logger.warn(`registerProvider: OAuth flow \"${flow.id}\" replaces another extension's`, { provider: descriptor.key })\n registerOAuthProvider(flow)\n claims().set(flow, (claims().get(flow) ?? 0) + 1)\n claimed.push(flow)\n }\n }\n\n let released = false\n return () => {\n if (released)\n return\n released = true\n for (const flow of claimed) {\n const left = (claims().get(flow) ?? 1) - 1\n if (left > 0) {\n claims().set(flow, left)\n continue\n }\n claims().delete(flow)\n unregisterOAuthProvider(flow)\n }\n }\n}\n","/**\n * The {@link ExtensionRegistry} hosts read, as a live view of the extension\n * runtime.\n *\n * Each extension's contributions are read from the runtime's registries:\n * tools, skills, MCP servers, agents, providers and sub-agents from the\n * catalogs; `/` commands, palette providers, keybindings and footer hints\n * from the command registry; panels, themes, references, badge actions and\n * context sections from the UI registry; composer providers; settings as\n * config rows; and, when the host wired none of its own, the extension's\n * agent-hook observers and host events as handlers. The view merges them.\n *\n * Reads are cached until one of those registries changes (or an extension\n * loads, fails or unloads); the next read recomputes, so a command or panel\n * registered after `setup` shows up. `registry.subscribe` tells hosts when\n * to read again. Filtered views (`filterExtensionRegistry`,\n * `filterRegistryPlugins`) share the runtime and the change feed.\n */\n\nimport type { AgentHooks } from '../../agent'\nimport type { ContextBreakdownContributor } from '../../chat/context-breakdown'\nimport type { Settings } from '../../chat/types'\nimport type { ToolDef } from '../../tools/types'\nimport type { JsonValue } from '../../types'\nimport type { ExtensionDefinition } from '../api/define'\nimport type { ExtensionConfigActionItem, ExtensionConfigCategory, StoredExtensionConfigItem } from '../config'\nimport type { ExtensionSessionEventHandler } from '../host-runtime'\nimport type { ExtensionPanelEntry } from '../panels'\nimport type { SettingsPort } from '../settings'\nimport type {\n ExtensionContributions,\n ExtensionFooterHint,\n ExtensionKeybinding,\n ExtensionOrderedContribution,\n ExtensionRegistry,\n ExtensionRunSettledHandler,\n ExtensionToolResultMetadataRegistration,\n LoadedExtension,\n LoadedExtensionSource,\n LoadedPluginRecord,\n} from '../types'\nimport type { UiChange } from '../ui/registry'\nimport type { ExtensionRuntime, RuntimeExtension } from './host'\nimport { basename } from 'node:path'\nimport { settingsForDefinition, toWireSettings } from '../settings'\nimport { withProvenance } from '../shared'\n\n/**\n * A settings port over the host's settings bag (`Settings.extensionConfig`),\n * which today's Settings UIs write: it is the `user` layer, and the\n * source of `secret` strings too. Writes are left to the host, which\n * persists what its Settings UI and action results give it.\n *\n * @param readSettings - The host's live settings getter.\n * @returns The port.\n */\nexport function extensionConfigSettingsPort(readSettings: (() => Partial<Settings> | undefined) | undefined): SettingsPort {\n const bag = (ext: string): Readonly<Record<string, unknown>> | undefined => {\n const all = readSettings?.()?.extensionConfig\n return all && Object.hasOwn(all, ext) ? all[ext] : undefined\n }\n return {\n read: (ext, layer) => (layer === 'user' ? bag(ext) : undefined),\n write: () => {},\n secrets: {\n get: (ext, key) => {\n const value = bag(ext)?.[key]\n return typeof value === 'string' && value ? value : undefined\n },\n set: () => {},\n },\n }\n}\n\nfunction emptyContributions(): ExtensionContributions {\n return {\n tools: {},\n hooks: {},\n mcpServers: [],\n skills: [],\n plugins: [],\n runSettled: [],\n sessionEvents: [],\n contextBreakdownSections: [],\n contextPanelSections: [],\n toolResultMetadata: [],\n artifactKinds: [],\n references: [],\n badgeActions: [],\n completionProviders: [],\n inlineAutocompleteProviders: [],\n commands: [],\n themes: {},\n agents: {},\n providers: {},\n subagents: {},\n configCategories: {},\n configItems: {},\n tui: { keybindings: [], footerHints: [] },\n panels: [],\n palette: [],\n }\n}\n\n/** The extension's settings as config categories and rows. Actions run through the settings domain when active. */\nfunction projectSettings(ext: RuntimeExtension, def: ExtensionDefinition): Pick<ExtensionContributions, 'configCategories' | 'configItems'> {\n const instance = ext.settings\n const wire = instance ? instance.wire() : toWireSettings(ext.id, settingsForDefinition(def).schema)\n const configCategories: Record<string, ExtensionConfigCategory> = {}\n for (const category of wire.schema.categories)\n configCategories[category.id] = category\n const configItems: Record<string, StoredExtensionConfigItem> = {}\n for (const item of wire.schema.items) {\n const { extension: _extension, ...rest } = item\n configItems[item.key] = {\n ...rest,\n ...(instance ? { validate: (value: unknown) => instance.check(item.key, value) === undefined } : {}),\n } as StoredExtensionConfigItem\n }\n for (const action of wire.actions) {\n const key = action.key\n const run: ExtensionConfigActionItem['run'] = async () => {\n if (!ext.settings)\n throw new Error('The extension is not active')\n const result = await ext.settings.runAction(key)\n return { ...(result.message !== undefined ? { message: result.message } : {}), ...(result.config ? { config: result.config } : {}) }\n }\n configItems[key] = {\n type: 'action',\n key,\n label: action.label,\n ...(action.description !== undefined ? { description: action.description } : {}),\n category: action.category,\n run,\n ...(action.hasStatus && instance\n ? {\n status: async () => {\n const status = await instance.actionStatuses()\n return status[`${ext.id}:${key}`]\n },\n }\n : {}),\n }\n if (!configCategories[action.category] && action.category !== ext.id)\n configCategories[action.category] = { id: action.category, label: action.categoryLabel }\n }\n return { configCategories, configItems }\n}\n\nfunction ownedBy(id: string, origin: { kind: string, id?: string } | undefined): boolean {\n return origin?.kind === 'extension' && origin.id === id\n}\n\n/** The live contributions of one active extension. */\nfunction projectActive(runtime: ExtensionRuntime, ext: RuntimeExtension, source: LoadedExtensionSource, cwd: string): ExtensionContributions {\n const { outputs } = runtime\n const { catalogs, ui, commands } = outputs\n const id = ext.id\n const out = emptyContributions()\n\n const tools = catalogs.tools.read()\n const toolRecord: Record<string, ToolDef> = {}\n for (const tool of tools.items) {\n if (ownedBy(id, tools.origin(tool.name)))\n toolRecord[tool.name] = tool.def\n }\n out.tools = toolRecord\n\n const agents = catalogs.agents.read().sections\n out.agents = Object.fromEntries(agents.profiles.items.filter(p => ownedBy(id, agents.profiles.origin(p.id))).map(p => [p.id, p]))\n out.subagents = Object.fromEntries(agents.subagents.items.filter(s => ownedBy(id, agents.subagents.origin(s.name))).map(s => [s.name, s]))\n const providers = catalogs.providers.read().sections.providers\n out.providers = Object.fromEntries(providers.items.filter(p => ownedBy(id, providers.origin(p.key))).map(p => [p.key, p]))\n const servers = catalogs.mcp.read().sections.servers\n out.mcpServers = servers.items.filter(s => ownedBy(id, servers.origin(s.name)))\n const skills = catalogs.skills.read().sections.skills\n out.skills = skills.items.filter(s => ownedBy(id, skills.origin(s.name))).map(s => withProvenance(s, source, id))\n\n out.artifactKinds = runtime.artifactKinds(id).map(e => ({ extensionName: id, source, value: e.registration }))\n out.plugins = runtime.plugins(id)\n out.toolResultMetadata = catalogs.tools.metadata.list().filter(m => m.extensionId === id).map((m): ExtensionOrderedContribution<ExtensionToolResultMetadataRegistration> => ({\n extensionName: id,\n source,\n value: {\n namespace: m.namespace,\n ...(m.spec.contextRows ? { contextRows: ctx => catalogs.tools.metadata.contextRows(m.namespace, ctx.entries.map(e => ({ value: e.value as never }))) } : {}),\n ...(m.spec.summarize ? { summarize: metadata => catalogs.tools.metadata.summarize(m.namespace, metadata) as JsonValue | undefined } : {}),\n },\n }))\n\n const handlers = runtime.hookHandlers(id)\n const hooks: Record<string, ((...args: unknown[]) => unknown)[]> = {}\n if (!runtime.hostWired.agentHooks) {\n for (const [name, set] of handlers.agent) {\n if (set.size === 0)\n continue\n hooks[name] = [(...args: unknown[]) => {\n for (const fn of [...set])\n fn(...args)\n }]\n }\n }\n // Artifact detection (`ctx.artifacts.kinds.register` with `detect`) runs on\n // tool results whatever bus the host gave: one dispatcher reading the live kinds.\n if (runtime.artifactKinds(id).some(e => e.detect)) {\n const detect = async (...args: unknown[]): Promise<void> => {\n for (const entry of [...runtime.artifactKinds(id)])\n await (entry.detect as ((...a: unknown[]) => unknown) | undefined)?.(...args)\n }\n for (const name of ['tool:transform', 'child:tool:transform'])\n (hooks[name] ??= []).push(detect)\n }\n out.hooks = hooks as ExtensionContributions['hooks']\n if (!runtime.hostWired.hostEvents) {\n const deliver = (name: 'run:settled' | 'session:event', event: unknown): void => {\n for (const fn of [...handlers.host.get(name) ?? []])\n (fn as (e: unknown) => void)(event)\n }\n const runSettled: ExtensionRunSettledHandler = e => deliver('run:settled', { sessionId: e.sessionId, runId: e.runId, ok: e.ok, aborted: e.aborted, session: e.session })\n const sessionEvent: ExtensionSessionEventHandler = (e) => {\n if (e.status === 'cancelled')\n return\n deliver('session:event', {\n sessionId: e.sessionId,\n kind: e.status,\n ...(e.status === 'error' ? { error: e.error ?? e.summary } : {}),\n ...(e.request ? { requestId: e.request.id } : {}),\n })\n }\n out.runSettled = [runSettled]\n out.sessionEvents = [sessionEvent]\n }\n\n const named = (c: ContextBreakdownContributor): string | undefined => (c as { __zidaneExtensionName?: string }).__zidaneExtensionName\n out.contextBreakdownSections = ui.contextContributors('breakdown').filter(c => named(c) === id)\n out.contextPanelSections = ui.contextContributors('panel').filter(c => named(c) === id)\n\n out.references = ui.list('reference').filter(e => e.extension === id).map(e => ({\n extensionName: id,\n source,\n value: { ...e.item, resolve: async (key: string) => (await ui.resolveReference(e.item.id, key)) ?? undefined },\n }))\n out.badgeActions = ui.list('badge-action').filter(e => e.extension === id).map(e => ({\n extensionName: id,\n source,\n value: {\n id: e.item.id,\n ...(e.item.match ? { match: e.item.match } : {}),\n actions: target => ui.badgeMenu(target).filter(item => item.source === e.item.id).map(({ source: _source, ...action }) => action),\n run: (actionId, target, ctx) => ui.runBadgeAction(e.item.id, actionId, target, { ...(ctx.sessionId !== undefined ? { sessionId: ctx.sessionId } : {}), ...(ctx.cwd !== undefined ? { cwd: ctx.cwd } : {}) }),\n },\n }))\n out.themes = Object.fromEntries(ui.list('theme').filter(e => e.extension === id).map(e => [e.item.id, e.item]))\n out.panels = ui.list('panel').filter(e => e.extension === id).map((e) => {\n const panel = e.item\n return {\n id: panel.id,\n owner: id,\n label: panel.label,\n ...(panel.icon !== undefined ? { icon: panel.icon } : {}),\n ...(panel.scope !== undefined ? { scope: panel.scope } : {}),\n surfaces: panel.surfaces,\n ...(panel.home !== undefined ? { home: panel.home } : {}),\n load: ctx => ui.loadPanel(panel.id, ctx, ctx.cwd ?? cwd),\n ...(panel.live\n ? {\n subscribe: (emit: (change?: { sessionId?: string }) => void) => ui.subscribe((change) => {\n if (change.type === 'panel-changed' && change.panelId === panel.id)\n emit(change.sessionId ? { sessionId: change.sessionId } : undefined)\n }),\n }\n : {}),\n ...(panel.actions ? { onAction: async (actionId: string, payload: JsonValue | undefined, ctx: { cwd: string }) => { await ui.panelAction(panel.id, actionId, payload, ctx, ctx.cwd ?? cwd) } } : {}),\n } satisfies ExtensionPanelEntry\n })\n out.completionProviders = ui.completions.list().filter(p => p.extension === id).map(p => p.provider)\n out.inlineAutocompleteProviders = ui.autocomplete.list().filter(p => p.extension === id).map(p => p.provider)\n\n const mine = (commandId: string): boolean => commands.get(commandId)?.extensionId === id\n out.commands = commands.slashCommands().filter(c => mine(c.commandId)).map(c => (c.group === undefined ? { ...c, group: id } : c))\n out.palette = commands.paletteProviders().filter(p => p.owner === id)\n const hints: ExtensionFooterHint[] = []\n for (const listing of commands.list()) {\n const entry = commands.get(listing.id)\n if (!entry || entry.extensionId !== id || !entry.spec.hint || !entry.enabled())\n continue\n const chord = commands.keymap.bindings(entry.id)[0]\n if (chord)\n hints.push({ key: chord, label: entry.title() })\n }\n out.tui = { keybindings: commands.keybindings().filter(k => mine(k.id)), footerHints: hints }\n return out\n}\n\n/** What a registry view reads from: the runtime, the entries it refused, and the change feed. */\nexport interface RegistryViewSource {\n /** The runtime. Absent when no extension was loaded into one. */\n readonly runtime?: ExtensionRuntime\n /** The host cwd (panel loads without one). */\n readonly cwd: string\n /** Entries refused before the runtime: load errors, modules without a definition, duplicates. */\n readonly refused: readonly LoadedExtension[]\n /**\n * Takes the refused entry of folder `dir` off the list (the folder was\n * deleted, or it loads into the runtime now). Returns whether there was one.\n */\n dropRefused: (dir: string) => boolean\n /**\n * Replaces the rows a host reports under `group` (config install\n * failures, `config:user`), listed after {@link refused}. An empty list\n * clears the group.\n */\n reportRefused: (group: string, entries: readonly LoadedExtension[]) => void\n /** Bumped on every change; views recompute when it moved. */\n version: () => number\n /** Calls `listener` (coalesced per microtask) after a change. */\n subscribe: (listener: () => void) => () => void\n /** Disposes the runtime. Idempotent. */\n dispose: () => Promise<void>\n}\n\n/** UI tokens whose items the view shows (slots, screens and the rest change without affecting it). */\nconst VIEWED_UI_TOKENS: ReadonlySet<string> = new Set(['panel', 'reference', 'badge-action', 'theme', 'context-section'])\n\nfunction uiChangeMatters(change: UiChange): boolean {\n if (change.type === 'providers')\n return true\n if (change.type === 'panel-changed')\n return false\n return VIEWED_UI_TOKENS.has(change.type === 'upsert' ? change.entry.token : change.token)\n}\n\n/**\n * The change feed and disposal of one runtime, shared by every view of it.\n *\n * @param input - The runtime (absent: nothing ever changes), the host cwd, refused entries and the dispose.\n * @param input.runtime - The runtime.\n * @param input.cwd - The host cwd.\n * @param input.refused - Entries that never reached the runtime.\n * @param input.dispose - Releases the runtime and its ports.\n * @returns The source.\n */\nexport function createRegistryViewSource(input: {\n runtime?: ExtensionRuntime\n cwd: string\n refused: readonly LoadedExtension[]\n dispose: () => Promise<void>\n}): RegistryViewSource & { changed: () => void } {\n let version = 0\n const refused = [...input.refused]\n const reported = new Map<string, readonly LoadedExtension[]>()\n const listeners = new Set<() => void>()\n let queued = false\n let disposed = false\n const unsubscribes: (() => void)[] = []\n const changed = (): void => {\n version++\n if (queued || listeners.size === 0)\n return\n queued = true\n queueMicrotask(() => {\n queued = false\n for (const listener of [...listeners]) {\n try {\n listener()\n }\n catch {}\n }\n })\n }\n const runtime = input.runtime\n if (runtime) {\n const { catalogs, ui, commands } = runtime.outputs\n for (const catalog of [catalogs.tools, catalogs.agents, catalogs.providers, catalogs.mcp, catalogs.skills])\n unsubscribes.push(catalog.subscribe(changed))\n unsubscribes.push(commands.subscribe(changed))\n unsubscribes.push(runtime.subscribe(changed))\n unsubscribes.push(ui.subscribe((change) => {\n if (uiChangeMatters(change))\n changed()\n }))\n }\n return {\n ...(runtime ? { runtime } : {}),\n cwd: input.cwd,\n get refused() { return reported.size === 0 ? refused : [...refused, ...[...reported.values()].flat()] },\n reportRefused: (group, entries) => {\n if (entries.length === 0 && !reported.has(group))\n return\n if (entries.length === 0)\n reported.delete(group)\n else\n reported.set(group, [...entries])\n changed()\n },\n dropRefused: (dir) => {\n const at = refused.findIndex(entry => entry.dir === dir)\n if (at === -1)\n return false\n refused.splice(at, 1)\n changed()\n return true\n },\n version: () => version,\n changed,\n subscribe: (listener) => {\n listeners.add(listener)\n return () => {\n listeners.delete(listener)\n }\n },\n dispose: async () => {\n if (disposed)\n return\n disposed = true\n for (const unsubscribe of unsubscribes.splice(0))\n unsubscribe()\n listeners.clear()\n await input.dispose()\n },\n }\n}\n\n/** How a view narrows its source. */\nexport interface RegistryViewFilter {\n /** Names of the extensions to keep active; the rest show as inactive. `undefined`: all. */\n readonly enabled?: ReadonlySet<string>\n /** Agent Plugin names whose skills and MCP servers drop out. */\n readonly droppedPlugins?: ReadonlySet<string>\n}\n\n/** Every known extension as `LoadedExtension` entries, with their live contributions. */\nfunction loadedEntries(source: RegistryViewSource): { active: LoadedExtension[], inactive: LoadedExtension[] } {\n const active: LoadedExtension[] = []\n const inactive: LoadedExtension[] = []\n const runtime = source.runtime\n for (const info of runtime?.extensions() ?? []) {\n const ext = runtime!.get(info.id)\n if (!ext)\n continue\n const def = ext.definition\n // A declaratively installed extension is a user one here.\n const loadedSource: LoadedExtensionSource = ext.entry.source === 'config' ? 'user' : ext.entry.source\n const base: LoadedExtension = {\n // The folder name is the persisted identity (an id that differs from it fails validation).\n name: ext.entry.dir !== undefined ? basename(ext.entry.dir) : ext.id,\n source: loadedSource,\n ...(ext.entry.dir !== undefined ? { dir: ext.entry.dir } : {}),\n ...(ext.entry.manifest ? { manifest: ext.entry.manifest } : {}),\n ...(def ? { definition: def } : {}),\n setupRan: info.status !== 'disabled',\n }\n if (info.status === 'active' && def)\n active.push({ ...base, contributions: { ...projectActive(runtime!, ext, loadedSource, source.cwd), ...projectSettings(ext, def) } })\n else if (info.status === 'disabled' && def)\n inactive.push({ ...base, contributions: { ...emptyContributions(), ...projectSettings(ext, def) } })\n else\n inactive.push({ ...base, error: info.error ?? 'failed to load' })\n }\n inactive.push(...source.refused)\n return { active, inactive }\n}\n\nfunction pruneDroppedPlugins(ext: LoadedExtension, dropped: ReadonlySet<string>, droppedServers: ReadonlySet<unknown>): LoadedExtension {\n const contributions = ext.contributions\n if (!contributions || contributions.plugins.length === 0)\n return ext\n return {\n ...ext,\n contributions: {\n ...contributions,\n skills: contributions.skills.filter((skill) => {\n const owner = skill.metadata?.['zidane.plugin']\n return owner === undefined || !dropped.has(owner)\n }),\n mcpServers: contributions.mcpServers.filter(server => !droppedServers.has(server)),\n },\n }\n}\n\ntype Merged = Omit<ExtensionRegistry, 'runtime' | 'subscribe' | 'dispose'>\n\n/** Folds the active extensions' contributions; inactive ones add only their settings. */\nfunction merge(active: readonly LoadedExtension[], inactive: readonly LoadedExtension[]): Merged {\n const tools: Record<string, ToolDef> = Object.create(null)\n const hooks: { [E in keyof AgentHooks]?: Array<AgentHooks[E]> } = {}\n const out = {\n mcpServers: [] as Merged['mcpServers'][number][],\n skills: [] as Merged['skills'][number][],\n plugins: [] as LoadedPluginRecord[],\n runSettled: [] as ExtensionOrderedContribution<ExtensionRunSettledHandler>[],\n sessionEvents: [] as ExtensionOrderedContribution<ExtensionSessionEventHandler>[],\n contextBreakdownSections: [] as ContextBreakdownContributor[],\n contextPanelSections: [] as ContextBreakdownContributor[],\n toolResultMetadata: [] as Merged['toolResultMetadata'][number][],\n artifactKinds: [] as Merged['artifactKinds'][number][],\n references: [] as Merged['references'][number][],\n badgeActions: [] as Merged['badgeActions'][number][],\n completionProviders: [] as Merged['completionProviders'][number][],\n inlineAutocompleteProviders: [] as Merged['inlineAutocompleteProviders'][number][],\n commands: [] as Merged['commands'][number][],\n keybindings: [] as ExtensionKeybinding[],\n footerHints: [] as ExtensionFooterHint[],\n panels: [] as ExtensionPanelEntry[],\n palette: [] as Merged['palette'][number][],\n }\n const themes: Record<string, Merged['themes'][string]> = {}\n const agents: Record<string, Merged['agents'][string]> = {}\n const providers: Record<string, Merged['providers'][string]> = {}\n const subagents: Record<string, Merged['subagents'][string]> = {}\n const configCategories: Record<string, ExtensionConfigCategory> = {}\n const configItems: Record<string, Readonly<Record<string, StoredExtensionConfigItem>>> = Object.create(null)\n const seen = { kinds: new Set<string>(), references: new Set<string>(), badges: new Set<string>(), inline: new Set<string>(), commands: new Set<string>(), keys: new Set<string>() }\n\n for (const entry of active) {\n const c = entry.contributions\n if (!c)\n continue\n Object.assign(tools, c.tools)\n for (const [event, list] of Object.entries(c.hooks)) {\n if (!list)\n continue\n const bucket = (hooks[event as keyof AgentHooks] ??= []) as unknown[]\n bucket.push(...list)\n }\n out.mcpServers.push(...c.mcpServers)\n out.skills.push(...c.skills)\n out.plugins.push(...c.plugins)\n for (const value of c.runSettled)\n out.runSettled.push({ extensionName: entry.name, source: entry.source, value })\n for (const value of c.sessionEvents)\n out.sessionEvents.push({ extensionName: entry.name, source: entry.source, value })\n out.contextBreakdownSections.push(...c.contextBreakdownSections)\n out.contextPanelSections.push(...c.contextPanelSections)\n out.toolResultMetadata.push(...c.toolResultMetadata)\n for (const kind of c.artifactKinds) {\n if (seen.kinds.has(kind.value.kind))\n continue\n seen.kinds.add(kind.value.kind)\n out.artifactKinds.push(kind)\n }\n for (const reference of c.references) {\n if (!seen.references.has(reference.value.id)) {\n seen.references.add(reference.value.id)\n out.references.push(reference)\n }\n }\n for (const badge of c.badgeActions) {\n if (!seen.badges.has(badge.value.id)) {\n seen.badges.add(badge.value.id)\n out.badgeActions.push(badge)\n }\n }\n out.completionProviders.push(...c.completionProviders)\n for (const provider of c.inlineAutocompleteProviders) {\n if (seen.inline.has(provider.id))\n continue\n seen.inline.add(provider.id)\n out.inlineAutocompleteProviders.push(provider)\n }\n // First wins by name, case-insensitive like `parseCommandInvocation`; aliases share the namespace.\n for (const command of c.commands) {\n const key = command.name.toLowerCase()\n if (seen.commands.has(key))\n continue\n seen.commands.add(key)\n for (const alias of command.aliases ?? [])\n seen.commands.add(alias.toLowerCase())\n out.commands.push(command)\n }\n Object.assign(themes, c.themes)\n Object.assign(agents, c.agents)\n Object.assign(providers, c.providers)\n Object.assign(subagents, c.subagents)\n Object.assign(configCategories, c.configCategories)\n if (Object.keys(c.configItems).length > 0)\n configItems[entry.name] = { ...c.configItems }\n for (const binding of c.tui.keybindings) {\n if (seen.keys.has(binding.id))\n continue\n seen.keys.add(binding.id)\n out.keybindings.push(binding)\n }\n out.footerHints.push(...c.tui.footerHints)\n out.panels.push(...c.panels)\n out.palette.push(...c.palette)\n }\n\n // Disabled extensions keep their settings visible (and editable) before they are enabled.\n for (const entry of inactive) {\n const c = entry.contributions\n if (entry.error || !c)\n continue\n for (const [id, category] of Object.entries(c.configCategories)) {\n if (!(id in configCategories))\n configCategories[id] = category\n }\n if (Object.keys(c.configItems).length > 0 && !(entry.name in configItems))\n configItems[entry.name] = { ...c.configItems }\n }\n\n return {\n loaded: active,\n inactive,\n tools,\n hooks,\n mcpServers: out.mcpServers,\n skills: out.skills,\n plugins: out.plugins,\n runSettled: out.runSettled,\n sessionEvents: out.sessionEvents,\n contextBreakdownSections: out.contextBreakdownSections,\n contextPanelSections: out.contextPanelSections,\n toolResultMetadata: out.toolResultMetadata,\n artifactKinds: out.artifactKinds,\n references: out.references,\n badgeActions: out.badgeActions,\n completionProviders: out.completionProviders,\n inlineAutocompleteProviders: out.inlineAutocompleteProviders,\n commands: out.commands,\n themes,\n agents,\n providers,\n subagents,\n configCategories,\n configItems,\n tuiContributions: { keybindings: out.keybindings, footerHints: out.footerHints },\n panels: out.panels,\n palette: out.palette,\n }\n}\n\nfunction compute(source: RegistryViewSource, filter: RegistryViewFilter): Merged {\n const { active, inactive } = loadedEntries(source)\n const enabled = filter.enabled\n let kept = enabled ? active.filter(e => enabled.has(e.name)) : active\n const off = enabled ? active.filter(e => !enabled.has(e.name)) : []\n const dropped = filter.droppedPlugins\n if (dropped && dropped.size > 0) {\n const records = kept.flatMap(e => e.contributions?.plugins ?? []).filter(r => dropped.has(r.name))\n if (records.length > 0) {\n const droppedServers = new Set<unknown>(records.flatMap(r => r.plugin.mcpServers))\n kept = kept.map(e => pruneDroppedPlugins(e, dropped, droppedServers))\n }\n }\n return merge(kept, [...inactive, ...off])\n}\n\nconst VIEW_STATE = Symbol('zidane.registryView')\n\ninterface ViewState {\n source: RegistryViewSource\n filter: RegistryViewFilter\n}\n\n/**\n * A live {@link ExtensionRegistry} over `source`, narrowed by `filter`.\n *\n * @param source - The runtime and change feed (`createRegistryViewSource`).\n * @param filter - Allowlist and dropped plugins.\n * @returns The view.\n */\nexport function createRegistryView(source: RegistryViewSource, filter: RegistryViewFilter = {}): ExtensionRegistry {\n let cached: { version: number, value: Merged } | undefined\n const read = (): Merged => {\n const version = source.version()\n if (!cached || cached.version !== version)\n cached = { version, value: compute(source, filter) }\n return cached.value\n }\n const view = {\n get loaded() { return read().loaded },\n get inactive() { return read().inactive },\n get tools() { return read().tools },\n get hooks() { return read().hooks },\n get mcpServers() { return read().mcpServers },\n get skills() { return read().skills },\n get plugins() { return read().plugins },\n get runSettled() { return read().runSettled },\n get sessionEvents() { return read().sessionEvents },\n get contextBreakdownSections() { return read().contextBreakdownSections },\n get contextPanelSections() { return read().contextPanelSections },\n get toolResultMetadata() { return read().toolResultMetadata },\n get artifactKinds() { return read().artifactKinds },\n get references() { return read().references },\n get badgeActions() { return read().badgeActions },\n get completionProviders() { return read().completionProviders },\n get inlineAutocompleteProviders() { return read().inlineAutocompleteProviders },\n get commands() { return read().commands },\n get themes() { return read().themes },\n get agents() { return read().agents },\n get providers() { return read().providers },\n get subagents() { return read().subagents },\n get configCategories() { return read().configCategories },\n get configItems() { return read().configItems },\n get tuiContributions() { return read().tuiContributions },\n get panels() { return read().panels },\n get palette() { return read().palette },\n ...(source.runtime ? { runtime: source.runtime.outputs } : {}),\n subscribe: (listener: () => void) => source.subscribe(listener),\n dispose: () => source.dispose(),\n } satisfies ExtensionRegistry\n Object.defineProperty(view, VIEW_STATE, { value: { source, filter } satisfies ViewState })\n return view\n}\n\n/**\n * The source and filter behind a view from {@link createRegistryView}, or\n * `undefined` for any other registry (`EMPTY_EXTENSION_REGISTRY`, a\n * hand-built one).\n *\n * @param registry - A registry.\n */\nexport function registryViewState(registry: ExtensionRegistry): ViewState | undefined {\n return (registry as { [VIEW_STATE]?: ViewState })[VIEW_STATE]\n}\n","/**\n * Load extensions into the runtime and hand hosts the {@link ExtensionRegistry}:\n * a live view of what they contribute (`runtime/registry-view.ts`).\n *\n * Only `apiVersion: 1` modules load. Discovery already turned a module\n * without a definition into an entry with its error; an entry that reaches\n * here with no definition and no error gets `NO_DEFINITION_ERROR`. Isolation, timeouts, error budgets and\n * rollback are the runtime's (`runtime/host.ts`): a failing extension lands\n * in `inactive` with its error and never stops the others.\n */\n\nimport type { Settings } from '../chat/types'\nimport type { LogSink } from '../logger'\nimport type { ExtensionHostKind, ExtensionPaths } from './api/core'\nimport type { ExtensionHostRuntimeBridge } from './host-runtime'\nimport type { ExtensionPromptBridge } from './prompt-bridge'\nimport type { ExtensionRuntime, ExtensionRuntimeOptions, RuntimePorts } from './runtime/host'\nimport type { ExtensionRuntimeOutputs } from './runtime/outputs'\nimport type { ExtensionRegistry, LoadedExtension } from './types'\nimport { homedir } from 'node:os'\nimport { join } from 'node:path'\nimport { resolveStorageDirs } from '../chat/xdg'\nimport { consoleSink, createLogger } from '../logger'\nimport { claimProviderOAuthFlows } from './provider-oauth'\nimport { isRuntimeLoadedExtension, NO_DEFINITION_ERROR, runtimeEntryOf } from './runtime/loaded-entry'\nimport { createRegistryView, createRegistryViewSource, extensionConfigSettingsPort, registryViewState } from './runtime/registry-view'\n\n/** Options for {@link buildExtensionRegistry}. */\nexport interface BuildExtensionRegistryOptions {\n /**\n * Names the user has explicitly disabled. Loaded but not run (their\n * settings stay readable); listed in `inactive` so the Settings panel\n * can show them.\n */\n disabled?: ReadonlySet<string>\n /** Maximum time one extension's setup may take before it is marked inactive. Default: the runtime's. */\n setupTimeoutMs?: number\n /**\n * Override the log sink. Defaults to a `consoleSink` writing to\n * stderr (which the TUI suppresses to keep the renderer clean —\n * only `ZIDANE_DEBUG=1` surfaces the lines).\n */\n sink?: LogSink\n /**\n * Prompt bridge backing `ctx.sessions.submit` without a session id.\n * Hosts with a submit pipeline attach their handler post-mount.\n */\n promptBridge?: ExtensionPromptBridge\n /**\n * Host runtime bridge backing `ctx.sessions`, `ctx.workspace` and\n * `ctx.artifacts` when `runtime.ports.host` is not given. Late-bound: the\n * host attaches its implementation post-mount.\n */\n hostRuntime?: ExtensionHostRuntimeBridge\n /**\n * Live settings getter: the `user` settings layer (`Settings.extensionConfig`)\n * when `runtime.ports.settings` is not given.\n */\n readSettings?: () => Partial<Settings> | undefined\n /** Runtime cwd used for `ctx.paths`. */\n cwd?: string\n /** Project root exposed as `ctx.paths.projectRoot`. */\n projectRoot?: string\n /** Storage directories exposed through `ctx.paths`. Default: resolved from `prefix` and the platform conventions. */\n storageDirs?: {\n configDir?: string\n dataDir: string\n stateDir?: string\n cacheDir: string\n }\n /** Storage prefix used to resolve the storage directories. Default: `ZIDANE_PREFIX`, else `.zidane`. */\n prefix?: string\n /** Host kind, ports and guard options of the runtime. */\n runtime?: BuildRuntimeOptions\n}\n\n/** How {@link buildExtensionRegistry} builds the runtime. */\nexport interface BuildRuntimeOptions {\n /** The host process. Default `'sdk'`. */\n host?: ExtensionHostKind\n /**\n * Host ports. Defaults: settings read from `readSettings` (the\n * `extensionConfig` bag), storage in files under\n * `<dataDir>/extension-storage` (and `<projectRoot>/<prefix>/extension-storage`),\n * the rest in memory.\n */\n ports?: RuntimePorts\n /** Guard and status options passed through to the runtime. */\n runtime?: Pick<ExtensionRuntimeOptions, 'budget' | 'callbackTimeoutMs' | 'onStall' | 'onChange' | 'memory' | 'platform'>\n}\n\n/** The runtime behind each registry. */\nconst registryRuntimes = new WeakMap<ExtensionRuntimeOutputs, ExtensionRuntime>()\n\n/**\n * The runtime behind `registry.runtime` (load, unload, reload, settings), or\n * `undefined` when the registry loaded no extension.\n *\n * @param registry - A registry from {@link buildExtensionRegistry} (or filtered from one).\n */\nexport function extensionRuntimeOf(registry: Pick<ExtensionRegistry, 'runtime'>): ExtensionRuntime | undefined {\n return registry.runtime ? registryRuntimes.get(registry.runtime) : undefined\n}\n\n/**\n * Load the extensions and return the live registry over them.\n * `loaded` typically comes from `discoverExtensions()` plus any inline\n * ones via `inlineLoadedExtension`.\n *\n * Disabled extensions stay in `inactive` (alongside any load errors)\n * so the Settings panel shows the full picture.\n *\n * @param loaded - Discovered and inline extensions.\n * @param options - Logging, bridges, storage paths, setup limits and the runtime's ports.\n * @example\n * ```ts\n * import { buildExtensionRegistry, discoverExtensions } from 'zidane/extensions'\n *\n * const loaded = await discoverExtensions({ cwd: process.cwd() })\n * const registry = await buildExtensionRegistry(loaded, { cwd: process.cwd() })\n * console.log(Object.keys(registry.tools))\n * ```\n */\nexport async function buildExtensionRegistry(\n loaded: readonly LoadedExtension[],\n options: BuildExtensionRegistryOptions = {},\n): Promise<ExtensionRegistry> {\n const sink = options.sink ?? consoleSink({ minLevel: 'warn' })\n const disabled = options.disabled ?? new Set<string>()\n const paths = resolveContextPaths(options)\n\n const refused: LoadedExtension[] = []\n const loadable: LoadedExtension[] = []\n for (const entry of loaded) {\n if (!isRuntimeLoadedExtension(entry)) {\n refused.push(entry.error ? entry : { ...entry, error: NO_DEFINITION_ERROR })\n continue\n }\n if (loadable.some(e => e.name === entry.name))\n refused.push({ ...entry, error: `Duplicate extension name \"${entry.name}\" ignored; the earlier registration wins.` })\n else\n loadable.push(entry)\n }\n\n if (loadable.length === 0) {\n const source = createRegistryViewSource({ cwd: paths.cwd, refused, dispose: async () => {} })\n return createRegistryView(source)\n }\n\n // Loaded on demand: a host with no extensions never pays for the runtime's module graph.\n const [{ createExtensionRuntime }, { createFileStoragePort }] = await Promise.all([\n import('./runtime/host'),\n import('./storage'),\n ])\n const ports = options.runtime?.ports ?? {}\n // Hosts attach their session runtime to these bridges; the runtime reads the same ones.\n const bridge = options.hostRuntime\n const host = ports.host ?? (bridge\n ? {\n sessions: { sessionControl: bridge.sessionControl, ...(options.promptBridge ? { promptBridge: options.promptBridge } : {}) },\n workspace: { current: bridge.current },\n artifacts: { current: bridge.current },\n }\n : undefined)\n const storage = ports.storage\n ? undefined\n : createFileStoragePort({\n root: join(paths.dataDir, 'extension-storage'),\n ...(paths.projectRoot ? { projectRoot: join(paths.projectRoot, options.prefix ?? process.env.ZIDANE_PREFIX ?? '.zidane', 'extension-storage') } : {}),\n watch: false,\n })\n const runtime = createExtensionRuntime({\n ...options.runtime?.runtime,\n host: options.runtime?.host ?? 'sdk',\n paths,\n logger: createLogger(sink),\n ...(options.setupTimeoutMs !== undefined ? { setupTimeoutMs: options.setupTimeoutMs } : {}),\n ports: {\n ...ports,\n ...(storage ? { storage } : {}),\n settings: ports.settings ?? extensionConfigSettingsPort(options.readSettings),\n ...(host ? { host } : {}),\n },\n })\n registryRuntimes.set(runtime.outputs, runtime)\n let releaseOAuthFlows: () => void = () => {}\n const source = createRegistryViewSource({\n runtime,\n cwd: paths.cwd,\n refused,\n dispose: async () => {\n releaseOAuthFlows()\n await runtime.dispose()\n storage?.close()\n },\n })\n await runtime.load(loadable.map(entry => runtimeEntryOf(entry, !disabled.has(entry.name))))\n const registry = createRegistryView(source)\n // Providers' OAuth flows ride their contribution: registered for the active\n // extensions now, released on dispose (see ./provider-oauth).\n releaseOAuthFlows = claimProviderOAuthFlows(registry.loaded, sink)\n return registry\n}\n\n/**\n * Filter the extension registry by the user's enable allowlist. Returns\n * the original registry by reference when `enabled` is `undefined` (the\n * fresh-install default — every loaded extension is active) or when it\n * keeps every active extension; otherwise a live view over the same\n * runtime with the others listed as inactive.\n *\n * The identity check is intentional — callers can compare the result\n * against the input registry to skip recomposing the preset when\n * nothing has changed.\n *\n * @param registry - Registry to filter.\n * @param enabled - Names of the enabled extensions. `undefined` keeps every extension.\n */\nexport function filterExtensionRegistry(\n registry: ExtensionRegistry,\n enabled: readonly string[] | undefined,\n): ExtensionRegistry {\n if (enabled === undefined)\n return registry\n const allow = new Set(enabled)\n if (registry.loaded.every(ext => allow.has(ext.name)))\n return registry\n const state = registryViewState(registry)\n if (!state)\n return registry\n const narrowed = state.filter.enabled ? new Set([...state.filter.enabled].filter(name => allow.has(name))) : allow\n return createRegistryView(state.source, { ...state.filter, enabled: narrowed })\n}\n\n/**\n * Drop the contributions of Agent Plugins the user has disabled.\n *\n * `filterExtensionRegistry` keys on EXTENSION names, so it can't express\n * \"this extension runs, but the plugin it loaded does not\". Plugin skills and\n * MCP servers are fanned into the loading extension's contributions by\n * `ctx.plugins.load`, which means without this pass `enabledPlugins` would\n * render a checkbox that changes nothing for extension-loaded plugins.\n *\n * Skills are matched by `metadata['zidane.plugin']` (stamped by the loader);\n * MCP servers carry no such marker, so they're matched by identity against\n * the server list on each {@link LoadedPluginRecord}.\n *\n * Returns the input registry unchanged when nothing is disabled, so callers\n * can compare identity to skip recomposing.\n *\n * @param registry - Registry to filter.\n * @param enabledPlugins - Names of the enabled plugins. `undefined` keeps every plugin.\n * @param shadowed - Plugin names already provided by another source (in\n * practice: disk discovery), pruned regardless of the allowlist. The\n * settings list dedupes such a plugin to ONE row preferring the disk copy;\n * contributions have to agree, or that single checkbox governs two live\n * copies.\n */\nexport function filterRegistryPlugins(\n registry: ExtensionRegistry,\n enabledPlugins: readonly string[] | undefined,\n shadowed?: ReadonlySet<string>,\n): ExtensionRegistry {\n if (registry.plugins.length === 0)\n return registry\n const allow = enabledPlugins === undefined ? null : new Set(enabledPlugins)\n const dropped = registry.plugins.filter(record =>\n (allow !== null && !allow.has(record.name)) || shadowed?.has(record.name) === true)\n if (dropped.length === 0)\n return registry\n const state = registryViewState(registry)\n if (!state)\n return registry\n const droppedPlugins = new Set([...(state.filter.droppedPlugins ?? []), ...dropped.map(record => record.name)])\n return createRegistryView(state.source, { ...state.filter, droppedPlugins })\n}\n\n/**\n * Dispose resources owned by an extension registry. Idempotent per registry.\n *\n * @param registry - Registry to dispose.\n */\nexport async function disposeExtensionRegistry(registry: ExtensionRegistry): Promise<void> {\n await registry.dispose()\n}\n\n/** Shape returned by {@link partitionExtensionCatalog}. */\nexport interface ExtensionCatalogPartition {\n /**\n * Rows the user can toggle: active extensions plus disabled-but-\n * loadable ones, sorted by name so the list order is stable across\n * boots regardless of where each entry landed in the registry.\n */\n toggleable: readonly LoadedExtension[]\n /** Entries whose import or `setup()` failed — read-only diagnostics. */\n errored: readonly LoadedExtension[]\n /**\n * Every known extension name — toggleable AND errored. Use this as\n * the GC key set for the persisted `enabledExtensions` allowlist so\n * an untrusted / temporarily-broken extension isn't permanently\n * dropped from the allowlist by an unrelated toggle.\n */\n allNames: readonly string[]\n}\n\n/**\n * Partition a registry's `loaded` + `inactive` lists into the shape the\n * Settings toggle UIs render. Pure; shared by the TUI's standalone\n * extensions modal and the Settings-modal tab so the rules (and the\n * allowlist-GC key set) stay in one place.\n *\n * @param loaded - Active extensions.\n * @param inactive - Disabled or failed extensions.\n */\nexport function partitionExtensionCatalog(\n loaded: readonly LoadedExtension[],\n inactive: readonly LoadedExtension[],\n): ExtensionCatalogPartition {\n const errored = inactive.filter(e => !!e.error)\n const disabledOk = inactive.filter(e => !e.error)\n const toggleable = [...loaded, ...disabledOk].sort((a, b) => a.name.localeCompare(b.name))\n return {\n toggleable,\n errored,\n allNames: [...toggleable.map(e => e.name), ...errored.map(e => e.name)],\n }\n}\n\nfunction resolveContextPaths(options: BuildExtensionRegistryOptions): ExtensionPaths {\n const cwd = options.cwd ?? process.cwd()\n const dirs = options.storageDirs ?? resolveStorageDirs({\n prefix: options.prefix ?? process.env.ZIDANE_PREFIX ?? '.zidane',\n home: homedir(),\n })\n return {\n cwd,\n ...(options.projectRoot ? { projectRoot: options.projectRoot } : {}),\n dataDir: dirs.dataDir,\n cacheDir: dirs.cacheDir,\n ...(dirs.configDir ? { configDir: dirs.configDir } : {}),\n ...(dirs.stateDir ? { stateDir: dirs.stateDir } : {}),\n }\n}\n","/**\n * Reloading the extensions whose folders changed, one by one, instead of\n * rebuilding the whole registry: a changed folder is imported again and its\n * extension reloaded in place (`ExtensionRuntime.reload`), a new folder is\n * loaded, a deleted one unloaded. The other extensions keep running, their\n * state untouched. The registry view over the runtime tells its subscribers.\n */\n\nimport type { LogSink } from '../../logger'\nimport type { ExtensionSource } from '../api/core'\nimport type { ExtensionRegistry } from '../types'\nimport type { ExtensionRuntime } from './host'\nimport { existsSync } from 'node:fs'\nimport { resolve } from 'node:path'\nimport { findEntryFile, loadExtensionFolder } from '../discovery'\nimport { extensionRuntimeOf } from '../register'\nimport { runtimeEntryOf } from './loaded-entry'\nimport { registryViewState } from './registry-view'\n\n/** How a folder the runtime does not hold may load. */\nexport interface NewExtensionFolder {\n /** Where it was found. */\n source: ExtensionSource\n /** `false`: listed disabled (not in the user's allowlist). Default `true`. */\n enabled?: boolean\n}\n\n/** Options of {@link reloadChangedExtensions}. */\nexport interface ReloadChangedOptions {\n /**\n * Whether a folder no extension was loaded from may load now, and how.\n * `undefined`: it may not (not under a scan root, an untrusted project\n * folder, shadowed by a folder of the same name that wins). Without\n * `classify`, new folders are ignored.\n */\n classify?: (dir: string) => NewExtensionFolder | undefined\n /** How long one import may take. Default 10 s. */\n importTimeoutMs?: number\n /** Where load warnings go. Default: warnings to stderr. */\n sink?: LogSink\n /** Node hosts: the folder compiled extension code is kept in. */\n compileCache?: string\n}\n\n/** What {@link reloadChangedExtensions} did, by extension id. */\nexport interface ReloadChangedResult {\n /** New folders that loaded (active, disabled or failed). */\n loaded: string[]\n /** Extensions imported again and reloaded in place. */\n reloaded: string[]\n /** Extensions whose folder (or entry file) is gone. */\n unloaded: string[]\n /**\n * A change could not be applied in place: the registry holds no runtime\n * (it loaded no extension), so a new folder needs a full rebuild.\n */\n needsRebuild: boolean\n}\n\nfunction isRuntime(target: ExtensionRuntime | ExtensionRegistry): target is ExtensionRuntime {\n return typeof (target as Partial<ExtensionRuntime>).idOfDir === 'function'\n}\n\n/**\n * Applies folder changes to a runtime: a held folder that changed is\n * imported fresh and reloaded in place; one whose folder or entry file is\n * gone is unloaded (its `ctx.storage.memory` cleared); a new folder loads\n * when `options.classify` allows it. Given a registry, a folder it refused\n * at build time (its import failed, an untrusted project folder) counts as\n * new, and leaves the refused list once it loads or is deleted. Folders are\n * handled one at a time, in the order given (duplicates once). Never rejects\n * for an extension's fault: a module that fails to import is listed\n * `failed` with the error.\n *\n * @param target - A registry from `buildExtensionRegistry` (or a view of one), or its runtime.\n * @param changedDirs - Extension folders that changed (absolute).\n * @param options - How new folders load, import bound, sink and compile cache.\n * @returns The ids loaded, reloaded and unloaded, and whether a rebuild is needed.\n * @example\n * ```ts\n * await reloadChangedExtensions(registry, ['/home/me/.zidane/extensions/notes'], {\n * classify: dir => (loadableExtensionDirs({ cwd }).includes(dir) ? { source: 'user' } : undefined),\n * })\n * ```\n */\nexport async function reloadChangedExtensions(target: ExtensionRuntime | ExtensionRegistry, changedDirs: readonly string[], options: ReloadChangedOptions = {}): Promise<ReloadChangedResult> {\n const runtime = isRuntime(target) ? target : extensionRuntimeOf(target)\n const source = isRuntime(target) ? undefined : registryViewState(target)?.source\n const result: ReloadChangedResult = { loaded: [], reloaded: [], unloaded: [], needsRebuild: false }\n const importOptions = {\n ...(options.importTimeoutMs !== undefined ? { importTimeoutMs: options.importTimeoutMs } : {}),\n ...(options.sink ? { sink: options.sink } : {}),\n ...(options.compileCache !== undefined ? { compileCache: options.compileCache } : {}),\n }\n const refusedDir = (dir: string): string | undefined => source?.refused.find(entry => entry.dir !== undefined && resolve(entry.dir) === dir)?.dir\n for (const dir of [...new Set(changedDirs.map(d => resolve(d)))]) {\n const id = runtime?.idOfDir(dir)\n const present = existsSync(dir) && findEntryFile(dir) !== null\n if (runtime && id !== undefined) {\n if (!present) {\n await runtime.unload(id, { forget: true })\n result.unloaded.push(id)\n continue\n }\n const held = runtime.get(id)!.entry\n const loaded = await loadExtensionFolder(dir, { source: held.source === 'project' ? 'project' : 'user', ...importOptions })\n const info = await runtime.reload(id, { entry: { ...runtimeEntryOf(loaded, held.enabled), source: held.source } })\n if (info)\n result.reloaded.push(info.id)\n continue\n }\n const refused = refusedDir(dir)\n if (!present) {\n if (refused !== undefined)\n source!.dropRefused(refused)\n continue\n }\n const how = options.classify?.(dir)\n if (!how)\n continue\n if (!runtime) {\n result.needsRebuild = true\n continue\n }\n const loaded = await loadExtensionFolder(dir, { source: how.source === 'project' ? 'project' : 'user', ...importOptions })\n const [info] = await runtime.load([{ ...runtimeEntryOf(loaded, how.enabled), source: how.source }])\n if (refused !== undefined)\n source!.dropRefused(refused)\n if (info)\n result.loaded.push(info.id)\n }\n return result\n}\n","/**\n * Declarative extension config: the `extensions` array in a zidane\n * config file (user `<configDir>/config.json`, project\n * `<project-root>/.zidane/config.json`).\n *\n * ```json\n * { \"extensions\": [\n * { \"source\": \"owner/repo\" },\n * { \"source\": \"github:owner/repo@v1.2.0:extensions/goal\", \"settings\": { \"model\": \"opus\" } },\n * { \"source\": \"owner/collection name\", \"enabled\": false },\n * { \"source\": \"@scope/pkg@1.0.0\" },\n * { \"source\": \"./tools/my-extension\" }\n * ] }\n * ```\n *\n * Remote sources use the install grammar of `parseInstallSource`\n * (`src/install/source.ts`), the same one `installExtensionFromSpec` takes. A\n * trailing word after a space picks one extension of a collection\n * (`owner/repo name`), like the `extension` field. Local paths (`./`, `../`, `/`,\n * `~/`, `file:`) are loaded in place, never copied.\n *\n * Everything here is pure: the caller reads the file and passes the parsed\n * JSON in.\n */\n\nimport type { InstallSource } from '../../install/source'\nimport { basename, isAbsolute, resolve } from 'node:path'\nimport { InstallSourceError, parseInstallSource } from '../../install/source'\nimport { isSettingKey } from '../settings/validate'\n\n/** The config file an entry came from. Each scope has its own lock file. */\nexport type ExtensionsConfigScope = 'user' | 'project'\n\n/** A value a config entry may give a setting. Secrets are refused: they belong in the auth store. */\nexport type ConfigSettingValue = string | number | boolean | readonly string[]\n\n/** Where a declared extension comes from. */\nexport type DeclaredLocation\n = | { readonly kind: 'remote', readonly source: InstallSource }\n | { readonly kind: 'local', readonly path: string }\n\n/** One valid entry of the `extensions` array. */\nexport interface DeclaredExtension {\n /**\n * Identity of the entry: the source without its ref or version, plus the\n * picked extension. Keys the lock file, so changing a ref is an update of\n * the same entry, not a new one.\n */\n readonly key: string\n /** The `source` string as written (trimmed). Compared with the lock to detect a changed pin. */\n readonly source: string\n /** The spec handed to the installer: `source` without the trailing extension name. */\n readonly installSpec: string\n /** The extension picked from a collection, when one was. */\n readonly extension?: string\n readonly location: DeclaredLocation\n /** Settings values this entry sets. They show as locked in Settings. */\n readonly settings: Readonly<Record<string, ConfigSettingValue>>\n /** `false` keeps the extension installed but not loaded. Default `true`. */\n readonly enabled: boolean\n readonly scope: ExtensionsConfigScope\n /** Position in the array, for messages. */\n readonly index: number\n}\n\n/** A problem found in a config or lock file. Errors drop the entry; warnings keep it. */\nexport interface ExtensionsConfigDiagnostic {\n readonly level: 'error' | 'warning'\n readonly scope: ExtensionsConfigScope\n /** Index of the entry in the `extensions` array, when the problem is in one. */\n readonly index?: number\n readonly message: string\n}\n\n/** What {@link parseExtensionsConfig} needs besides the JSON. */\nexport interface ParseExtensionsConfigOptions {\n readonly scope: ExtensionsConfigScope\n /** Relative local paths resolve against it (the project root, or the user config dir). */\n readonly baseDir: string\n /** Home directory for `~/` paths. */\n readonly home: string\n}\n\n/** Result of {@link parseExtensionsConfig}. */\nexport interface ParsedExtensionsConfig {\n readonly entries: readonly DeclaredExtension[]\n readonly diagnostics: readonly ExtensionsConfigDiagnostic[]\n}\n\nconst ENTRY_FIELDS = new Set(['source', 'extension', 'settings', 'enabled'])\nconst NAME_RE = /^[\\w.-]+$/\n\n/**\n * Whether `source` names a local directory rather than a GitHub repo or npm\n * package.\n *\n * @param source - A trimmed source string.\n */\nexport function isLocalSource(source: string): boolean {\n return source === '.' || source === '~' || source.startsWith('./') || source.startsWith('../')\n || source.startsWith('/') || source.startsWith('~/') || source.startsWith('file:')\n || /^[a-z]:[\\\\/]/i.test(source)\n}\n\n/**\n * Splits `owner/repo name` into the install spec and the picked extension.\n * Local paths are never split: a space is part of the path.\n *\n * @param source - A trimmed source string.\n */\nexport function splitSourceSpec(source: string): { spec: string, extension?: string } {\n if (isLocalSource(source))\n return { spec: source }\n const m = /^(\\S+)\\s+(\\S+)$/.exec(source)\n return m ? { spec: m[1] as string, extension: m[2] as string } : { spec: source }\n}\n\n/**\n * The identity of a source: GitHub owner/repo and subdir, npm package name,\n * or the local path as written. Ref and version are left out.\n *\n * @param location - The parsed source.\n * @param localSpec - For a local source, the path as written (identity stays stable across machines).\n * @param extension - The extension picked from a collection.\n */\nexport function sourceIdentity(location: DeclaredLocation, localSpec: string, extension?: string): string {\n const base = location.kind === 'local'\n ? `local:${localSpec}`\n : location.source.kind === 'npm'\n ? `npm:${location.source.pkg}`\n : `github:${location.source.owner.toLowerCase()}/${location.source.repo.toLowerCase()}${location.source.subdir ? `:${location.source.subdir}` : ''}`\n return extension ? `${base}#${extension}` : base\n}\n\n/**\n * The identity of an install spec as recorded in `.install.json`, or\n * `undefined` when it does not parse. Lets a planner recognize an extension\n * installed by hand from the same source as a config entry.\n *\n * @param spec - A remote install spec.\n * @param extension - The extension picked from a collection.\n */\nexport function installSpecIdentity(spec: string, extension?: string): string | undefined {\n try {\n return sourceIdentity({ kind: 'remote', source: parseInstallSource(spec) }, spec, extension)\n }\n catch {\n return undefined\n }\n}\n\n/**\n * The local directory `source` points at, absolute.\n *\n * @param source - A local source string.\n * @param baseDir - Directory relative paths resolve against.\n * @param home - Home directory for `~`.\n */\nexport function resolveLocalSource(source: string, baseDir: string, home: string): string {\n const path = source.startsWith('file:') ? source.slice('file:'.length).replace(/^\\/\\/(?=\\/)/, '') : source\n if (path === '~')\n return home\n if (path.startsWith('~/'))\n return resolve(home, path.slice(2))\n return isAbsolute(path) ? resolve(path) : resolve(baseDir, path)\n}\n\n/**\n * The id a local source loads as: its folder name, as discovery requires.\n *\n * @param path - The resolved local directory.\n */\nexport function localExtensionId(path: string): string {\n return basename(path)\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === 'object' && !Array.isArray(value)\n}\n\nfunction isSettingValue(value: unknown): value is ConfigSettingValue {\n if (typeof value === 'string' || typeof value === 'boolean')\n return true\n if (typeof value === 'number')\n return Number.isFinite(value)\n return Array.isArray(value) && value.every(v => typeof v === 'string')\n}\n\n/**\n * Parses the `extensions` field of a config file. Never throws: a bad entry\n * is dropped with an error diagnostic, an odd field kept with a warning.\n * A source declared twice keeps its first entry.\n *\n * @param config - The whole parsed config file (its `extensions` field is read), or `undefined` when there is no file.\n * @param options - Scope, base directory and home.\n */\nexport function parseExtensionsConfig(config: unknown, options: ParseExtensionsConfigOptions): ParsedExtensionsConfig {\n const { scope } = options\n const diagnostics: ExtensionsConfigDiagnostic[] = []\n const entries: DeclaredExtension[] = []\n if (config === undefined || config === null)\n return { entries, diagnostics }\n if (!isRecord(config)) {\n diagnostics.push({ level: 'error', scope, message: 'The config file is not a JSON object.' })\n return { entries, diagnostics }\n }\n const list = config.extensions\n if (list === undefined)\n return { entries, diagnostics }\n if (!Array.isArray(list)) {\n diagnostics.push({ level: 'error', scope, message: '\"extensions\" must be an array of { source, settings?, enabled? }.' })\n return { entries, diagnostics }\n }\n const seen = new Map<string, number>()\n list.forEach((raw, index) => {\n const fail = (message: string): void => {\n diagnostics.push({ level: 'error', scope, index, message })\n }\n const warn = (message: string): void => {\n diagnostics.push({ level: 'warning', scope, index, message })\n }\n if (!isRecord(raw))\n return fail('An entry must be an object with a \"source\".')\n if (typeof raw.source !== 'string' || raw.source.trim() === '')\n return fail('\"source\" must be a non-empty string.')\n for (const field of Object.keys(raw)) {\n if (!ENTRY_FIELDS.has(field))\n warn(`Unknown field \"${field}\" is ignored.`)\n }\n const source = raw.source.trim()\n const split = splitSourceSpec(source)\n let extension = split.extension\n if (raw.extension !== undefined) {\n if (typeof raw.extension !== 'string' || !NAME_RE.test(raw.extension))\n return fail('\"extension\" must be an extension name ([A-Za-z0-9_.-]).')\n if (extension !== undefined && extension !== raw.extension)\n return fail(`\"source\" picks \"${extension}\" but \"extension\" says \"${raw.extension}\".`)\n extension = raw.extension\n }\n if (extension !== undefined && !NAME_RE.test(extension))\n return fail(`\"${extension}\" is not an extension name ([A-Za-z0-9_.-]).`)\n\n let location: DeclaredLocation\n if (isLocalSource(split.spec)) {\n if (extension !== undefined)\n return fail('A local source points at one extension folder; \"extension\" does not apply.')\n location = { kind: 'local', path: resolveLocalSource(split.spec, options.baseDir, options.home) }\n }\n else {\n try {\n location = { kind: 'remote', source: parseInstallSource(split.spec) }\n }\n catch (err) {\n return fail(err instanceof InstallSourceError ? err.message : `\"${source}\" is not a valid source.`)\n }\n }\n\n let enabled = true\n if (raw.enabled !== undefined) {\n if (typeof raw.enabled !== 'boolean')\n return fail('\"enabled\" must be true or false.')\n enabled = raw.enabled\n }\n\n const settings: Record<string, ConfigSettingValue> = {}\n if (raw.settings !== undefined) {\n if (!isRecord(raw.settings))\n return fail('\"settings\" must be an object of setting values.')\n for (const [key, value] of Object.entries(raw.settings)) {\n if (!isSettingKey(key))\n warn(`Setting \"${key}\" is not a valid key and is ignored.`)\n else if (!isSettingValue(value))\n warn(`Setting \"${key}\" must be a string, number, boolean or list of strings. It is ignored.`)\n else\n settings[key] = value\n }\n }\n\n const key = sourceIdentity(location, split.spec, extension)\n const first = seen.get(key)\n if (first !== undefined)\n return fail(`\"${source}\" is the same extension as entry ${first}. Only the first is used.`)\n seen.set(key, index)\n entries.push({\n key,\n source,\n installSpec: split.spec,\n ...(extension !== undefined ? { extension } : {}),\n location,\n settings,\n enabled,\n scope,\n index,\n })\n })\n return { entries, diagnostics }\n}\n","/**\n * Extension import — fetch from GitHub or npm, validate, and install into\n * the roots {@link discoverExtensions} already scans.\n *\n * Host-agnostic by construction: no UI, no settings access, no renderer.\n * The TUI's `Settings → Extensions` install flow (`ctrl+g`) and the GUI\n * call the same {@link installExtensionFromSpec} orchestrator; hosts own scope\n * selection, overwrite confirmation, allowlist updates, and the\n * post-install registry rebuild (the `/reload` path).\n *\n * Pipeline invariants:\n *\n * - **Validate before touching user roots.** The candidate is imported\n * and validated (an `apiVersion: 1` definition, checked like the\n * runtime does with `validateDefinition`) inside the temp dir; a failure installs nothing.\n * Importing executes the extension's top-level code once — the\n * explicit install request is the consent; it's the same code that\n * would run at next boot.\n * - **Folder name = definition name, by construction.** The target dir\n * is named from the validated definition's `id`, so discovery's\n * name-match invariant can't be violated by an install.\n * - **Dependency installs never run lifecycle scripts** (bun's default;\n * the npm/pnpm/yarn fallbacks get `--ignore-scripts`).\n * - Failures throw {@link ExtensionInstallError} with a machine-readable\n * `code` so hosts can react (e.g. `exists` → confirm-and-retry with\n * `overwrite`), never half-install.\n *\n * Recognized package shapes (both fetch targets):\n *\n * - root `index.{ts,tsx,mjs,js}` → a single-extension repo/package\n * - `extensions/<name>/index.*` → a multi-extension collection;\n * `extension` selects one (mandatory when several exist)\n */\n\nimport type { FetchSourceResult, InstallIo, InstallScope, InstallSource } from '../install/source'\nimport { cpSync, existsSync, lstatSync, mkdirSync, mkdtempSync, readdirSync, readFileSync, renameSync, rmSync, writeFileSync } from 'node:fs'\nimport { tmpdir } from 'node:os'\nimport { basename, dirname, join, resolve } from 'node:path'\nimport { projectUserPaths } from '../chat/project-user-paths'\nimport { errorMessage } from '../errors'\nimport { defaultExec, defaultWhich, fetchInstallSource, InstallSourceError, lastLine, parseInstallSource, resolveNpmVersion, resolveSubdirRoot } from '../install/source'\nimport { EXTENSION_API_VERSION } from './api/define'\nimport { definitionExport, findEntryFile, importExtensionEntry, readExtensionManifest, releaseExtensionModules } from './discovery'\nimport { checkZidaneVersion } from './host-version'\nimport { validateDefinition } from './runtime/validate-definition'\nimport { withTimeout } from './with-timeout'\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/** Where an extension is installed: the project or the user directory. */\nexport type ExtensionInstallScope = InstallScope\n\n/** The shared install-source shape — see `src/install/source.ts` for the grammar. */\nexport type ExtensionInstallSource = InstallSource\n\n/** Reason an install, update or removal failed. Matches {@link ExtensionInstallError.code}. */\nexport type ExtensionInstallErrorCode\n = | 'invalid-source'\n | 'fetch-failed'\n | 'no-extension'\n | 'multiple-candidates'\n | 'deps-failed'\n | 'validate-failed'\n | 'exists'\n | 'no-package-manager'\n | 'not-installed'\n | 'no-provenance'\n | 'name-mismatch'\n\n/** Error thrown by the extension installer. `code` says which step failed. */\nexport class ExtensionInstallError extends InstallSourceError {\n /** Machine-readable reason for the failure. */\n declare readonly code: ExtensionInstallErrorCode\n /**\n * Creates an install error.\n * @param code - Reason for the failure.\n * @param message - Human-readable description.\n * @param candidates - Extension names found in the source, set for `multiple-candidates`, `no-extension` and `name-mismatch`.\n */\n constructor(code: ExtensionInstallErrorCode, message: string, candidates?: readonly string[]) {\n super(code, message, candidates)\n this.name = 'ExtensionInstallError'\n }\n}\n\n/**\n * Re-raise a shared-layer {@link InstallSourceError} in the extension\n * error vocabulary so every consumer keeps a single `err.code` switch\n * over {@link ExtensionInstallErrorCode}. The base layer only throws\n * `'invalid-source'` / `'fetch-failed'` — both members of the extension\n * union.\n */\nfunction rethrowAsExtensionError(err: unknown): never {\n if (err instanceof InstallSourceError && !(err instanceof ExtensionInstallError))\n throw new ExtensionInstallError(err.code as ExtensionInstallErrorCode, err.message, err.candidates)\n throw err\n}\n\nconst PROVENANCE_FILE = '.install.json'\n\n/** What `.install.json` records — enough to replay the install for updates. */\nexport interface ExtensionInstallProvenance {\n /** Resolved provenance, e.g. `npm:foo@1.2.3` / `github:owner/repo@main`. */\n source: string\n /** The raw spec the user passed — what an update re-resolves. */\n spec: string\n /** Scope the extension was installed into. */\n scope: ExtensionInstallScope\n /** Candidate selected from a multi-extension source, when one was. */\n extension?: string\n /** Exact commit SHA (GitHub via git clone) — anchors the update no-op check. */\n commit?: string\n /** ISO 8601 timestamp of the install. */\n installedAt: string\n}\n\n/** Where an installed extension came from, from its `.install.json`: what Settings shows (\"Update from <label>\"). */\nexport interface ExtensionInstallOrigin {\n /** The spec it was installed from, what an update re-resolves (`Tahul/zidane#v9.0.4:extensions/goal`). */\n spec: string\n /** A short name of the source: `Tahul/zidane`, `Tahul/zidane@v9.0.4`, `@scope/pkg`. */\n label: string\n /** The resolved provenance (`github:Tahul/zidane@v9.0.4:extensions/goal`, `npm:pkg@1.2.3`). */\n source: string\n /** The exact commit, when the install cloned it. */\n commit?: string\n /** When it was installed (ISO 8601), when recorded. */\n installedAt?: string\n}\n\n/** One installable extension found inside a fetched tree. */\nexport interface ExtensionInstallCandidate {\n /** Proposed name (manifest name, else collection dirname, else repo/pkg basename). */\n name: string\n /** Absolute directory inside the fetched tree. */\n dir: string\n}\n\n/** Outcome of an install or update. */\nexport interface ExtensionInstallResult {\n /** Final name — the validated `definition.name`. */\n name: string\n /** Absolute installed directory. */\n dir: string\n /** Scope the extension was installed into. */\n scope: ExtensionInstallScope\n /** Human-readable provenance, e.g. `npm:foo@1.2.3` / `github:owner/repo@main`. */\n provenance: string\n /** Exact commit SHA when known (GitHub via git clone). */\n commit?: string\n /** Non-fatal problems met during the install, such as dependency install notices. */\n warnings: readonly string[]\n}\n\n/**\n * Injectable side-effect seams — tests swap these to stay offline; hosts\n * normally omit the whole object. Shared shape with the skills installer.\n */\nexport type ExtensionInstallIo = InstallIo\n\n/** Options for {@link installExtensionFromSpec}. */\nexport interface InstallExtensionFromSpecOptions {\n /** Raw source spec — see {@link parseExtensionInstallSource}. */\n source: string\n /** Candidate name to install when the source contains several extensions. */\n extension?: string\n /**\n * The name the install must have: the candidate of that name, else the\n * only candidate, and its definition's id must equal it. Anything else\n * fails with `name-mismatch` (listing the names found) before the target\n * is touched. Used by {@link changeExtensionOrigin}.\n */\n expectName?: string\n /**\n * Candidate to pick when the source contains several and `extension` is unset: an update of an\n * install recorded without one (older hosts did not record it). Unlike `extension`, a source\n * with one candidate, or none of that name, is not an error. The pick is recorded.\n */\n fallbackExtension?: string\n /** Scope to install into. */\n scope: ExtensionInstallScope\n /** Replace an existing install of the same name. Default false → `exists` error. */\n overwrite?: boolean\n /** Working directory used to find the project root. @default process.cwd() */\n cwd?: string\n /** User home directory. @default os.homedir() */\n home?: string\n /** Storage prefix (e.g. `.zidane`). Matches discovery's default. */\n prefix?: string\n /** Called with a short status message as each step runs. */\n onProgress?: (message: string) => void\n /** Overrides for fetch, process execution and executable lookup. Mainly for tests. */\n io?: ExtensionInstallIo\n /** Timeout for the validation import. Default 10s (matches discovery). */\n importTimeoutMs?: number\n /**\n * Advanced: exact extensions root to install into, bypassing the\n * scope → `.{prefix}/extensions` resolution. Used by\n * {@link updateInstalledExtension} to replace an install in place\n * (e.g. one living under `.agents/extensions`).\n */\n installRoot?: string\n}\n\n// ---------------------------------------------------------------------------\n// Source spec parsing + fetch — thin wrappers over the shared install\n// layer (`src/install/source.ts`), re-raised in the extension error\n// vocabulary. The grammar, fetch pipeline, caps, and hardening live\n// there so the skills installer shares them verbatim.\n// ---------------------------------------------------------------------------\n\n/**\n * Classify a raw source string. See `parseInstallSource` for the grammar.\n *\n * @param raw - Source spec such as `owner/repo`, `npm:pkg` or a git URL.\n */\nexport function parseExtensionInstallSource(raw: string): ExtensionInstallSource {\n try {\n return parseInstallSource(raw)\n }\n catch (err) {\n rethrowAsExtensionError(err)\n }\n}\n\n/** Result of {@link fetchExtensionSource}: the provenance string and, for git clones, the commit SHA. */\nexport type ExtensionFetchResult = FetchSourceResult\n\n/**\n * Materialize the source into `destDir` (created by the caller, assumed\n * empty). Returns the provenance string plus, for git clones, the exact\n * commit SHA. See `fetchInstallSource` for transport details and caps.\n *\n * @param source - Parsed install source.\n * @param destDir - Empty directory to fetch into.\n * @param io - Overrides for fetch, process execution and executable lookup.\n * @param onProgress - Called with a short status message as the fetch runs.\n */\nexport async function fetchExtensionSource(\n source: ExtensionInstallSource,\n destDir: string,\n io: ExtensionInstallIo = {},\n onProgress?: (message: string) => void,\n): Promise<ExtensionFetchResult> {\n try {\n return await fetchInstallSource(source, destDir, io, onProgress)\n }\n catch (err) {\n rethrowAsExtensionError(err)\n }\n}\n\n// ---------------------------------------------------------------------------\n// Candidate enumeration\n// ---------------------------------------------------------------------------\n\n/**\n * List the installable extensions inside a fetched tree. `fallbackName`\n * seeds the single-extension case when no manifest names it (repo or\n * unscoped package basename).\n *\n * @param dir - Root of the fetched tree.\n * @param fallbackName - Name to use when no manifest names the extension.\n */\nexport function listExtensionCandidates(dir: string, fallbackName: string): ExtensionInstallCandidate[] {\n if (findEntryFile(dir))\n return [{ name: readExtensionManifest(dir).manifest?.name ?? sanitizeName(fallbackName), dir }]\n const collection = join(dir, 'extensions')\n const out: ExtensionInstallCandidate[] = []\n let children: string[]\n try {\n children = readdirSync(collection)\n }\n catch {\n return out\n }\n for (const child of children.sort()) {\n if (child.startsWith('.'))\n continue\n const childDir = join(collection, child)\n try {\n if (!lstatSync(childDir).isDirectory())\n continue\n }\n catch {\n continue\n }\n if (findEntryFile(childDir))\n out.push({ name: child, dir: childDir })\n }\n return out\n}\n\n/** Basename-ish fallback: strip npm scope, keep folder-safe chars. */\nfunction sanitizeName(raw: string): string {\n const base = raw.includes('/') ? (raw.split('/').pop() as string) : raw\n return base.replace(/[^\\w.-]+/g, '-').replace(/^[.-]+/, '') || 'extension'\n}\n\n// ---------------------------------------------------------------------------\n// Orchestrator\n// ---------------------------------------------------------------------------\n\n/**\n * The full fetch → enumerate → deps → validate → copy pipeline. See the\n * module doc for invariants. Throws {@link ExtensionInstallError}; a throw\n * means nothing was written to the target roots.\n *\n * @param opts - Source, scope and install options.\n */\nexport async function installExtensionFromSpec(opts: InstallExtensionFromSpecOptions): Promise<ExtensionInstallResult> {\n const io = opts.io ?? {}\n const onProgress = opts.onProgress\n const source = parseExtensionInstallSource(opts.source)\n const warnings: string[] = []\n\n const stage = mkdtempSync(join(tmpdir(), 'zidane-ext-install-'))\n try {\n const fetchedInto = join(stage, 'fetched')\n mkdirSync(fetchedInto, { recursive: true })\n const { provenance, commit } = await fetchExtensionSource(source, fetchedInto, io, onProgress)\n\n // A `:subdir` source re-roots the candidate search. Physical (not\n // just string-level) containment lives in `resolveSubdirRoot` — a\n // malicious repo shipping a symlink (`evil -> /`) must not walk the\n // candidate search (and the validation IMPORT) onto the local\n // filesystem. Structural escapes are already rejected at parse time;\n // this is the belt-and-braces layer.\n let candidateRoot = fetchedInto\n let fallbackName = source.kind === 'github' ? source.repo : source.pkg\n if (source.kind === 'github' && source.subdir) {\n const rooted = resolveSubdirRoot(fetchedInto, source.subdir)\n if (!rooted.ok) {\n if (rooted.reason === 'missing')\n throw new ExtensionInstallError('no-extension', `\"${source.subdir}\" is not a directory in ${source.owner}/${source.repo}${source.ref ? `@${source.ref}` : ''}.`)\n throw new ExtensionInstallError(\n 'invalid-source',\n rooted.reason === 'escape-symlink'\n ? `Subdirectory \"${source.subdir}\" escapes the repository root through a symlink.`\n : `Subdirectory \"${source.subdir}\" escapes the repository root.`,\n )\n }\n candidateRoot = rooted.dir\n fallbackName = basename(resolve(fetchedInto, source.subdir))\n }\n const candidates = listExtensionCandidates(candidateRoot, fallbackName)\n if (candidates.length === 0) {\n throw new ExtensionInstallError('no-extension', `No extension found in ${opts.source}. Expected a root index.{ts,tsx,mjs,js} or extensions/<name>/index.* directories.`)\n }\n let candidate: ExtensionInstallCandidate\n if (opts.expectName !== undefined) {\n const match = candidates.find(c => c.name === opts.expectName) ?? (candidates.length === 1 ? candidates[0] : undefined)\n if (!match)\n throw nameMismatch(opts.expectName, opts.source, candidates.map(c => c.name))\n candidate = match\n }\n else if (opts.extension) {\n const match = candidates.find(c => c.name === opts.extension)\n if (!match) {\n throw new ExtensionInstallError(\n 'no-extension',\n `No extension named \"${opts.extension}\" in ${opts.source}. Available: ${candidates.map(c => c.name).join(', ')}`,\n candidates.map(c => c.name),\n )\n }\n candidate = match\n }\n else if (candidates.length > 1 && candidates.some(c => c.name === opts.fallbackExtension)) {\n candidate = candidates.find(c => c.name === opts.fallbackExtension) as ExtensionInstallCandidate\n }\n else if (candidates.length > 1) {\n throw new ExtensionInstallError(\n 'multiple-candidates',\n `${opts.source} contains ${candidates.length} extensions. Pass one of: ${candidates.map(c => c.name).join(', ')}`,\n candidates.map(c => c.name),\n )\n }\n else {\n candidate = candidates[0] as ExtensionInstallCandidate\n }\n\n // Dependencies BEFORE validation — the import may need them.\n const pm = await installDependencies(candidate.dir, io, onProgress)\n if (pm)\n warnings.push(...pm.warnings)\n\n onProgress?.('validating extension module…')\n const definition = await validateCandidate(candidate, opts.importTimeoutMs ?? 10_000)\n if (opts.expectName !== undefined && definition.name !== opts.expectName)\n throw nameMismatch(opts.expectName, opts.source, [definition.name])\n if (definition.warning)\n warnings.push(definition.warning)\n\n const targetRoot = opts.installRoot ?? resolveInstallRoot(opts)\n const targetDir = join(targetRoot, definition.name)\n // Overwrites are fully live: discovery evicts the extension's module\n // graph before each import, so the next reload runs the new code.\n if (existsSync(targetDir) && !opts.overwrite)\n throw new ExtensionInstallError('exists', `${targetDir} already exists. Pass overwrite to replace it.`)\n\n onProgress?.(`installing to ${targetDir}…`)\n mkdirSync(targetRoot, { recursive: true })\n // Transactional target phase — the \"never half-install\" invariant. An\n // overwritten previous version is parked under a dot-name (invisible\n // to the scanner) and restored if anything past this point throws\n // (e.g. the in-place deps install failing on a full disk); on success\n // it is deleted. A fresh install that fails is wiped back to absence.\n const backupDir = existsSync(targetDir)\n ? join(targetRoot, `.${definition.name}.prev-${process.pid}-${Date.now()}`)\n : null\n if (backupDir)\n renameSync(targetDir, backupDir)\n try {\n cpSync(candidate.dir, targetDir, {\n recursive: true,\n // Materialize symlinked files: the stage dir they'd point into is\n // deleted after install, so copied links would dangle. (The\n // extension's code already ran at validation with the user's\n // consent — dereferencing discloses nothing new.)\n dereference: true,\n filter: src => !/(?:^|[\\\\/])(?:\\.git|node_modules)(?:$|[\\\\/])/.test(src),\n })\n // Re-install deps in place (node_modules excluded from the copy —\n // symlink layouts don't survive a cp).\n await installDependencies(targetDir, io, onProgress)\n\n const provenanceRecord: ExtensionInstallProvenance = {\n source: provenance,\n spec: opts.source,\n scope: opts.scope,\n // Picked from several (named or by fallback): recorded, so its update needs no fallback.\n ...(opts.extension !== undefined && opts.expectName === undefined ? { extension: opts.extension } : candidates.length > 1 ? { extension: candidate.name } : {}),\n ...(commit !== undefined ? { commit } : {}),\n installedAt: new Date().toISOString(),\n }\n writeFileSync(join(targetDir, PROVENANCE_FILE), `${JSON.stringify(provenanceRecord, null, 2)}\\n`)\n }\n catch (err) {\n rmSync(targetDir, { recursive: true, force: true })\n if (backupDir)\n renameSync(backupDir, targetDir)\n throw err\n }\n if (backupDir)\n rmSync(backupDir, { recursive: true, force: true })\n\n return { name: definition.name, dir: targetDir, scope: opts.scope, provenance, ...(commit !== undefined ? { commit } : {}), warnings }\n }\n finally {\n rmSync(stage, { recursive: true, force: true })\n }\n}\n\n/**\n * Read `.install.json` provenance from an installed extension dir, or null.\n *\n * @param dir - Installed extension directory.\n */\nexport function readExtensionInstallProvenance(dir: string): ExtensionInstallProvenance | null {\n const raw = readJson(join(dir, PROVENANCE_FILE)) as Partial<ExtensionInstallProvenance> | null\n if (!raw || typeof raw.spec !== 'string' || typeof raw.source !== 'string')\n return null\n return {\n source: raw.source,\n spec: raw.spec,\n scope: raw.scope === 'project' ? 'project' : 'user',\n ...(typeof raw.extension === 'string' ? { extension: raw.extension } : {}),\n ...(typeof raw.commit === 'string' ? { commit: raw.commit } : {}),\n installedAt: typeof raw.installedAt === 'string' ? raw.installedAt : '',\n }\n}\n\n/**\n * A short name of an install spec: `owner/repo` with `@ref` when one is\n * pinned (the folder in the repository left out), an npm package with\n * `@version` when one is pinned. A spec that does not parse is returned as is.\n *\n * @param spec - An install spec (`Tahul/zidane#v9.0.4:extensions/goal`, `@scope/pkg`).\n * @example\n * ```ts\n * extensionSourceLabel('Tahul/zidane#v9.0.4:extensions/goal') // 'Tahul/zidane@v9.0.4'\n * extensionSourceLabel('@scope/pkg') // '@scope/pkg'\n * ```\n */\nexport function extensionSourceLabel(spec: string): string {\n try {\n const source = parseInstallSource(spec)\n return source.kind === 'github'\n ? `${source.owner}/${source.repo}${source.ref ? `@${source.ref}` : ''}`\n : `${source.pkg}${source.version ? `@${source.version}` : ''}`\n }\n catch {\n return spec.trim()\n }\n}\n\n/**\n * Where an installed extension came from (its `.install.json`), or `null`\n * for one not installed from a source (hand-written, linked, built in).\n *\n * @param dir - Installed extension directory.\n */\nexport function readExtensionInstallOrigin(dir: string): ExtensionInstallOrigin | null {\n const provenance = readExtensionInstallProvenance(dir)\n if (!provenance)\n return null\n return {\n spec: provenance.spec,\n label: extensionSourceLabel(provenance.spec),\n source: provenance.source,\n ...(provenance.commit !== undefined ? { commit: provenance.commit } : {}),\n ...(provenance.installedAt ? { installedAt: provenance.installedAt } : {}),\n }\n}\n\nfunction nameMismatch(expected: string, source: string, found: readonly string[]): ExtensionInstallError {\n const names = found.length > 0 ? `Found: ${found.join(', ')}.` : 'It holds no extension.'\n return new ExtensionInstallError('name-mismatch', `${source} has no extension named \"${expected}\". ${names}`, found)\n}\n\n/** Identifies an installed extension and where to look for extension folders. Used by {@link updateInstalledExtension} and {@link removeInstalledExtension}. */\nexport interface InstalledExtensionTargetOptions {\n /** The installed extension's directory (e.g. `LoadedExtension.dir`). */\n dir: string\n /** Working directory used to find the project root. @default process.cwd() */\n cwd?: string\n /** User home directory. @default os.homedir() */\n home?: string\n /** Storage prefix. @default '.zidane' */\n prefix?: string\n /** Extra trusted roots (`ZIDANE_EXTENSION_DIRS` / host scan paths). */\n extensionScanPaths?: readonly string[]\n}\n\n/**\n * Containment guard shared by update/remove: `dir` must be a DIRECT child\n * of a recognized extensions root (the four `.{agents,prefix}/extensions`\n * search paths, plus any host scan roots). Refuses anything else — these\n * functions delete directories and must never be pointable at arbitrary\n * paths (an inline/builtin extension has no dir; a hand-typed path is not\n * an install).\n */\nfunction assertInstalledExtensionDir(opts: InstalledExtensionTargetOptions): { dir: string, root: string, scope: ExtensionInstallScope } {\n const dir = resolve(opts.dir)\n const roots: Array<{ path: string, scope: ExtensionInstallScope }> = [\n ...projectUserPaths({\n subPath: 'extensions',\n ...(opts.cwd !== undefined ? { cwd: opts.cwd } : {}),\n ...(opts.home !== undefined ? { home: opts.home } : {}),\n ...(opts.prefix !== undefined ? { prefix: opts.prefix } : {}),\n }).map(p => ({ path: p.path, scope: p.source })),\n // Host scan roots are user-opted-in — user scope by convention.\n ...(opts.extensionScanPaths ?? []).map(p => ({ path: resolve(p), scope: 'user' as const })),\n ]\n const root = roots.find(r => dirname(dir) === r.path)\n if (!root)\n throw new ExtensionInstallError('not-installed', `${dir} is not inside an extensions folder, so it was left alone.`)\n return { dir, root: root.path, scope: root.scope }\n}\n\n/**\n * Delete an installed extension's directory. Works on any on-disk\n * extension (hand-authored ones too — no provenance required); the\n * containment guard is the safety boundary. The caller owns follow-up\n * (allowlist cleanup, registry reload).\n *\n * @param opts - The installed extension to remove.\n */\nexport function removeInstalledExtension(opts: InstalledExtensionTargetOptions): { dir: string } {\n const { dir } = assertInstalledExtensionDir(opts)\n if (!existsSync(dir))\n throw new ExtensionInstallError('not-installed', `${dir} does not exist.`)\n rmSync(dir, { recursive: true, force: true })\n return { dir }\n}\n\n/**\n * Cheap \"is there anything new?\" probe, no fetch of content:\n *\n * - GitHub (with a recorded commit): `git ls-remote` resolves the ref's\n * current SHA in one round-trip — equal SHA means up to date.\n * - npm: one registry metadata GET re-resolves the version/dist-tag —\n * an unchanged resolved provenance string means up to date.\n *\n * `null` = \"can't tell cheaply\" (no recorded commit, git missing,\n * ls-remote/parse failure) — the caller falls through to a full update,\n * which errors honestly if the network is actually down.\n */\nasync function checkRemoteUnchanged(\n source: ExtensionInstallSource,\n previous: ExtensionInstallProvenance,\n io: ExtensionInstallIo,\n): Promise<boolean | null> {\n if (source.kind === 'npm') {\n try {\n const { version } = await resolveNpmVersion(source, io.fetch ?? fetch)\n return `npm:${source.pkg}@${version}` === previous.source\n }\n catch {\n return null\n }\n }\n if (!previous.commit)\n return null\n const which = io.which ?? defaultWhich\n const exec = io.exec ?? defaultExec\n if (!which('git'))\n return null\n const url = `https://github.com/${source.owner}/${source.repo}.git`\n const refspecs = source.ref ? [`refs/heads/${source.ref}`, `refs/tags/${source.ref}`] : ['HEAD']\n // GIT_TERMINAL_PROMPT=0 — never let git prompt for credentials from\n // inside the TUI; an unreachable remote degrades to \"can't tell\" (null).\n const res = await exec('git', ['ls-remote', url, ...refspecs], { env: { GIT_TERMINAL_PROMPT: '0' } })\n if (!res.ok)\n return null\n const sha = res.stdout.trim().split('\\n')[0]?.split('\\t')[0]?.trim()\n if (!sha || !/^[0-9a-f]{40}$/.test(sha))\n return null\n return sha === previous.commit\n}\n\n/**\n * Re-run the recorded install for an extension: re-resolves the original\n * spec (so `owner/repo` follows the branch and `pkg` follows `latest`,\n * while pinned refs/versions stay pinned) and replaces the install\n * IN PLACE (same root the extension currently lives in, even a\n * `.agents/extensions` one). Requires `.install.json` provenance —\n * hand-authored extensions have nothing to update from.\n *\n * When the remote is provably unchanged (recorded commit matches\n * `git ls-remote`, or the npm version re-resolves identically), the\n * reinstall is skipped entirely and the result carries `upToDate: true`.\n *\n * @param opts - The installed extension to update, plus progress and IO overrides.\n */\nexport async function updateInstalledExtension(\n opts: InstalledExtensionTargetOptions & {\n onProgress?: (message: string) => void\n io?: ExtensionInstallIo\n },\n): Promise<ExtensionInstallResult & { previous: ExtensionInstallProvenance, upToDate: boolean }> {\n const { dir, root, scope } = assertInstalledExtensionDir(opts)\n const provenance = readExtensionInstallProvenance(dir)\n if (!provenance)\n throw new ExtensionInstallError('no-provenance', `${dir} has no .install.json. It was not installed from a source, so there is nothing to update from.`)\n\n const source = parseExtensionInstallSource(provenance.spec)\n opts.onProgress?.(`checking ${provenance.source} for changes…`)\n if (await checkRemoteUnchanged(source, provenance, opts.io ?? {}) === true) {\n return {\n name: basename(dir),\n dir,\n scope,\n provenance: provenance.source,\n ...(provenance.commit !== undefined ? { commit: provenance.commit } : {}),\n warnings: [],\n previous: provenance,\n upToDate: true,\n }\n }\n\n const result = await installExtensionFromSpec({\n source: provenance.spec,\n // Recorded without one (older hosts): the folder it was installed as, when the source holds several.\n ...(provenance.extension !== undefined ? { extension: provenance.extension } : { fallbackExtension: basename(dir) }),\n // Scope from where the extension ACTUALLY lives (the containment\n // root), not the recorded field — a stale/corrupt provenance scope\n // would otherwise self-perpetuate through every future update.\n scope,\n overwrite: true,\n installRoot: root,\n ...(opts.cwd !== undefined ? { cwd: opts.cwd } : {}),\n ...(opts.home !== undefined ? { home: opts.home } : {}),\n ...(opts.prefix !== undefined ? { prefix: opts.prefix } : {}),\n ...(opts.onProgress !== undefined ? { onProgress: opts.onProgress } : {}),\n ...(opts.io !== undefined ? { io: opts.io } : {}),\n })\n // The upstream may have renamed its definition — the fresh install then\n // landed in a sibling folder. Remove the superseded dir so an update\n // never leaves two generations installed side by side.\n if (result.dir !== dir)\n rmSync(dir, { recursive: true, force: true })\n return { ...result, previous: provenance, upToDate: false }\n}\n\n/**\n * Installs an extension again from another source, in place: the source\n * must hold an extension with the same name (else `name-mismatch`, with the\n * names found), the folder is replaced only once the new copy fetched,\n * installed its dependencies and validated (the install's transaction), and\n * `.install.json` records the new source, which later updates follow.\n * Works on any installed folder, with or without a recorded source.\n *\n * @param opts - The installed extension, the new source, progress and IO overrides.\n * @returns The install's result, the source it had (`null` when none was recorded) and the one it has now.\n */\nexport async function changeExtensionOrigin(\n opts: InstalledExtensionTargetOptions & {\n /** The new source spec (GitHub or npm, as {@link installExtensionFromSpec} takes it). */\n source: string\n onProgress?: (message: string) => void\n io?: ExtensionInstallIo\n },\n): Promise<ExtensionInstallResult & { previous: ExtensionInstallOrigin | null, origin: ExtensionInstallOrigin }> {\n const { dir, root, scope } = assertInstalledExtensionDir(opts)\n if (!existsSync(dir))\n throw new ExtensionInstallError('not-installed', `${dir} does not exist.`)\n const previous = readExtensionInstallOrigin(dir)\n const result = await installExtensionFromSpec({\n source: opts.source,\n expectName: basename(dir),\n scope,\n overwrite: true,\n installRoot: root,\n ...(opts.cwd !== undefined ? { cwd: opts.cwd } : {}),\n ...(opts.home !== undefined ? { home: opts.home } : {}),\n ...(opts.prefix !== undefined ? { prefix: opts.prefix } : {}),\n ...(opts.onProgress !== undefined ? { onProgress: opts.onProgress } : {}),\n ...(opts.io !== undefined ? { io: opts.io } : {}),\n })\n const origin = readExtensionInstallOrigin(result.dir)\n if (!origin)\n throw new Error(`unreachable: ${result.dir} was installed without .install.json`)\n return { ...result, previous, origin }\n}\n\n/** The scope's canonical `.{prefix}/extensions` write root. */\nfunction resolveInstallRoot(opts: { scope: ExtensionInstallScope, cwd?: string, home?: string, prefix?: string }): string {\n const prefix = (opts.prefix ?? '.zidane').replace(/^\\./, '')\n const paths = projectUserPaths({\n subPath: 'extensions',\n ...(opts.cwd !== undefined ? { cwd: opts.cwd } : {}),\n ...(opts.home !== undefined ? { home: opts.home } : {}),\n ...(opts.prefix !== undefined ? { prefix: opts.prefix } : {}),\n })\n const root = paths.find(p => p.source === opts.scope && p.path.includes(`.${prefix}`))\n if (!root)\n throw new Error(`unreachable: projectUserPaths yields a .${prefix} root per scope`)\n return root.path\n}\n\nasync function validateCandidate(\n candidate: ExtensionInstallCandidate,\n timeoutMs: number,\n): Promise<{ name: string, warning?: string }> {\n const entry = findEntryFile(candidate.dir)\n if (!entry)\n throw new ExtensionInstallError('no-extension', `${candidate.dir} has no index.{ts,tsx,mjs,js} entry.`)\n const version = checkZidaneVersion(candidate.dir)\n if (version?.level === 'error')\n throw new ExtensionInstallError('validate-failed', version.message)\n let mod: unknown\n try {\n mod = await withTimeout(\n importExtensionEntry(entry, candidate.dir),\n timeoutMs,\n `Timed out importing ${entry} after ${timeoutMs}ms.`,\n )\n }\n catch (err) {\n throw new ExtensionInstallError('validate-failed', `Cannot import the extension: ${errorMessage(err)}`)\n }\n finally {\n // The staged dir moves or is deleted next: nothing may stay cached under it.\n releaseExtensionModules(candidate.dir)\n }\n const m = (mod ?? {}) as Record<string, unknown>\n const exported = [m.default, m.extension].filter(value => value !== undefined)\n const candidateDef = definitionExport(exported)\n if (candidateDef === undefined) {\n throw new ExtensionInstallError('validate-failed', `Module at ${entry} does not export an extension definition (expected \\`default\\` or named \\`extension\\` with \\`apiVersion: 1\\`).`)\n }\n const validation = validateDefinition(candidateDef)\n if (!validation.ok)\n throw new ExtensionInstallError('validate-failed', validation.errors.map(issue => (issue.path ? `${issue.path}: ${issue.message}` : issue.message)).join('; '))\n const definition = { name: validation.definition.id }\n if (!/^[\\w.-]+$/.test(definition.name) || definition.name.startsWith('.'))\n throw new ExtensionInstallError('validate-failed', `Extension id \"${definition.name}\" is not folder-safe ([A-Za-z0-9_.-], no leading dot).`)\n const manifest = readExtensionManifest(candidate.dir).manifest\n if (manifest?.apiVersion !== undefined && manifest.apiVersion !== EXTENSION_API_VERSION)\n throw new ExtensionInstallError('validate-failed', `Unsupported extension API version \"${manifest.apiVersion}\" in manifest. This runtime supports apiVersion 1.`)\n if (manifest?.name && manifest.name !== definition.name)\n throw new ExtensionInstallError('validate-failed', `Manifest name \"${manifest.name}\" does not match the module's exported id \"${definition.name}\".`)\n return { name: definition.name, ...(version ? { warning: version.message } : {}) }\n}\n\n// ---------------------------------------------------------------------------\n// Dependency install\n// ---------------------------------------------------------------------------\n\nconst PM_COMMANDS: ReadonlyArray<{ cmd: string, args: readonly string[] }> = [\n // bun skips lifecycle scripts by default (trustedDependencies opt-in).\n { cmd: 'bun', args: ['install'] },\n { cmd: 'npm', args: ['install', '--ignore-scripts', '--no-audit', '--no-fund'] },\n { cmd: 'pnpm', args: ['install', '--ignore-scripts'] },\n { cmd: 'yarn', args: ['install', '--ignore-scripts'] },\n]\n\n/** Install deps when `dir/package.json` declares any. Returns null when skipped. */\nasync function installDependencies(\n dir: string,\n io: ExtensionInstallIo,\n onProgress?: (message: string) => void,\n): Promise<{ warnings: string[] } | null> {\n const pkg = readJson(join(dir, 'package.json')) as { dependencies?: Record<string, string> } | null\n if (!pkg?.dependencies || Object.keys(pkg.dependencies).length === 0)\n return null\n const exec = io.exec ?? defaultExec\n const which = io.which ?? defaultWhich\n const pm = PM_COMMANDS.find(p => which(p.cmd))\n if (!pm) {\n throw new ExtensionInstallError('no-package-manager', 'The extension has dependencies, but no package manager (bun, npm, pnpm or yarn) is on PATH.')\n }\n onProgress?.(`installing dependencies with ${pm.cmd}…`)\n const res = await exec(pm.cmd, pm.args, { cwd: dir })\n if (!res.ok)\n throw new ExtensionInstallError('deps-failed', `${pm.cmd} install failed: ${lastLine(res.stderr) || lastLine(res.stdout)}`)\n return { warnings: [] }\n}\n\n// ---------------------------------------------------------------------------\n// Shared helpers\n// ---------------------------------------------------------------------------\n\nfunction readJson(path: string): unknown {\n try {\n return JSON.parse(readFileSync(path, 'utf8')) as unknown\n }\n catch {\n return null\n }\n}\n","/**\n * `extensions.lock.json`: what the declarative config installed, next to the\n * config file it belongs to. One lock per config file (user, project), so a\n * project lock can be committed and replayed on another machine.\n *\n * Entries are keyed by {@link DeclaredExtension.key} (source identity\n * without ref or version). Directories are not recorded: they follow from\n * the scope and the id, and differ between machines.\n */\n\nimport type { ExtensionsConfigDiagnostic, ExtensionsConfigScope } from './config'\nimport { existsSync, readFileSync } from 'node:fs'\nimport { dirname, join } from 'node:path'\nimport { writeJsonFileAtomic } from '../../atomic-write'\n\n/** File name of the lock, beside `config.json`. */\nexport const EXTENSIONS_LOCK_FILE = 'extensions.lock.json'\n\n/** Format version written in every lock. A lock with another version is read as empty. */\nexport const EXTENSIONS_LOCK_VERSION = 1\n\n/** What the lock records for one declared extension. */\nexport interface ExtensionsLockEntry {\n /** The config `source` it was installed from, as written. A different one means the pin changed. */\n readonly source: string\n /** The extension picked from a collection, when one was. */\n readonly extension?: string\n /** The installed extension id (its folder name). */\n readonly id: string\n /** Resolved provenance: `npm:pkg@1.2.3`, `github:owner/repo@ref`, `local:./path`. */\n readonly resolved: string\n /** The extension's own version (package.json), when it has one. */\n readonly version?: string\n /** Exact commit SHA, for GitHub installs made with git. */\n readonly commit?: string\n /** `sha256-<base64>` of the installed files, when the host computed it. */\n readonly integrity?: string\n /** ISO 8601 time of the install. */\n readonly installedAt: string\n}\n\n/** The whole lock file. */\nexport interface ExtensionsLock {\n readonly lockfileVersion: typeof EXTENSIONS_LOCK_VERSION\n /** Entries by {@link DeclaredExtension.key}. */\n readonly extensions: Readonly<Record<string, ExtensionsLockEntry>>\n}\n\n/** A lock with no entries. */\nexport function emptyExtensionsLock(): ExtensionsLock {\n return { lockfileVersion: EXTENSIONS_LOCK_VERSION, extensions: {} }\n}\n\n/**\n * The lock path for a config file: `extensions.lock.json` in the same\n * directory.\n *\n * @param configPath - Path of the `config.json` the lock belongs to.\n */\nexport function extensionsLockPath(configPath: string): string {\n return join(dirname(configPath), EXTENSIONS_LOCK_FILE)\n}\n\nfunction optionalString(raw: Record<string, unknown>, key: string): Record<string, string> {\n const value = raw[key]\n return typeof value === 'string' && value !== '' ? { [key]: value } : {}\n}\n\n/**\n * Reads parsed lock JSON. Never throws: a lock with another version or a\n * broken shape reads as empty, a broken entry is dropped, each with a\n * warning (the next reconcile rewrites the lock).\n *\n * @param raw - The parsed JSON, or `undefined` when there is no file.\n * @param scope - The scope the lock belongs to, for diagnostics.\n */\nexport function parseExtensionsLock(raw: unknown, scope: ExtensionsConfigScope): { lock: ExtensionsLock, diagnostics: ExtensionsConfigDiagnostic[] } {\n const diagnostics: ExtensionsConfigDiagnostic[] = []\n if (raw === undefined)\n return { lock: emptyExtensionsLock(), diagnostics }\n const record = raw !== null && typeof raw === 'object' && !Array.isArray(raw) ? raw as Record<string, unknown> : null\n if (!record || record.lockfileVersion !== EXTENSIONS_LOCK_VERSION || record.extensions === null || typeof record.extensions !== 'object' || Array.isArray(record.extensions)) {\n diagnostics.push({ level: 'warning', scope, message: `${EXTENSIONS_LOCK_FILE} is not a version ${EXTENSIONS_LOCK_VERSION} lock. It is ignored and will be rewritten.` })\n return { lock: emptyExtensionsLock(), diagnostics }\n }\n const extensions: Record<string, ExtensionsLockEntry> = {}\n for (const [key, value] of Object.entries(record.extensions as Record<string, unknown>)) {\n const entry = value !== null && typeof value === 'object' && !Array.isArray(value) ? value as Record<string, unknown> : null\n if (!entry || typeof entry.source !== 'string' || typeof entry.id !== 'string' || typeof entry.resolved !== 'string') {\n diagnostics.push({ level: 'warning', scope, message: `Lock entry \"${key}\" is incomplete. It is ignored.` })\n continue\n }\n extensions[key] = {\n source: entry.source,\n id: entry.id,\n resolved: entry.resolved,\n installedAt: typeof entry.installedAt === 'string' ? entry.installedAt : '',\n ...optionalString(entry, 'extension'),\n ...optionalString(entry, 'version'),\n ...optionalString(entry, 'commit'),\n ...optionalString(entry, 'integrity'),\n }\n }\n return { lock: { lockfileVersion: EXTENSIONS_LOCK_VERSION, extensions }, diagnostics }\n}\n\n/**\n * Reads the lock at `path`. A missing file is an empty lock; unreadable\n * JSON is an empty lock with a warning.\n *\n * @param path - The lock file.\n * @param scope - The scope the lock belongs to, for diagnostics.\n */\nexport function readExtensionsLock(path: string, scope: ExtensionsConfigScope): { lock: ExtensionsLock, diagnostics: ExtensionsConfigDiagnostic[] } {\n if (!existsSync(path))\n return parseExtensionsLock(undefined, scope)\n let raw: unknown\n try {\n raw = JSON.parse(readFileSync(path, 'utf8'))\n }\n catch {\n raw = null\n }\n return parseExtensionsLock(raw, scope)\n}\n\n/**\n * Writes the lock atomically (`writeJsonFileAtomic`), entries and fields\n * in a stable order so a committed lock diffs cleanly.\n *\n * @param path - The lock file. Its directory is created when missing.\n * @param lock - The lock to write.\n */\nexport function writeExtensionsLock(path: string, lock: ExtensionsLock): void {\n const extensions: Record<string, ExtensionsLockEntry> = {}\n for (const key of Object.keys(lock.extensions).sort()) {\n const e = lock.extensions[key] as ExtensionsLockEntry\n extensions[key] = {\n source: e.source,\n ...(e.extension !== undefined ? { extension: e.extension } : {}),\n id: e.id,\n resolved: e.resolved,\n ...(e.version !== undefined ? { version: e.version } : {}),\n ...(e.commit !== undefined ? { commit: e.commit } : {}),\n ...(e.integrity !== undefined ? { integrity: e.integrity } : {}),\n installedAt: e.installedAt,\n }\n }\n writeJsonFileAtomic(path, { lockfileVersion: EXTENSIONS_LOCK_VERSION, extensions }, { ensureDir: true })\n}\n","/**\n * The reconcile planner: config entries + lock + what is on disk → the\n * actions that bring the disk in line with the config. Pure; {@link\n * reconcile} runs the plan through a port.\n *\n * Rules:\n *\n * - The lock pins. An entry already in the lock with the same `source`\n * is kept as it is; nothing is re-resolved unless `update` is set.\n * - A changed `source` (new ref, version or pick) reinstalls in place.\n * - A locked entry missing on disk (a fresh clone of a project) installs\n * the locked version: npm exactly, GitHub from the source (a commit\n * mismatch is reported by reconcile).\n * - An extension already installed from the same source, not in the\n * lock, is adopted without a fetch.\n * - Removing an entry removes only what the lock owns, and only when the\n * folder on disk still comes from that source; anything else is just\n * dropped from the lock.\n * - `enabled: false` stays installed (Settings still shows it).\n */\n\nimport type { DeclaredExtension, ExtensionsConfigDiagnostic, ExtensionsConfigScope } from './config'\nimport type { ExtensionsLock, ExtensionsLockEntry } from './lock'\nimport type { InstalledExtensionInfo } from './port'\nimport { installSpecIdentity } from './config'\n\n/** Why an install runs. */\nexport type InstallReason = 'new' | 'locked' | 'changed'\n\n/** One step of a plan. */\nexport type ReconcileAction\n = | {\n readonly kind: 'install'\n readonly entry: DeclaredExtension\n /** The spec to install: the entry's, or the locked npm version. */\n readonly spec: string\n readonly reason: InstallReason\n /** The previous install this one replaces, for `changed`. */\n readonly replaces?: InstalledExtensionInfo\n /** The lock entry being replayed or replaced. */\n readonly lock?: ExtensionsLockEntry\n }\n | { readonly kind: 'adopt', readonly entry: DeclaredExtension, readonly installed: InstalledExtensionInfo }\n | { readonly kind: 'update', readonly entry: DeclaredExtension, readonly installed: InstalledExtensionInfo, readonly lock: ExtensionsLockEntry }\n | { readonly kind: 'keep', readonly entry: DeclaredExtension, readonly installed: InstalledExtensionInfo, readonly lock: ExtensionsLockEntry }\n | { readonly kind: 'link', readonly entry: DeclaredExtension, readonly path: string }\n | { readonly kind: 'remove', readonly key: string, readonly lock: ExtensionsLockEntry, readonly installed: InstalledExtensionInfo }\n | { readonly kind: 'forget', readonly key: string, readonly lock: ExtensionsLockEntry }\n\n/** The actions for one scope, in run order. */\nexport interface ReconcilePlan {\n readonly scope: ExtensionsConfigScope\n readonly actions: readonly ReconcileAction[]\n readonly diagnostics: readonly ExtensionsConfigDiagnostic[]\n}\n\n/** Input of {@link planReconcile}. */\nexport interface PlanReconcileInput {\n readonly scope: ExtensionsConfigScope\n /** The scope's valid entries (`parseExtensionsConfig`). */\n readonly entries: readonly DeclaredExtension[]\n readonly lock: ExtensionsLock\n /** The scope's install root as it is now (`port.listInstalled`). */\n readonly installed: readonly InstalledExtensionInfo[]\n /** Re-resolve every remote entry (follow branches and dist-tags). Default `false`. */\n readonly update?: boolean\n}\n\n/**\n * The npm spec pinned to the locked version, or the entry's own spec.\n *\n * @param entry - The config entry.\n * @param lock - Its lock entry.\n */\nexport function pinnedSpec(entry: DeclaredExtension, lock: ExtensionsLockEntry): string {\n if (entry.location.kind !== 'remote' || entry.location.source.kind !== 'npm')\n return entry.installSpec\n const prefix = `npm:${entry.location.source.pkg}@`\n return lock.resolved.startsWith(prefix) ? `${entry.location.source.pkg}@${lock.resolved.slice(prefix.length)}` : entry.installSpec\n}\n\nfunction sameOrigin(installed: InstalledExtensionInfo, key: string): boolean {\n return installed.spec !== undefined && installSpecIdentity(installed.spec, installed.extension) === key\n}\n\n/**\n * Plans the reconcile of one scope. Removals come first, so a folder freed\n * by a removed entry can be reused by a new one.\n *\n * @param input - Entries, lock and the install root's contents.\n */\nexport function planReconcile(input: PlanReconcileInput): ReconcilePlan {\n const byId = new Map(input.installed.map(i => [i.id, i]))\n const declared = new Set(input.entries.map(e => e.key))\n const removals: ReconcileAction[] = []\n const actions: ReconcileAction[] = []\n const diagnostics: ExtensionsConfigDiagnostic[] = []\n\n for (const [key, lock] of Object.entries(input.lock.extensions)) {\n if (declared.has(key))\n continue\n const installed = lock.resolved.startsWith('local:') ? undefined : byId.get(lock.id)\n if (installed && sameOrigin(installed, key))\n removals.push({ kind: 'remove', key, lock, installed })\n else\n removals.push({ kind: 'forget', key, lock })\n }\n\n for (const entry of input.entries) {\n if (entry.location.kind === 'local') {\n actions.push({ kind: 'link', entry, path: entry.location.path })\n continue\n }\n const lock = input.lock.extensions[entry.key]\n const lockedDir = lock ? byId.get(lock.id) : undefined\n if (lock && (lock.source !== entry.source || lock.extension !== entry.extension)) {\n actions.push({ kind: 'install', entry, spec: entry.installSpec, reason: 'changed', lock, ...(lockedDir ? { replaces: lockedDir } : {}) })\n continue\n }\n if (lock && lockedDir) {\n actions.push(input.update ? { kind: 'update', entry, installed: lockedDir, lock } : { kind: 'keep', entry, installed: lockedDir, lock })\n continue\n }\n if (lock) {\n actions.push({ kind: 'install', entry, spec: pinnedSpec(entry, lock), reason: 'locked', lock })\n continue\n }\n const existing = input.installed.find(i => sameOrigin(i, entry.key))\n if (existing) {\n actions.push({ kind: 'adopt', entry, installed: existing })\n if (input.update)\n diagnostics.push({ level: 'warning', scope: input.scope, index: entry.index, message: `\"${entry.source}\" was already installed; it is adopted as is. Update again to re-resolve it.` })\n continue\n }\n actions.push({ kind: 'install', entry, spec: entry.installSpec, reason: 'new' })\n }\n return { scope: input.scope, actions: [...removals, ...actions], diagnostics }\n}\n","/**\n * Runs a {@link ReconcilePlan} through an {@link ExtensionsInstallPort} and\n * returns the next lock. One action at a time, in plan order. A failed\n * action keeps its previous lock entry (or none), so the lock always\n * describes what is really on disk; the caller writes it.\n */\n\nimport type { DeclaredExtension, ExtensionsConfigScope } from './config'\nimport type { ExtensionsLock, ExtensionsLockEntry } from './lock'\nimport type { ReconcileAction, ReconcilePlan } from './plan'\nimport type { ExtensionsInstallPort } from './port'\nimport { errorMessage } from '../../errors'\nimport { EXTENSIONS_LOCK_VERSION } from './lock'\nimport { planReconcile } from './plan'\n\n/** What happened to one action. */\nexport type ReconcileOutcome\n = | {\n readonly action: ReconcileAction\n readonly ok: true\n /** The extension id it concerns. */\n readonly id: string\n /** Non-fatal notices: host-version warnings, a moved GitHub pin. */\n readonly warnings: readonly string[]\n /** For `update`: the remote had nothing new. */\n readonly upToDate?: boolean\n /** For `install` and `update`: the folder installed. */\n readonly dir?: string\n }\n | {\n readonly action: ReconcileAction\n readonly ok: false\n readonly error: string\n /** The installer's error code (`ExtensionInstallError.code`), when it had one. */\n readonly code?: string\n }\n\n/** Result of {@link reconcile}. */\nexport interface ReconcileResult {\n readonly scope: ExtensionsConfigScope\n /** The lock to write. */\n readonly lock: ExtensionsLock\n readonly outcomes: readonly ReconcileOutcome[]\n /** Whether `lock` differs from the lock the run started from. */\n readonly changed: boolean\n}\n\n/** Options of {@link reconcile}. */\nexport interface ReconcileOptions {\n /** The lock the plan was made from. */\n readonly lock: ExtensionsLock\n /** Clock for `installedAt`. Default `() => new Date()`. */\n readonly now?: () => Date\n /** Stops the run: the current install rolls back, the rest are skipped. */\n readonly signal?: AbortSignal\n /** Status lines while an action runs. */\n readonly onProgress?: (action: ReconcileAction, message: string) => void\n}\n\nfunction lockEntryFor(\n entry: DeclaredExtension,\n rec: { id: string, resolved: string, version?: string | undefined, commit?: string | undefined, integrity?: string | undefined },\n installedAt: string,\n): ExtensionsLockEntry {\n return {\n source: entry.source,\n ...(entry.extension !== undefined ? { extension: entry.extension } : {}),\n id: rec.id,\n resolved: rec.resolved,\n ...(rec.version !== undefined ? { version: rec.version } : {}),\n ...(rec.commit !== undefined ? { commit: rec.commit } : {}),\n ...(rec.integrity !== undefined ? { integrity: rec.integrity } : {}),\n installedAt,\n }\n}\n\nfunction errorCode(err: unknown): string | undefined {\n const code = (err as { code?: unknown } | null)?.code\n return typeof code === 'string' ? code : undefined\n}\n\nfunction sameEntry(a: ExtensionsLockEntry | undefined, b: ExtensionsLockEntry | undefined): boolean {\n return JSON.stringify(a) === JSON.stringify(b)\n}\n\n/**\n * Runs `plan` and returns the next lock with one outcome per action.\n * Never throws for a failed action; it reports it.\n *\n * @param plan - From {@link planReconcile}.\n * @param port - The host effects.\n * @param options - The starting lock, clock, signal and progress.\n */\nexport async function reconcile(plan: ReconcilePlan, port: ExtensionsInstallPort, options: ReconcileOptions): Promise<ReconcileResult> {\n const now = options.now ?? (() => new Date())\n const next: Record<string, ExtensionsLockEntry> = { ...options.lock.extensions }\n const outcomes: ReconcileOutcome[] = []\n\n for (const action of plan.actions) {\n if (options.signal?.aborted) {\n outcomes.push({ action, ok: false, error: 'The reconcile was stopped.' })\n continue\n }\n const onProgress = options.onProgress ? (message: string): void => options.onProgress?.(action, message) : undefined\n const signalOpt = options.signal ? { signal: options.signal } : {}\n const progressOpt = onProgress ? { onProgress } : {}\n try {\n switch (action.kind) {\n case 'forget': {\n delete next[action.key]\n outcomes.push({ action, ok: true, id: action.lock.id, warnings: [] })\n break\n }\n case 'remove': {\n await port.remove({ dir: action.installed.dir })\n delete next[action.key]\n outcomes.push({ action, ok: true, id: action.lock.id, warnings: [] })\n break\n }\n case 'keep': {\n outcomes.push({ action, ok: true, id: action.lock.id, warnings: [] })\n break\n }\n case 'link': {\n const described = await port.describe({ dir: action.path })\n if (!described) {\n outcomes.push({ action, ok: false, error: `${action.path} is not an extension folder.` })\n break\n }\n if (described.hostVersion?.level === 'error') {\n outcomes.push({ action, ok: false, error: described.hostVersion.message, code: 'validate-failed' })\n break\n }\n const previous = next[action.entry.key]\n const resolved = `local:${action.entry.installSpec}`\n const installedAt = previous && previous.resolved === resolved ? previous.installedAt : now().toISOString()\n next[action.entry.key] = lockEntryFor(action.entry, { id: described.id, resolved, version: described.version }, installedAt)\n outcomes.push({ action, ok: true, id: described.id, warnings: described.hostVersion ? [described.hostVersion.message] : [] })\n break\n }\n case 'adopt': {\n const described = await port.describe({ dir: action.installed.dir })\n const id = described?.id ?? action.installed.id\n next[action.entry.key] = lockEntryFor(action.entry, {\n id,\n resolved: described?.resolved ?? action.installed.spec ?? action.entry.installSpec,\n version: described?.version,\n commit: described?.commit ?? action.installed.commit,\n integrity: described?.integrity,\n }, now().toISOString())\n outcomes.push({ action, ok: true, id, warnings: described?.hostVersion ? [described.hostVersion.message] : [] })\n break\n }\n case 'update': {\n const { entry, installed } = action\n if (installed.spec === entry.installSpec && installed.extension === entry.extension) {\n const rec = await port.update({ dir: installed.dir, ...signalOpt, ...progressOpt })\n next[entry.key] = lockEntryFor(entry, rec, rec.upToDate ? action.lock.installedAt : now().toISOString())\n outcomes.push({ action, ok: true, id: rec.id, warnings: rec.warnings, upToDate: rec.upToDate, dir: rec.dir })\n }\n else {\n // Installed from the locked pin (npm exact version): re-resolve the config's own spec.\n const rec = await port.install({ source: entry.installSpec, ...(entry.extension !== undefined ? { extension: entry.extension } : {}), scope: plan.scope, overwrite: true, ...signalOpt, ...progressOpt })\n next[entry.key] = lockEntryFor(entry, rec, now().toISOString())\n if (rec.id !== installed.id)\n await port.remove({ dir: installed.dir })\n outcomes.push({ action, ok: true, id: rec.id, warnings: rec.warnings, dir: rec.dir })\n }\n break\n }\n case 'install': {\n const { entry } = action\n const rec = await port.install({\n source: action.spec,\n ...(entry.extension !== undefined ? { extension: entry.extension } : {}),\n scope: plan.scope,\n overwrite: action.replaces !== undefined,\n ...signalOpt,\n ...progressOpt,\n })\n const warnings = [...rec.warnings]\n next[entry.key] = lockEntryFor(entry, rec, now().toISOString())\n if (action.replaces && action.replaces.id !== rec.id) {\n try {\n await port.remove({ dir: action.replaces.dir })\n }\n catch (err) {\n warnings.push(`The previous install at ${action.replaces.dir} could not be removed: ${errorMessage(err)}`)\n }\n }\n if (action.reason === 'locked' && action.lock?.commit && rec.commit && rec.commit !== action.lock.commit)\n warnings.push(`The lock pins commit ${action.lock.commit.slice(0, 12)}, but ${entry.source} now resolves to ${rec.commit.slice(0, 12)}. The lock was updated.`)\n outcomes.push({ action, ok: true, id: rec.id, warnings, dir: rec.dir })\n break\n }\n }\n }\n catch (err) {\n const code = errorCode(err)\n outcomes.push({ action, ok: false, error: errorMessage(err), ...(code !== undefined ? { code } : {}) })\n }\n }\n\n const keys = new Set([...Object.keys(options.lock.extensions), ...Object.keys(next)])\n const changed = [...keys].some(k => !sameEntry(options.lock.extensions[k], next[k]))\n return { scope: plan.scope, lock: { lockfileVersion: EXTENSIONS_LOCK_VERSION, extensions: next }, outcomes, changed }\n}\n\n/** Input of {@link syncDeclaredExtensions}. */\nexport interface SyncDeclaredExtensionsInput extends Omit<ReconcileOptions, 'lock'> {\n readonly scope: ExtensionsConfigScope\n readonly entries: readonly DeclaredExtension[]\n readonly lock: ExtensionsLock\n readonly port: ExtensionsInstallPort\n /** Re-resolve every remote entry. */\n readonly update?: boolean\n}\n\n/**\n * Lists the install root, plans and reconciles one scope.\n *\n * @param input - Scope, entries, lock, port and run options.\n */\nexport async function syncDeclaredExtensions(input: SyncDeclaredExtensionsInput): Promise<ReconcileResult & { readonly plan: ReconcilePlan }> {\n const installed = await input.port.listInstalled(input.scope)\n const plan = planReconcile({ scope: input.scope, entries: input.entries, lock: input.lock, installed, ...(input.update !== undefined ? { update: input.update } : {}) })\n const result = await reconcile(plan, input.port, {\n lock: input.lock,\n ...(input.now !== undefined ? { now: input.now } : {}),\n ...(input.signal !== undefined ? { signal: input.signal } : {}),\n ...(input.onProgress !== undefined ? { onProgress: input.onProgress } : {}),\n })\n return { ...result, plan }\n}\n","/**\n * The Node side of declarative install: where the config files live,\n * reading them, the default {@link ExtensionsInstallPort} over\n * `src/extensions/install.ts`, and a one-call sync of both scopes that\n * writes the locks.\n *\n * Config files:\n *\n * - user: `<configDir>/config.json` (the file `loadUserConfig` reads)\n * - project: `<project-root>/.zidane/config.json` (project root = git\n * root, else cwd, as in `projectUserPaths`)\n *\n * Each has its `extensions.lock.json` beside it. Relative local sources\n * resolve against the project root (project) or the config dir (user).\n */\n\nimport type { InstallIo } from '../../install/source'\nimport type { ZidaneVersionCheckOptions } from '../host-version'\nimport type { DeclaredExtension, ExtensionsConfigDiagnostic, ExtensionsConfigScope } from './config'\nimport type { ExtensionsLock } from './lock'\nimport type { ReconcileAction, ReconcilePlan } from './plan'\nimport type { DescribedExtension, ExtensionsInstallPort, InstalledExtensionInfo, InstalledExtensionRecord } from './port'\nimport type { ReconcileResult } from './reconcile'\nimport { createHash } from 'node:crypto'\nimport { existsSync, lstatSync, readdirSync, readFileSync, statSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { basename, dirname, join, relative, resolve } from 'node:path'\nimport { findGitRoot } from '../../chat/project-root'\nimport { projectUserPaths } from '../../chat/project-user-paths'\nimport { abortableInstallIo } from '../../install/source'\nimport { findEntryFile } from '../discovery'\nimport { checkZidaneVersion } from '../host-version'\nimport { installExtensionFromSpec, readExtensionInstallProvenance, removeInstalledExtension, updateInstalledExtension } from '../install'\nimport { parseExtensionsConfig } from './config'\nimport { extensionsLockPath, readExtensionsLock, writeExtensionsLock } from './lock'\nimport { syncDeclaredExtensions } from './reconcile'\n\n/** Where the two config files and their locks are. */\nexport interface ExtensionsConfigPaths {\n readonly user: { readonly config: string, readonly lock: string, readonly baseDir: string }\n readonly project: { readonly config: string, readonly lock: string, readonly baseDir: string }\n}\n\n/** Where to look: the user config dir, the working directory, the storage prefix. */\nexport interface ExtensionsConfigLocation {\n /** The user config dir (`ResolvedConfig.configDir`). */\n readonly configDir: string\n /** Default `process.cwd()`. */\n readonly cwd?: string\n /** Default `os.homedir()`. */\n readonly home?: string\n /** Default `.zidane`. */\n readonly prefix?: string\n}\n\n/**\n * The config and lock paths of both scopes.\n *\n * @param location - Config dir, cwd and prefix.\n */\nexport function extensionsConfigPaths(location: ExtensionsConfigLocation): ExtensionsConfigPaths {\n const cwd = location.cwd ?? process.cwd()\n const projectRoot = findGitRoot(cwd) ?? cwd\n const prefix = (location.prefix ?? '.zidane').replace(/^\\./, '')\n const userConfig = resolve(location.configDir, 'config.json')\n const projectConfig = resolve(projectRoot, `.${prefix}`, 'config.json')\n return {\n user: { config: userConfig, lock: extensionsLockPath(userConfig), baseDir: dirname(userConfig) },\n project: { config: projectConfig, lock: extensionsLockPath(projectConfig), baseDir: projectRoot },\n }\n}\n\n/**\n * Reads a config file as JSON. A missing file is `undefined`; unreadable\n * JSON is `undefined` with an error diagnostic.\n *\n * @param path - The config file.\n * @param scope - Its scope, for diagnostics.\n */\nexport function readExtensionsConfigFile(path: string, scope: ExtensionsConfigScope): { config: unknown, diagnostics: ExtensionsConfigDiagnostic[] } {\n if (!existsSync(path))\n return { config: undefined, diagnostics: [] }\n try {\n return { config: JSON.parse(readFileSync(path, 'utf8')) as unknown, diagnostics: [] }\n }\n catch (err) {\n return { config: undefined, diagnostics: [{ level: 'error', scope, message: `${path} is not valid JSON: ${err instanceof Error ? err.message : String(err)}` }] }\n }\n}\n\n/** One scope's parsed entries and lock. */\nexport interface LoadedExtensionsScope {\n readonly scope: ExtensionsConfigScope\n readonly configPath: string\n readonly lockPath: string\n readonly entries: readonly DeclaredExtension[]\n readonly lock: ExtensionsLock\n}\n\n/** Result of {@link loadExtensionsConfig}. */\nexport interface LoadedExtensionsConfig {\n readonly user: LoadedExtensionsScope\n readonly project: LoadedExtensionsScope\n readonly diagnostics: readonly ExtensionsConfigDiagnostic[]\n}\n\n/**\n * Reads and parses both config files and their locks. Feed `[user,\n * project]` to `createConfigSettingsLayer`.\n *\n * @param location - Config dir, cwd, home and prefix.\n */\nexport function loadExtensionsConfig(location: ExtensionsConfigLocation): LoadedExtensionsConfig {\n const paths = extensionsConfigPaths(location)\n const home = location.home ?? homedir()\n const diagnostics: ExtensionsConfigDiagnostic[] = []\n const load = (scope: ExtensionsConfigScope): LoadedExtensionsScope => {\n const p = paths[scope]\n const file = readExtensionsConfigFile(p.config, scope)\n const parsed = parseExtensionsConfig(file.config, { scope, baseDir: p.baseDir, home })\n const lock = readExtensionsLock(p.lock, scope)\n diagnostics.push(...file.diagnostics, ...parsed.diagnostics, ...lock.diagnostics)\n return { scope, configPath: p.config, lockPath: p.lock, entries: parsed.entries, lock: lock.lock }\n }\n return { user: load('user'), project: load('project'), diagnostics }\n}\n\nconst HASH_SKIP = new Set(['.git', 'node_modules', '.install.json'])\n\n/**\n * `sha256-<base64>` over the extension's files (paths and contents, in\n * sorted order), without `node_modules`, `.git` and `.install.json`.\n * Symlinked folders are not followed.\n *\n * @param dir - The extension directory.\n */\nexport function hashExtensionDir(dir: string): string {\n const hash = createHash('sha256')\n const walk = (current: string): void => {\n for (const name of readdirSync(current).sort()) {\n if (HASH_SKIP.has(name))\n continue\n const path = join(current, name)\n const link = lstatSync(path)\n const stat = link.isSymbolicLink() ? safeStat(path) : link\n if (!stat)\n continue\n if (stat.isDirectory()) {\n if (!link.isSymbolicLink())\n walk(path)\n }\n else if (stat.isFile()) {\n hash.update(relative(dir, path).split('\\\\').join('/'))\n hash.update('\\0')\n hash.update(readFileSync(path))\n hash.update('\\0')\n }\n }\n }\n walk(dir)\n return `sha256-${hash.digest('base64')}`\n}\n\nfunction safeStat(path: string): ReturnType<typeof statSync> | undefined {\n try {\n return statSync(path)\n }\n catch {\n return undefined\n }\n}\n\nfunction readVersion(dir: string): string | undefined {\n try {\n const pkg = JSON.parse(readFileSync(join(dir, 'package.json'), 'utf8')) as { version?: unknown }\n return typeof pkg.version === 'string' && pkg.version ? pkg.version : undefined\n }\n catch {\n return undefined\n }\n}\n\n/** Options of {@link createNodeInstallPort}. */\nexport interface NodeInstallPortOptions {\n /** Default `process.cwd()`. */\n readonly cwd?: string\n /** Default `os.homedir()`. */\n readonly home?: string\n /** Default `.zidane`. */\n readonly prefix?: string\n /** Extra trusted extension roots (`ZIDANE_EXTENSION_DIRS`), for update and remove. */\n readonly extensionScanPaths?: readonly string[]\n /** Network and process seams, for tests. */\n readonly io?: InstallIo\n /** Host-version check seams, for tests. */\n readonly hostVersion?: ZidaneVersionCheckOptions\n}\n\n/**\n * The default port: `installExtensionFromSpec`, `updateInstalledExtension`\n * and `removeInstalledExtension`, plus `checkZidaneVersion` for local\n * folders and a content hash for the lock's `integrity`.\n *\n * @param options - cwd, home, prefix, scan roots and test seams.\n */\nexport function createNodeInstallPort(options: NodeInstallPortOptions = {}): ExtensionsInstallPort {\n const where = {\n ...(options.cwd !== undefined ? { cwd: options.cwd } : {}),\n ...(options.home !== undefined ? { home: options.home } : {}),\n ...(options.prefix !== undefined ? { prefix: options.prefix } : {}),\n }\n const prefix = (options.prefix ?? '.zidane').replace(/^\\./, '')\n // The root installs write to: the scope's `.{prefix}/extensions` (same choice as install.ts' resolveInstallRoot).\n const installRoot = (scope: ExtensionsConfigScope): string => {\n const root = projectUserPaths({ subPath: 'extensions', ...where }).find(p => p.source === scope && p.path.includes(`.${prefix}/`))\n if (!root)\n throw new Error(`unreachable: projectUserPaths yields a .${prefix} root per scope`)\n return root.path\n }\n const record = (r: { name: string, dir: string, provenance: string, commit?: string, warnings: readonly string[] }): InstalledExtensionRecord => {\n const version = readVersion(r.dir)\n return {\n id: r.name,\n dir: r.dir,\n resolved: r.provenance,\n ...(version !== undefined ? { version } : {}),\n ...(r.commit !== undefined ? { commit: r.commit } : {}),\n integrity: hashExtensionDir(r.dir),\n warnings: r.warnings,\n }\n }\n const ioFor = (signal: AbortSignal | undefined): InstallIo | undefined => signal ? abortableInstallIo(options.io, signal) : options.io\n return {\n listInstalled: async (scope) => {\n const root = installRoot(scope)\n let names: string[]\n try {\n names = readdirSync(root).sort()\n }\n catch {\n return []\n }\n const out: InstalledExtensionInfo[] = []\n for (const name of names) {\n const dir = join(root, name)\n if (name.startsWith('.') || !safeStat(dir)?.isDirectory())\n continue\n const prov = readExtensionInstallProvenance(dir)\n out.push({\n id: name,\n dir,\n ...(prov ? { spec: prov.spec } : {}),\n ...(prov?.extension !== undefined ? { extension: prov.extension } : {}),\n ...(prov?.commit !== undefined ? { commit: prov.commit } : {}),\n })\n }\n return out\n },\n install: async (req) => {\n const io = ioFor(req.signal)\n const result = await installExtensionFromSpec({\n source: req.source,\n ...(req.extension !== undefined ? { extension: req.extension } : {}),\n scope: req.scope,\n overwrite: req.overwrite,\n ...where,\n ...(req.onProgress !== undefined ? { onProgress: req.onProgress } : {}),\n ...(io !== undefined ? { io } : {}),\n })\n return record(result)\n },\n update: async (req) => {\n const io = ioFor(req.signal)\n const result = await updateInstalledExtension({\n dir: req.dir,\n ...where,\n ...(options.extensionScanPaths !== undefined ? { extensionScanPaths: options.extensionScanPaths } : {}),\n ...(req.onProgress !== undefined ? { onProgress: req.onProgress } : {}),\n ...(io !== undefined ? { io } : {}),\n })\n return { ...record(result), upToDate: result.upToDate }\n },\n remove: async (req) => {\n removeInstalledExtension({\n dir: req.dir,\n ...where,\n ...(options.extensionScanPaths !== undefined ? { extensionScanPaths: options.extensionScanPaths } : {}),\n })\n },\n describe: async (req) => {\n if (!safeStat(req.dir)?.isDirectory() || !findEntryFile(req.dir))\n return null\n const prov = readExtensionInstallProvenance(req.dir)\n const version = readVersion(req.dir)\n const hostVersion = checkZidaneVersion(req.dir, options.hostVersion)\n const described: DescribedExtension = {\n id: basename(req.dir),\n ...(version !== undefined ? { version } : {}),\n integrity: hashExtensionDir(req.dir),\n ...(prov ? { resolved: prov.source } : {}),\n ...(prov?.commit !== undefined ? { commit: prov.commit } : {}),\n hostVersion,\n }\n return described\n },\n }\n}\n\n/** Options of {@link syncExtensionsConfigFiles}. */\nexport interface SyncExtensionsConfigFilesOptions extends ExtensionsConfigLocation {\n /**\n * Scopes to reconcile. Installing runs the extension's code once (the\n * validation import), so a host passes `'project'` only for a trusted\n * project.\n */\n readonly scopes: readonly ExtensionsConfigScope[]\n /** Default `createNodeInstallPort` over the same location. */\n readonly port?: ExtensionsInstallPort\n /** Re-resolve every remote entry. */\n readonly update?: boolean\n readonly signal?: AbortSignal\n readonly now?: () => Date\n readonly onProgress?: (scope: ExtensionsConfigScope, action: ReconcileAction, message: string) => void\n}\n\n/** Result of {@link syncExtensionsConfigFiles}. */\nexport interface SyncExtensionsConfigFilesResult {\n readonly config: LoadedExtensionsConfig\n /** One result per reconciled scope. */\n readonly results: ReadonlyArray<ReconcileResult & { readonly plan: ReconcilePlan }>\n}\n\n/**\n * Loads both config files, reconciles the requested scopes and writes each\n * lock that changed (atomically). A scope with no entries and no lock\n * writes nothing.\n *\n * @param options - Location, scopes, port and run options.\n */\nexport async function syncExtensionsConfigFiles(options: SyncExtensionsConfigFilesOptions): Promise<SyncExtensionsConfigFilesResult> {\n const config = loadExtensionsConfig(options)\n const port = options.port ?? createNodeInstallPort({\n ...(options.cwd !== undefined ? { cwd: options.cwd } : {}),\n ...(options.home !== undefined ? { home: options.home } : {}),\n ...(options.prefix !== undefined ? { prefix: options.prefix } : {}),\n })\n const results: Array<ReconcileResult & { plan: ReconcilePlan }> = []\n for (const scope of options.scopes) {\n const loaded = config[scope]\n const onProgress = options.onProgress\n const result = await syncDeclaredExtensions({\n scope,\n entries: loaded.entries,\n lock: loaded.lock,\n port,\n ...(options.update !== undefined ? { update: options.update } : {}),\n ...(options.signal !== undefined ? { signal: options.signal } : {}),\n ...(options.now !== undefined ? { now: options.now } : {}),\n ...(onProgress ? { onProgress: (action: ReconcileAction, message: string) => onProgress(scope, action, message) } : {}),\n })\n if (result.changed)\n writeExtensionsLock(loaded.lockPath, result.lock)\n results.push(result)\n }\n return { config, results }\n}\n","/**\n * Declarative install inside a running host. A host that owns an extension\n * set (the daemon per folder, the TUI and the desktop app in local mode)\n * attaches each registry it builds to one {@link ExtensionsConfigSync}:\n *\n * - it reconciles the `extensions` entries of the user and project\n * `config.json` in the background (`syncExtensionsConfigFiles`), once at\n * the first attach and again when a config or lock file changes, one run\n * at a time per scope. Project entries run only for a target whose\n * project is trusted (installing runs the extension's code);\n * - it hands each target the result ({@link ExtensionsConfigSyncReport}),\n * which the host applies to its registry with\n * {@link applyExtensionsConfigReport}: installed, updated and removed\n * folders go through `reloadChangedExtensions`, unlinked ones unload,\n * `enabled` flags follow the config, and failures become inactive rows\n * (where Settings shows install errors).\n *\n * A failed fetch (offline) leaves the previous install and lock entry in\n * place: `reconcile` keeps the lock of a failed action.\n *\n * At build time {@link configuredExtensions} gives the folders config\n * entries link in place and the ids they keep disabled, for\n * `discoverAndBuildExtensionRegistry`.\n */\n\nimport type { LogSink } from '../../logger'\nimport type { LinkedExtensionDir } from '../discovery'\nimport type { NewExtensionFolder, ReloadChangedResult } from '../runtime/reload'\nimport type { ExtensionRegistry, LoadedExtension } from '../types'\nimport type { ExtensionsConfigDiagnostic, ExtensionsConfigScope } from './config'\nimport type { ExtensionsConfigLocation, LoadedExtensionsConfig } from './node'\nimport type { ReconcilePlan } from './plan'\nimport type { ExtensionsInstallPort } from './port'\nimport type { ReconcileResult } from './reconcile'\nimport { existsSync, readFileSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { basename, resolve } from 'node:path'\nimport { errorMessage } from '../../errors'\nimport { extensionRuntimeOf } from '../register'\nimport { registryViewState } from '../runtime/registry-view'\nimport { reloadChangedExtensions } from '../runtime/reload'\nimport { localExtensionId, resolveLocalSource } from './config'\nimport { extensionsConfigPaths, loadExtensionsConfig, syncExtensionsConfigFiles } from './node'\n\n/** What config entries change in a registry build: linked folders and disabled ids. */\nexport interface ConfiguredExtensions {\n /** Folders local entries link in place, once a reconcile recorded them in the lock. */\n readonly links: readonly LinkedExtensionDir[]\n /** Ids of entries with `enabled: false` (the lock's id, or a local folder's name). */\n readonly disabled: readonly string[]\n}\n\n/**\n * Reads both config files and their locks: the folders to load in place and\n * the ids to load disabled. Project entries count only when `trustProject`.\n * Never throws (a broken file reads as no entries).\n *\n * @param location - Config dir, cwd, home and prefix.\n * @param options - Whether the project's entries apply.\n * @param options.trustProject - The project-extensions trust of the build.\n */\nexport function configuredExtensions(location: ExtensionsConfigLocation, options: { trustProject: boolean }): ConfiguredExtensions {\n let loaded: LoadedExtensionsConfig\n try {\n loaded = loadExtensionsConfig(location)\n }\n catch {\n return { links: [], disabled: [] }\n }\n const links: LinkedExtensionDir[] = []\n const disabled: string[] = []\n for (const scope of options.trustProject ? [loaded.project, loaded.user] : [loaded.user]) {\n for (const entry of scope.entries) {\n const lock = scope.lock.extensions[entry.key]\n if (entry.location.kind === 'local' && lock?.resolved.startsWith('local:'))\n links.push({ dir: entry.location.path, source: scope.scope })\n const id = lock?.id ?? (entry.location.kind === 'local' ? localExtensionId(entry.location.path) : undefined)\n if (!entry.enabled && id !== undefined)\n disabled.push(id)\n }\n }\n return { links, disabled }\n}\n\n/** What happened to one config entry (or lock entry) in a reconcile. */\nexport type ConfigSyncStatus = 'installed' | 'updated' | 'up-to-date' | 'kept' | 'adopted' | 'linked' | 'removed' | 'unlinked' | 'forgotten' | 'failed'\n\n/** One entry's outcome, as hosts log and show it. */\nexport interface ConfigSyncItem {\n /** What the reconcile did with the entry. */\n readonly status: ConfigSyncStatus\n /** The config `source` (or the lock's, for a dropped entry). */\n readonly source: string\n /** The extension id, when known. */\n readonly id?: string\n /** For `failed`: why. */\n readonly error?: string\n /** Non-fatal notices (host-version warnings, a moved GitHub pin). */\n readonly warnings: readonly string[]\n}\n\n/** The result of one scope's reconcile, handed to every attached target. */\nexport interface ExtensionsConfigSyncReport {\n /** The config scope that was reconciled (user or project). */\n readonly scope: ExtensionsConfigScope\n /** The `config.json` the entries came from. */\n readonly configPath: string\n /** Each entry's outcome, in config order. */\n readonly items: readonly ConfigSyncItem[]\n /** Folders installed, updated, replaced or removed: reload them. */\n readonly changedDirs: readonly string[]\n /** Folders local entries link in place. */\n readonly linkedDirs: readonly string[]\n /** Folders whose entry was dropped from the config: unload them. */\n readonly unlinkedDirs: readonly string[]\n /** The scope's entries with a known id, and whether they may load. */\n readonly entries: ReadonlyArray<{ readonly id: string, readonly enabled: boolean }>\n /** Problems found in the config file itself (bad entries, unknown keys). */\n readonly diagnostics: readonly ExtensionsConfigDiagnostic[]\n /**\n * `true`: the result of an earlier run, given to a target that attached\n * after it (its registry was built from the disk the run left). Folders\n * the registry already holds are not reloaded.\n */\n readonly replay: boolean\n}\n\n/**\n * The inactive rows of a report's failures: named after the entry's source,\n * carrying the reason.\n *\n * @param report - A reconcile report.\n */\nexport function configSyncFailures(report: ExtensionsConfigSyncReport): LoadedExtension[] {\n return report.items.filter(item => item.status === 'failed').map(item => ({\n name: item.source,\n source: report.scope,\n error: `Installing \"${item.source}\" from ${report.configPath} failed: ${item.error ?? 'unknown error'}`,\n }))\n}\n\n/** Converts a reconcile result into the report hosts apply. */\nfunction toReport(scope: ExtensionsConfigScope, config: LoadedExtensionsConfig, result: ReconcileResult & { readonly plan: ReconcilePlan }, baseDir: string, home: string): ExtensionsConfigSyncReport {\n const items: ConfigSyncItem[] = []\n const changedDirs: string[] = []\n const linkedDirs: string[] = []\n const unlinkedDirs: string[] = []\n for (const outcome of result.outcomes) {\n const action = outcome.action\n const source = 'entry' in action ? action.entry.source : action.lock.source\n const lockId = 'lock' in action ? action.lock?.id : undefined\n if (!outcome.ok) {\n items.push({ status: 'failed', source, ...(lockId !== undefined ? { id: lockId } : {}), error: outcome.error, warnings: [] })\n continue\n }\n const item = (status: ConfigSyncStatus): void => {\n items.push({ status, source, id: outcome.id, warnings: outcome.warnings })\n }\n switch (action.kind) {\n case 'install':\n item('installed')\n if (outcome.dir !== undefined)\n changedDirs.push(outcome.dir)\n if (action.replaces && action.replaces.dir !== outcome.dir)\n changedDirs.push(action.replaces.dir)\n break\n case 'update':\n item(outcome.upToDate ? 'up-to-date' : 'updated')\n if (!outcome.upToDate && outcome.dir !== undefined)\n changedDirs.push(outcome.dir)\n if (outcome.dir !== undefined && outcome.dir !== action.installed.dir)\n changedDirs.push(action.installed.dir)\n break\n case 'keep':\n item('kept')\n break\n case 'adopt':\n item('adopted')\n break\n case 'link':\n item('linked')\n linkedDirs.push(action.path)\n break\n case 'remove':\n item('removed')\n changedDirs.push(action.installed.dir)\n break\n case 'forget':\n if (action.lock.resolved.startsWith('local:')) {\n item('unlinked')\n unlinkedDirs.push(resolveLocalSource(action.lock.resolved.slice('local:'.length), baseDir, home))\n }\n else {\n item('forgotten')\n }\n break\n }\n }\n const loaded = config[scope]\n const entries = loaded.entries.flatMap((entry) => {\n const id = result.lock.extensions[entry.key]?.id ?? (entry.location.kind === 'local' ? localExtensionId(entry.location.path) : undefined)\n return id !== undefined ? [{ id, enabled: entry.enabled }] : []\n })\n const diagnostics = [...config.diagnostics.filter(d => d.scope === scope), ...result.plan.diagnostics]\n return { scope, configPath: loaded.configPath, items, changedDirs, linkedDirs, unlinkedDirs, entries, diagnostics, replay: false }\n}\n\n/** A registry a host keeps in line with the config. */\nexport interface ExtensionsConfigSyncTarget {\n /** The folder the registry was built for: picks the project config. */\n readonly cwd: string\n /** Whether the project's entries apply (the build's project-extensions trust). */\n readonly trustProject: () => boolean\n /**\n * Applies a report to the registry (usually {@link applyExtensionsConfigReport}). Its errors are logged.\n * Called without awaiting the previous apply (the scope's next run does not wait for it): a host that\n * waits (for runs to end) queues the reports itself, in call order.\n */\n readonly apply: (report: ExtensionsConfigSyncReport) => void | Promise<void>\n}\n\n/** A level and a line, for the host's log. */\nexport type ConfigSyncLog = (level: 'info' | 'warn' | 'error', message: string) => void\n\n/** Options of {@link createExtensionsConfigSync}. */\nexport interface ExtensionsConfigSyncOptions {\n /** The user config dir (`ResolvedConfig.paths.configDir`). */\n readonly configDir: string\n /** Default `.zidane`. */\n readonly prefix?: string\n /** Default `os.homedir()`. */\n readonly home?: string\n /** The install port of a scope run from `cwd`. Default `createNodeInstallPort`. A test seam. */\n readonly port?: (scope: ExtensionsConfigScope, cwd: string) => ExtensionsInstallPort\n /** Where outcomes and errors go. Default: warnings and errors to the console. */\n readonly log?: ConfigSyncLog\n /**\n * Calls `onChange` after `file` changes (hosts pass `watchFileChanges`,\n * which follows atomic replaces and polls). Returns the stop. Absent or\n * `false`: no watching, the config applies at attach only.\n */\n readonly watch?: false | ((file: string, onChange: () => void) => () => void)\n /** Clock for the lock's `installedAt`. */\n readonly now?: () => Date\n}\n\n/** The process's declarative-install coordinator. */\nexport interface ExtensionsConfigSync {\n /**\n * Follows the config for one registry. Reconciles in the background the\n * scopes no run covered yet; a scope already reconciled replays its last\n * report to the target. Returns the detach.\n */\n attach: (target: ExtensionsConfigSyncTarget) => () => void\n /** Resolves once no scope run (and no apply it started) is in flight. */\n settled: () => Promise<void>\n /** Stops watching; runs in flight finish but apply nothing. */\n close: () => void\n}\n\ninterface ScopeState {\n readonly scope: ExtensionsConfigScope\n readonly configPath: string\n readonly lockPath: string\n readonly baseDir: string\n readonly targets: Set<ExtensionsConfigSyncTarget>\n running?: Promise<void>\n again: boolean\n /** Targets attached while a run was in flight and not yet handed its report: replayed when the run ends. */\n readonly pending: Set<ExtensionsConfigSyncTarget>\n last?: ExtensionsConfigSyncReport\n /** The config and lock contents the last run left: a change event that matches is the run's own write. */\n stamp?: string\n stopWatch?: () => void\n}\n\nfunction readText(path: string): string {\n try {\n return readFileSync(path, 'utf8')\n }\n catch {\n return ''\n }\n}\n\nconst defaultLog: ConfigSyncLog = (level, message) => {\n if (level !== 'info')\n console.warn(`[extensions] ${message}`)\n}\n\nfunction logReport(report: ExtensionsConfigSyncReport, log: ConfigSyncLog): void {\n for (const d of report.diagnostics)\n log(d.level === 'error' ? 'error' : 'warn', `${report.configPath}${d.index !== undefined ? ` entry ${d.index}` : ''}: ${d.message}`)\n for (const item of report.items) {\n const name = item.id !== undefined && item.id !== item.source ? `${item.id} (${item.source})` : item.source\n if (item.status === 'failed')\n log('error', `config extension ${name} failed: ${item.error}`)\n else if (item.status !== 'kept' && item.status !== 'linked' && item.status !== 'up-to-date')\n log('info', `config extension ${name} ${item.status}`)\n for (const warning of item.warnings)\n log('warn', `config extension ${name}: ${warning}`)\n }\n}\n\n/**\n * Creates the coordinator. One per process: scopes are keyed by config file,\n * so every registry of the same user (and project) shares one run.\n *\n * @param options - Config dir, prefix, home, and the port, log and watch seams.\n * @returns The coordinator.\n */\nexport function createExtensionsConfigSync(options: ExtensionsConfigSyncOptions): ExtensionsConfigSync {\n const log = options.log ?? defaultLog\n const home = options.home ?? homedir()\n const watchFile = options.watch === false ? undefined : options.watch\n const states = new Map<string, ScopeState>()\n /** Applies in flight, for {@link ExtensionsConfigSync.settled}. */\n const applies = new Set<Promise<void>>()\n let closed = false\n\n const location = (cwd: string): ExtensionsConfigLocation => ({\n configDir: options.configDir,\n cwd,\n home,\n ...(options.prefix !== undefined ? { prefix: options.prefix } : {}),\n })\n const stampOf = (s: ScopeState): string => `${readText(s.configPath)}\\0${readText(s.lockPath)}`\n const eligible = (s: ScopeState): ExtensionsConfigSyncTarget[] => [...s.targets].filter(t => s.scope === 'user' || t.trustProject())\n\n // Starts every apply at once, in order, without awaiting: one target waiting for its runs must not hold the scope.\n const deliver = (report: ExtensionsConfigSyncReport, targets: readonly ExtensionsConfigSyncTarget[]): void => {\n for (const target of targets) {\n if (closed)\n return\n const apply: Promise<void> = (async () => target.apply(report))()\n .catch((err: unknown) => log('error', `applying ${report.configPath} failed: ${errorMessage(err)}`))\n .finally(() => applies.delete(apply))\n applies.add(apply)\n }\n }\n\n const runOnce = async (s: ScopeState): Promise<void> => {\n const first = eligible(s)[0]\n if (!first)\n return\n let report: ExtensionsConfigSyncReport\n // Read before the sync: an edit saved during it must not pass for the run's own write.\n const configBefore = readText(s.configPath)\n try {\n const { config, results } = await syncExtensionsConfigFiles({\n ...location(first.cwd),\n scopes: [s.scope],\n ...(options.port ? { port: options.port(s.scope, first.cwd) } : {}),\n ...(options.now ? { now: options.now } : {}),\n })\n report = toReport(s.scope, config, results[0]!, s.baseDir, home)\n }\n catch (err) {\n // Reading or writing the files failed: nothing changed on disk that a target must reload.\n report = { scope: s.scope, configPath: s.configPath, items: [{ status: 'failed', source: s.configPath, error: errorMessage(err), warnings: [] }], changedDirs: [], linkedDirs: [], unlinkedDirs: [], entries: [], diagnostics: [], replay: false }\n }\n s.stamp = `${configBefore}\\0${readText(s.lockPath)}`\n if (readText(s.configPath) !== configBefore)\n s.again = true\n s.last = report\n logReport(report, log)\n const targets = eligible(s)\n for (const target of targets)\n s.pending.delete(target)\n deliver(report, targets)\n }\n\n const kick = (s: ScopeState): void => {\n if (closed)\n return\n if (s.running) {\n s.again = true\n return\n }\n s.running = (async () => {\n try {\n for (;;) {\n s.again = false\n await runOnce(s)\n if (!s.again || closed)\n return\n }\n }\n catch (err) {\n log('error', `reconciling ${s.configPath} failed: ${errorMessage(err)}`)\n }\n finally {\n // In the same step that ends the run: a later attach sees no run and replays by itself.\n s.running = undefined\n const missed = [...s.pending].filter(t => s.targets.has(t) && (s.scope === 'user' || t.trustProject()))\n s.pending.clear()\n if (missed.length > 0 && !closed) {\n if (s.last)\n deliver({ ...s.last, replay: true }, missed)\n else\n kick(s)\n }\n }\n })()\n }\n\n const stateFor = (scope: ExtensionsConfigScope, paths: { config: string, lock: string, baseDir: string }): ScopeState => {\n const key = `${scope}\\0${paths.config}`\n let s = states.get(key)\n if (!s) {\n s = { scope, configPath: paths.config, lockPath: paths.lock, baseDir: paths.baseDir, targets: new Set(), again: false, pending: new Set() }\n states.set(key, s)\n }\n return s\n }\n\n const startWatch = (s: ScopeState): void => {\n if (!watchFile || s.stopWatch)\n return\n const onChange = (): void => {\n if (stampOf(s) !== s.stamp && eligible(s).length > 0)\n kick(s)\n }\n const stops = [watchFile(s.configPath, onChange), watchFile(s.lockPath, onChange)]\n s.stopWatch = () => {\n for (const stop of stops) stop()\n }\n }\n\n const stopWatch = (s: ScopeState): void => {\n s.stopWatch?.()\n s.stopWatch = undefined\n }\n\n return {\n attach: (target) => {\n if (closed)\n return () => undefined\n const paths = extensionsConfigPaths(location(target.cwd))\n const scopes = [stateFor('user', paths.user), stateFor('project', paths.project)]\n for (const s of scopes) {\n s.targets.add(target)\n startWatch(s)\n if (s.scope === 'project' && !target.trustProject())\n continue\n if (s.running) {\n // The run hands it its report, or replays the last one when it ends.\n s.pending.add(target)\n continue\n }\n if (s.last && s.stamp === stampOf(s)) {\n deliver({ ...s.last, replay: true }, [target])\n }\n else {\n kick(s)\n }\n }\n return () => {\n for (const s of scopes) {\n s.targets.delete(target)\n s.pending.delete(target)\n if (s.targets.size === 0)\n stopWatch(s)\n }\n }\n },\n settled: async () => {\n for (;;) {\n const running = [...applies, ...[...states.values()].flatMap(s => (s.running ? [s.running] : []))]\n if (running.length === 0)\n return\n await Promise.all(running)\n }\n },\n close: () => {\n closed = true\n for (const s of states.values())\n stopWatch(s)\n },\n }\n}\n\n/** Options of {@link applyExtensionsConfigReport}. */\nexport interface ApplyConfigReportOptions {\n /** How a new folder under a scan root loads (the host's watcher rule). Linked folders load without it. */\n readonly classify?: (dir: string) => NewExtensionFolder | undefined\n /** Whether the host lets `id` run (its allowlist). Default: every id. */\n readonly allowed?: (id: string) => boolean\n /** How long one extension import may take. Default 10 s. */\n readonly importTimeoutMs?: number\n /** Where load warnings go. */\n readonly sink?: LogSink\n /** Node hosts: the folder compiled extension code is kept in. */\n readonly compileCache?: string\n}\n\n/**\n * Applies a report to a live registry, one extension at a time: changed\n * folders through `reloadChangedExtensions` (loaded, reloaded or unloaded\n * in place), linked folders it does not hold yet loaded, unlinked ones\n * unloaded, each held entry's `enabled` set to what the config and\n * `allowed` say (a reload of that extension), and the report's failures\n * listed as inactive rows (`config:<scope>`). Never rejects for an\n * extension's fault.\n *\n * @param registry - A registry from `buildExtensionRegistry` (or a view of one).\n * @param report - From an {@link ExtensionsConfigSync} target's `apply`.\n * @param options - Classify, allowlist, import bound, sink and compile cache.\n * @returns What loaded, reloaded and unloaded; `needsRebuild` when the registry holds no runtime to load into.\n */\nexport async function applyExtensionsConfigReport(registry: ExtensionRegistry, report: ExtensionsConfigSyncReport, options: ApplyConfigReportOptions = {}): Promise<ReloadChangedResult> {\n registryViewState(registry)?.source.reportRefused(`config:${report.scope}`, configSyncFailures(report))\n const runtime = extensionRuntimeOf(registry)\n const result: ReloadChangedResult = { loaded: [], reloaded: [], unloaded: [], needsRebuild: false }\n const enabledOf = new Map(report.entries.map(e => [e.id, e.enabled]))\n const wants = (id: string): boolean => (options.allowed?.(id) ?? true) && enabledOf.get(id) !== false\n const held = (dir: string): boolean => runtime?.idOfDir(dir) !== undefined\n\n for (const dir of report.unlinkedDirs.map(d => resolve(d))) {\n const id = runtime?.idOfDir(dir)\n if (runtime && id !== undefined) {\n await runtime.unload(id, { forget: true })\n result.unloaded.push(id)\n }\n }\n\n const linked = new Set(report.linkedDirs.map(d => resolve(d)))\n const dirs = [\n ...report.changedDirs.map(d => resolve(d)).filter(d => !report.replay || !held(d) || !existsSync(d)),\n ...[...linked].filter(d => !held(d)),\n ]\n if (dirs.length > 0) {\n const classify = (dir: string): NewExtensionFolder | undefined => {\n if (linked.has(dir))\n return { source: report.scope, enabled: wants(basename(dir)) }\n const how = options.classify?.(dir)\n return how ? { ...how, enabled: how.enabled !== false && wants(basename(dir)) } : undefined\n }\n const done = await reloadChangedExtensions(registry, dirs, {\n classify,\n ...(options.importTimeoutMs !== undefined ? { importTimeoutMs: options.importTimeoutMs } : {}),\n ...(options.sink ? { sink: options.sink } : {}),\n ...(options.compileCache !== undefined ? { compileCache: options.compileCache } : {}),\n })\n result.loaded.push(...done.loaded)\n result.reloaded.push(...done.reloaded)\n result.unloaded.push(...done.unloaded)\n result.needsRebuild = done.needsRebuild\n }\n\n for (const { id } of runtime ? report.entries : []) {\n const ext = runtime!.get(id)\n const want = wants(id)\n if (!ext || (ext.entry.enabled !== false) === want)\n continue\n const info = await runtime!.reload(id, { entry: { ...ext.entry, enabled: want } })\n if (info && !result.reloaded.includes(id))\n result.reloaded.push(id)\n }\n return result\n}\n","/**\n * The `config` settings layer: values set by declarative config entries,\n * by extension id. The settings domain reads it between the user layer and\n * the schema default (session ` project ` user ` config ` default) and\n * shows every key it holds as locked.\n *\n * Built from the parsed entries and the locks (which map a source to the\n * id it installed as). Rebuild it when a config file or lock changes; the\n * layer itself is an immutable snapshot.\n */\n\nimport type { SettingsSchema } from '../api/settings'\nimport type { ConfigSettingValue, DeclaredExtension, ExtensionsConfigScope } from './config'\nimport type { ExtensionsLock } from './lock'\nimport { localExtensionId } from './config'\n\n/** One config file's entries and its lock. */\nexport interface ConfigSettingsSource {\n readonly entries: readonly DeclaredExtension[]\n readonly lock: ExtensionsLock\n}\n\n/** A config entry that applies to an extension id. */\nexport interface ConfigLayerEntry {\n readonly id: string\n readonly scope: ExtensionsConfigScope\n /** The entry's `source`, for \"set by …\" hints in Settings. */\n readonly source: string\n readonly enabled: boolean\n readonly settings: Readonly<Record<string, ConfigSettingValue>>\n}\n\n/** Read access to the config layer. */\nexport interface ConfigSettingsLayer {\n /** The value config sets for `key`, or `undefined`. */\n get: (extensionId: string, key: string) => ConfigSettingValue | undefined\n /** Whether config sets `key` (Settings shows it locked). */\n locked: (extensionId: string, key: string) => boolean\n /** The config file that set `key`, when one did. */\n origin: (extensionId: string, key: string) => ExtensionsConfigScope | undefined\n /** Every value config sets for the extension. */\n values: (extensionId: string) => Readonly<Record<string, ConfigSettingValue>>\n /** `enabled` from config, or `undefined` when no entry declares the extension. */\n enabled: (extensionId: string) => boolean | undefined\n /** The entries that apply to the extension, in precedence order (last wins). */\n entries: (extensionId: string) => readonly ConfigLayerEntry[]\n /** Ids config declares. */\n ids: () => readonly string[]\n}\n\n/**\n * The id a config entry stands for: from its lock entry, or the folder name\n * of a local source. `undefined` for a remote entry not installed yet.\n *\n * @param entry - The config entry.\n * @param lock - Its scope's lock.\n */\nexport function resolveDeclaredId(entry: DeclaredExtension, lock: ExtensionsLock): string | undefined {\n const locked = lock.extensions[entry.key]\n if (locked && locked.source === entry.source)\n return locked.id\n return entry.location.kind === 'local' ? localExtensionId(entry.location.path) : undefined\n}\n\n/**\n * Builds the layer. Pass the user source first and the project source\n * after: a later source wins per key and for `enabled`.\n *\n * @param sources - Config entries with their locks, lowest precedence first.\n */\nexport function createConfigSettingsLayer(sources: readonly ConfigSettingsSource[]): ConfigSettingsLayer {\n const byId = new Map<string, ConfigLayerEntry[]>()\n for (const { entries, lock } of sources) {\n for (const entry of entries) {\n const id = resolveDeclaredId(entry, lock)\n if (id === undefined)\n continue\n const list = byId.get(id) ?? []\n list.push({ id, scope: entry.scope, source: entry.source, enabled: entry.enabled, settings: entry.settings })\n byId.set(id, list)\n }\n }\n const merged = new Map<string, { values: Record<string, ConfigSettingValue>, origins: Record<string, ExtensionsConfigScope> }>()\n for (const [id, list] of byId) {\n const values: Record<string, ConfigSettingValue> = {}\n const origins: Record<string, ExtensionsConfigScope> = {}\n for (const e of list) {\n for (const [key, value] of Object.entries(e.settings)) {\n values[key] = value\n origins[key] = e.scope\n }\n }\n merged.set(id, { values, origins })\n }\n const own = (record: Record<string, unknown> | undefined, key: string): boolean => record !== undefined && Object.hasOwn(record, key)\n return {\n get: (id, key) => {\n const m = merged.get(id)\n return m && own(m.values, key) ? m.values[key] : undefined\n },\n locked: (id, key) => own(merged.get(id)?.values, key),\n origin: (id, key) => {\n const m = merged.get(id)\n return m && own(m.origins, key) ? m.origins[key] : undefined\n },\n values: id => ({ ...merged.get(id)?.values }),\n enabled: id => byId.get(id)?.at(-1)?.enabled,\n entries: id => byId.get(id) ?? [],\n ids: () => [...byId.keys()],\n }\n}\n\n/** A config value the schema refused. */\nexport interface ConfigSettingIssue {\n readonly key: string\n readonly message: string\n}\n\n/**\n * Checks config values against an extension's settings schema. Refused\n * values are dropped (the setting falls back to the next layer) and\n * reported. Secret settings are always refused: they live in the auth\n * store, never in a config file. A setting's own `validate` callback is\n * extension code and is left to the settings domain, which runs it under\n * its guard.\n *\n * @param schema - The extension's `settings`.\n * @param values - What config sets (`layer.values(id)`).\n */\nexport function validateConfigSettings(schema: SettingsSchema | undefined, values: Readonly<Record<string, ConfigSettingValue>>): { values: Record<string, ConfigSettingValue>, issues: ConfigSettingIssue[] } {\n const out: Record<string, ConfigSettingValue> = {}\n const issues: ConfigSettingIssue[] = []\n for (const [key, value] of Object.entries(values)) {\n const item = schema?.items[key]\n const refuse = (message: string): void => {\n issues.push({ key, message })\n }\n if (!item) {\n refuse(`\"${key}\" is not a setting of this extension.`)\n continue\n }\n switch (item.type) {\n case 'action':\n refuse(`\"${key}\" is a button, not a value.`)\n continue\n case 'boolean':\n if (typeof value !== 'boolean')\n refuse(`\"${key}\" must be true or false.`)\n break\n case 'number':\n if (typeof value !== 'number')\n refuse(`\"${key}\" must be a number.`)\n else if ((item.min !== undefined && value < item.min) || (item.max !== undefined && value > item.max))\n refuse(`\"${key}\" must be between ${item.min ?? '-∞'} and ${item.max ?? '∞'}.`)\n break\n case 'string':\n if (item.secret)\n refuse(`\"${key}\" is a secret. Set it in Settings, not in a config file.`)\n else if (typeof value !== 'string')\n refuse(`\"${key}\" must be text.`)\n else if (item.pattern !== undefined && !safeTest(item.pattern, value))\n refuse(`\"${key}\" does not match ${item.pattern}.`)\n break\n case 'enum':\n if (typeof value !== 'string' || !item.options.some(o => o.value === value))\n refuse(`\"${key}\" must be one of: ${item.options.map(o => o.value).join(', ')}.`)\n break\n case 'model':\n if (item.multi ? !Array.isArray(value) : typeof value !== 'string')\n refuse(item.multi ? `\"${key}\" must be a list of models.` : `\"${key}\" must be a model id.`)\n break\n }\n if (!issues.some(i => i.key === key))\n out[key] = value\n }\n return { values: out, issues }\n}\n\n/** A pattern that does not compile refuses nothing (the schema is at fault, not the value). */\nfunction safeTest(pattern: string, value: string): boolean {\n try {\n return new RegExp(pattern).test(value)\n }\n catch {\n return true\n }\n}\n","/**\n * Shared discover → disabled-set → build pipeline.\n *\n * Every host runs the identical sequence: the TUI launcher (`runTui`),\n * the TUI's cwd-change rebuild, the daemon's per-cwd runtime cache and the\n * GUI's per-cwd registry cache.\n * Centralizing it keeps the allowlist-gating contract — the `disabled`\n * set spans BOTH disk-discovered and inline candidates — in one place\n * so the callers can't drift on it.\n */\n\nimport type { Settings } from '../chat/types'\nimport type { LogSink } from '../logger'\nimport type { LinkedExtensionDir } from './discovery'\nimport type { ExtensionHostRuntimeBridge } from './host-runtime'\nimport type { ExtensionPromptBridge } from './prompt-bridge'\nimport type { BuildRuntimeOptions } from './register'\nimport type { ExtensionRegistry, LoadedExtension } from './types'\nimport { discoverExtensions } from './discovery'\nimport { registerExtensionApiHostModules } from './host-modules'\nimport { buildExtensionRegistry } from './register'\n\n/** Options for {@link discoverAndBuildExtensionRegistry}. */\nexport interface DiscoverAndBuildExtensionRegistryOptions {\n /** Discovery cwd — project roots are walked up from here. Defaults to `process.cwd()`. */\n cwd?: string\n /** User home directory. Defaults to `os.homedir()`. Mainly a test seam. */\n home?: string\n /** Storage prefix (e.g. `.zidane`). Defaults to `.zidane` inside discovery. */\n prefix?: string\n /**\n * Extra extension scan roots, prepended ahead of the default project/user\n * roots. Each root contains extension package dirs (`<root>/<name>/index.ts`).\n * Treated as user-scoped/trusted because the host/user opted into them\n * explicitly.\n */\n extensionScanPaths?: readonly string[]\n /**\n * Extension folders a config entry links in place (`configuredExtensions`,\n * `./declarative/host-sync`). Each is one extension, ahead of every scan root.\n */\n linkedExtensionDirs?: readonly LinkedExtensionDir[]\n /** Ids a config entry keeps installed but off (`enabled: false`): they load disabled, like ones the allowlist leaves out. */\n configDisabled?: readonly string[]\n /**\n * User enable allowlist (`Settings.enabledExtensions`). `undefined`\n * means \"fresh install — everything enabled\". When set it gates BOTH\n * disk and inline candidates: a name absent from the list lands in the\n * build's `disabled` set, so it classifies as `inactive` and its\n * contributions never reach the registry's active surface. Its\n * `setup()` does not run; its settings stay browsable in Settings\n * before enabling.\n */\n enabledAllowlist?: readonly string[]\n /** Whether project-scoped extensions are trusted (allowed to run their code). */\n trustProjectExtensions?: boolean\n /** Host-supplied inline extensions, already `inlineLoadedExtension()`-wrapped. */\n inlineExtensions?: readonly LoadedExtension[]\n /** Log sink for the runtime. Defaults to stderr inside `buildExtensionRegistry`. */\n sink?: LogSink\n /** Prompt bridge for `ctx.sessions.submit` (hosts with a submit pipeline). */\n promptBridge?: ExtensionPromptBridge\n /** Host runtime bridge for `ctx.sessions` / `ctx.workspace` / `ctx.artifacts`. */\n hostRuntime?: ExtensionHostRuntimeBridge\n /**\n * Live settings getter: the `user` settings layer, threaded verbatim to\n * {@link BuildExtensionRegistryOptions.readSettings}. Hosts pass a getter\n * returning their current `Settings` (TUI: a live mirror; GUI: the DB\n * reader) so extension settings reads are live.\n */\n readSettings?: () => Partial<Settings> | undefined\n /** Abort discovery before its imports dispatch. */\n signal?: AbortSignal\n /** Node hosts: the folder compiled extension code is kept in, so only a changed file compiles again (`./compile-cache`). */\n compileCache?: string\n /** Host kind and ports of the runtime (`registry.runtime`). */\n runtime?: BuildRuntimeOptions\n}\n\n/**\n * Discover disk extensions, fold in the inline ones, compute the\n * allowlist-driven `disabled` set, and build the merged\n * {@link ExtensionRegistry}.\n *\n * The `disabled` set honors the allowlist for inline extensions too:\n * the TUI treats inline as toggleable everywhere else (Settings tab,\n * live filtering), so both ride the same inactive-classification path.\n *\n * @param opts - Discovery, trust, allowlist and bridge options.\n */\nexport async function discoverAndBuildExtensionRegistry(\n opts: DiscoverAndBuildExtensionRegistryOptions = {},\n): Promise<ExtensionRegistry> {\n // Core entrypoints, mapped BEFORE discovery's imports dispatch. An extension\n // contributing a provider (`ctx.providers`) needs the host's live\n // factories and credential helpers at runtime; a bare `import { anthropic }\n // from 'zidane'` would otherwise resolve from the EXTENSION's directory —\n // nothing inside a compiled binary, or a second zidane copy with its own\n // module state (and its own OAuth registry). Renderer-neutral, so it lives\n // here rather than in the TUI: headless / ACP / GUI hosts get it too.\n // pi-ai is NOT mapped: a lazy mapping would re-import the very specifier it\n // intercepts. Extensions reach the host's provider plumbing through zidane\n // instead (`googleCompatible`).\n registerCoreExtensionHostModules()\n\n const discovered = await discoverExtensions({\n ...(opts.cwd !== undefined ? { cwd: opts.cwd } : {}),\n ...(opts.home !== undefined ? { home: opts.home } : {}),\n ...(opts.prefix !== undefined ? { prefix: opts.prefix } : {}),\n ...(opts.extensionScanPaths !== undefined ? { extensionScanPaths: opts.extensionScanPaths } : {}),\n ...(opts.linkedExtensionDirs !== undefined ? { linkedExtensionDirs: opts.linkedExtensionDirs } : {}),\n ...(opts.trustProjectExtensions !== undefined ? { trustProjectExtensions: opts.trustProjectExtensions } : {}),\n ...(opts.signal !== undefined ? { signal: opts.signal } : {}),\n ...(opts.sink !== undefined ? { sink: opts.sink } : {}),\n ...(opts.compileCache !== undefined ? { compileCache: opts.compileCache } : {}),\n })\n const candidates = [...discovered, ...(opts.inlineExtensions ?? [])]\n const allowlist = opts.enabledAllowlist\n const configDisabled = new Set(opts.configDisabled ?? [])\n const disabled = allowlist === undefined && configDisabled.size === 0\n ? undefined\n : new Set(candidates.map(e => e.name).filter(name => configDisabled.has(name) || (allowlist !== undefined && !allowlist.includes(name))))\n return buildExtensionRegistry(candidates, {\n ...(opts.sink !== undefined ? { sink: opts.sink } : {}),\n ...(opts.promptBridge !== undefined ? { promptBridge: opts.promptBridge } : {}),\n ...(opts.hostRuntime !== undefined ? { hostRuntime: opts.hostRuntime } : {}),\n ...(disabled ? { disabled } : {}),\n ...(opts.readSettings !== undefined ? { readSettings: opts.readSettings } : {}),\n ...(opts.cwd !== undefined ? { cwd: opts.cwd } : {}),\n ...(opts.prefix !== undefined ? { prefix: opts.prefix } : {}),\n ...(opts.runtime !== undefined ? { runtime: opts.runtime } : {}),\n })\n}\n\n/**\n * Maps every zidane entrypoint extensions import at runtime\n * (`hostModuleSpecifiers()`) to this process's live modules, so an\n * installed extension (or one inside a compiled binary) gets the host's\n * copy. Idempotent; call before importing an extension. Same as\n * `registerExtensionApiHostModules`.\n */\nexport function registerCoreExtensionHostModules(): void {\n registerExtensionApiHostModules()\n}\n","/**\n * {@link integrationMethodFromOAuthProvider}: a `zidane/oauth` provider flow\n * (`OAuthProviderInterface`: `login`, `refreshToken`, `getApiKey`) as an\n * integration's `custom` method, so a bespoke flow (Bolt's device flow\n * with its Access headers) signs in through `ctx.integrations`.\n *\n * Type imports only: authors import it from `zidane`, and it must not pull\n * the provider graph in.\n */\n\nimport type { OAuthCredentials } from '@earendil-works/pi-ai/oauth'\nimport type { OAuthProviderInterface } from '../../providers/oauth-registry'\nimport type { Credential, IntegrationCustomMethod, IntegrationFlowIO } from '../api/sessions'\n\n/** Fields of a grant the credential carries elsewhere. */\nconst GRANT_FIELDS = new Set(['access', 'refresh', 'expires', 'kind', 'type'])\n\nfunction toCredential(provider: OAuthProviderInterface, grant: OAuthCredentials): Extract<Credential, { type: 'oauth' }> {\n const extra: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(grant)) {\n if (!GRANT_FIELDS.has(key))\n extra[key] = value\n }\n const apiKey = provider.getApiKey(grant)\n // The credential hands out the API key; keep the raw access token for the next refresh.\n if (apiKey !== grant.access)\n extra.access = grant.access\n return {\n type: 'oauth',\n accessToken: apiKey,\n ...(typeof grant.expires === 'number' && Number.isFinite(grant.expires) ? { expiresAt: grant.expires } : {}),\n ...(typeof grant.refresh === 'string' && grant.refresh ? { refreshToken: grant.refresh } : {}),\n ...(Object.keys(extra).length ? { extra } : {}),\n }\n}\n\nfunction toGrant(credential: Credential): OAuthCredentials {\n if (credential.type !== 'oauth')\n throw new Error('This sign-in has no OAuth grant to refresh.')\n const { access, ...extra } = (credential.extra ?? {}) as Record<string, unknown>\n return {\n ...extra,\n access: typeof access === 'string' ? access : credential.accessToken,\n refresh: credential.refreshToken ?? '',\n expires: credential.expiresAt ?? 0,\n }\n}\n\nfunction labelOf(grant: OAuthCredentials): string | undefined {\n for (const key of ['email', 'account', 'label']) {\n const value = grant[key]\n if (typeof value === 'string' && value.trim())\n return value.trim()\n }\n return undefined\n}\n\nasync function promptOrCancel(io: IntegrationFlowIO, opts: Parameters<IntegrationFlowIO['prompt']>[0]): Promise<string> {\n const value = await io.prompt(opts)\n if (value === undefined)\n throw new Error('Sign-in cancelled.')\n return value\n}\n\n/**\n * Adapts a `zidane/oauth` provider flow to an integration method of type\n * `custom`. `connect` runs `provider.login` with the host's flow UI\n * (links, device codes, prompts and choices go through {@link IntegrationFlowIO});\n * the credential's `accessToken` is `provider.getApiKey(grant)`, the\n * refresh token is kept by the store, and other grant fields ride in\n * `credential.extra`. `refresh` runs `provider.refreshToken`. The account\n * is the grant's `email`, `account` or `label` when it has one.\n *\n * @param provider - The flow (`OAuthProviderInterface` from `zidane/oauth`).\n * @param opts - Method id (default `provider.id`), label (default `Sign in with <name>`) and help.\n * @param opts.id - The method id.\n * @param opts.label - The button label.\n * @param opts.help - A line under it.\n */\nexport function integrationMethodFromOAuthProvider(provider: OAuthProviderInterface, opts: { id?: string, label?: string, help?: string } = {}): IntegrationCustomMethod {\n return {\n type: 'custom',\n id: opts.id ?? provider.id,\n label: opts.label ?? `Sign in with ${provider.name}`,\n ...(opts.help ? { help: opts.help } : {}),\n connect: async (io) => {\n const grant = await provider.login({\n onAuth: (info) => {\n if (info.instructions)\n io.log(info.instructions)\n io.openUrl(info.url)\n },\n onDeviceCode: info => io.showCode(info.userCode, info.verificationUri),\n onPrompt: prompt => promptOrCancel(io, { message: prompt.message, ...(prompt.placeholder ? { placeholder: prompt.placeholder } : {}), ...(prompt.allowEmpty ? { allowEmpty: true } : {}) }),\n onSelect: prompt => io.prompt({ message: prompt.message, options: prompt.options.map(o => ({ id: o.id, label: o.label })) }),\n onProgress: message => io.log(message),\n signal: io.signal,\n })\n const label = labelOf(grant)\n return { credential: toCredential(provider, grant), ...(label ? { account: label, label } : {}) }\n },\n refresh: async credential => toCredential(provider, await provider.refreshToken(toGrant(credential))),\n }\n}\n","/**\n * Hosting extension side panels and palette providers for an app that paints\n * them elsewhere (the desktop app's renderer, a zidane-server's clients):\n * a folder's panels as summaries, a panel's `load()` and `onAction` run with\n * a hard timeout and their results normalised, a provider's items and runs\n * the same way, and their `subscribe` debounced into one change call. One\n * broken extension yields an empty panel or an error row, never a rejection.\n *\n * A panel runs in a read-only host scope ({@link panelHostRuntime}): the\n * folder's project, and the session when one is bound.\n */\nimport type { PaletteContext, PaletteItem, PaletteRunResult } from '../chat/palette'\nimport type { SessionArtifact } from '../session/artifacts'\nimport type { ExtensionHostRuntimeBridge, ExtensionHostRuntimeImpl } from './host-runtime'\nimport type { ExtensionPanelEntry, ExtensionPanelScope, PanelContent, PanelHomeLayout, PanelIcon, PanelLoadContextInput, PanelSurface } from './panels'\nimport type { ExtensionPaletteProviderEntry } from './types'\nimport { normalizePaletteItems, normalizePaletteRunResult } from '../chat/palette'\nimport { normalizePanelContent, panelSurfaces, resolvePanelLoadContext } from './panels'\nimport { withTimeout } from './with-timeout'\n\nconst LOAD_TIMEOUT_MS = 10_000\nconst ACTION_TIMEOUT_MS = 30_000\nconst ITEMS_TIMEOUT_MS = 3_000\nconst CHANGE_DEBOUNCE_MS = 150\n\nfunction timed<T>(work: () => T | Promise<T>, ms: number): Promise<T> {\n return withTimeout(Promise.resolve().then(work), ms, `timed out after ${ms}ms`)\n}\n\nfunction messageOf(err: unknown): string {\n return err instanceof Error ? err.message : String(err)\n}\n\n/** One panel a folder offers, as an app lists it. */\nexport interface PanelSummary {\n /** The panel's id, unique in the folder. */\n id: string\n /** Its tab title. */\n label: string\n /** The extension that registered it. */\n owner: string\n /** Its tab icon, when the extension gave one. */\n icon?: PanelIcon\n /** Where its side tab shows (`ExtensionPanel.scope`, `'session'` when unset). */\n scope: ExtensionPanelScope\n /** The surfaces it shows on (`ExtensionPanel.surfaces`, `['side']` when unset). */\n surfaces: readonly PanelSurface[]\n /** Its default place on the project home, when it gave one. */\n home?: PanelHomeLayout\n}\n\n/** A panel action's or a palette run's failure: the extension's own words. */\nexport interface PanelHostFailure {\n /** Always `false`: the call did not go through. */\n ok: false\n /** What the extension said went wrong. */\n error: string\n}\n\n/** What a panel's scope reads from its host. */\nexport interface PanelScopeDeps {\n /** A session's artifacts, or a project's. */\n listArtifacts: (query: { sessionId: string } | { projectRoot: string }) => Promise<SessionArtifact[]>\n /** Whether artifacts are on: off, the scope reads none. */\n artifactsEnabled: () => boolean\n /** The project a folder belongs to (its checkout's root). */\n projectRootOf: (cwd: string) => string\n}\n\n/** Where panels run: the scope's reads, and the bridge extension code reads its host from (absent: detached). */\nexport interface PanelHostDeps extends PanelScopeDeps {\n /** The bridge extension code reads its host from; absent, panels run detached. */\n hostRuntime?: ExtensionHostRuntimeBridge\n}\n\n/**\n * Summaries of a folder's panels.\n *\n * @param panels - The registry's panels.\n */\nexport function panelSummaries(panels: readonly ExtensionPanelEntry[]): PanelSummary[] {\n return panels.map(p => ({\n id: p.id,\n label: p.label,\n owner: p.owner,\n ...(p.icon ? { icon: p.icon } : {}),\n scope: p.scope ?? 'session',\n surfaces: panelSurfaces(p),\n ...(p.home ? { home: p.home } : {}),\n }))\n}\n\n/**\n * The host runtime a panel's `load` / `onAction` (or a badge action) runs in,\n * read-only: the folder's project (`projectRootOf(cwd)`), plus the session\n * when one is bound. `ctx.artifacts.list()` answers that session's artifacts\n * (`[]` unbound), `list({ scope: 'project' })` every session's under the\n * project root. Store-wide queries (`scope: 'all'`, `find`) answer `[]`;\n * `record` needs a session, so it answers `undefined` unbound. Everything\n * else reads as detached, as it does for any extension code outside a run.\n *\n * @param ctx - The bound load context.\n * @param deps - The scope's reads.\n */\nexport function panelHostRuntime(ctx: PanelLoadContextInput, deps: PanelScopeDeps): ExtensionHostRuntimeImpl {\n const { sessionId } = ctx\n const projectRoot = ctx.cwd ? deps.projectRootOf(ctx.cwd) : undefined\n const matches = (rows: SessionArtifact[], filter: { kind?: string, uri?: string, since?: number, limit?: number }): SessionArtifact[] => {\n const kept = rows.filter(a =>\n (filter.kind === undefined || a.kind === filter.kind)\n && (filter.uri === undefined || a.uri === filter.uri)\n && (filter.since === undefined || a.updatedAt >= filter.since))\n return filter.limit !== undefined ? kept.slice(0, filter.limit) : kept\n }\n return {\n model: () => null,\n thinking: () => null,\n setThinking: () => false,\n switchSession: async () => false,\n createSession: async () => false,\n appendNote: () => false,\n artifacts: () => !deps.artifactsEnabled()\n ? null\n : {\n ...(sessionId ? { sessionId } : {}),\n ...(projectRoot ? { projectRoot } : {}),\n store: {\n listArtifacts: async (filter = {}) => {\n if (filter.sessionId)\n return sessionId ? matches(await deps.listArtifacts({ sessionId }), filter) : []\n if (filter.projectRoot)\n return matches(await deps.listArtifacts({ projectRoot: filter.projectRoot }), filter)\n return []\n },\n },\n },\n }\n}\n\nfunction inPanelScope<T>(ctx: PanelLoadContextInput, deps: PanelHostDeps, run: () => Promise<T>): Promise<T> {\n return deps.hostRuntime ? deps.hostRuntime.runWith(panelHostRuntime(ctx, deps), run) : run()\n}\n\n/**\n * Runs a panel's `load()` for a context from across the boundary (known\n * string fields only, bound to `cwd`). A missing, throwing or hanging panel\n * yields an empty content naming why.\n *\n * @param panel - The panel, `undefined` when the folder no longer has it.\n * @param rawCtx - The client's context.\n * @param cwd - The folder.\n * @param deps - Where it runs.\n */\nexport async function loadExtensionPanel(panel: ExtensionPanelEntry | undefined, rawCtx: unknown, cwd: string, deps: PanelHostDeps): Promise<PanelContent> {\n if (!panel)\n return { sections: [], empty: 'This panel is no longer registered.' }\n const ctx = resolvePanelLoadContext(rawCtx, cwd)\n try {\n return normalizePanelContent(await timed(() => inPanelScope(ctx, deps, () => Promise.resolve(panel.load(ctx))), LOAD_TIMEOUT_MS))\n }\n catch (err) {\n return { sections: [], empty: `Panel failed to load: ${messageOf(err)}` }\n }\n}\n\n/**\n * Runs a panel's `onAction` as {@link loadExtensionPanel} runs its `load`.\n *\n * @param panel - The panel, `undefined` when the folder no longer has it.\n * @param actionId - The action.\n * @param payload - Its payload, as the panel's content declared it.\n * @param rawCtx - The client's context.\n * @param cwd - The folder.\n * @param deps - Where it runs.\n */\nexport async function runExtensionPanelAction(panel: ExtensionPanelEntry | undefined, actionId: string, payload: unknown, rawCtx: unknown, cwd: string, deps: PanelHostDeps): Promise<{ ok: true } | PanelHostFailure> {\n if (!panel?.onAction)\n return { ok: false, error: 'Panel has no action handler.' }\n const onAction = panel.onAction\n const ctx = resolvePanelLoadContext(rawCtx, cwd)\n try {\n await timed(() => inPanelScope(ctx, deps, () => Promise.resolve(onAction(actionId, payload as never, ctx))), ACTION_TIMEOUT_MS)\n return { ok: true }\n }\n catch (err) {\n return { ok: false, error: messageOf(err) }\n }\n}\n\n/** `onChange` at most once per {@link CHANGE_DEBOUNCE_MS}, and the timer's cancel. */\nfunction debounced(onChange: () => void): { emit: () => void, cancel: () => void } {\n let timer: ReturnType<typeof setTimeout> | null = null\n return {\n emit: () => {\n timer ??= setTimeout(() => {\n timer = null\n onChange()\n }, CHANGE_DEBOUNCE_MS)\n },\n cancel: () => {\n if (timer)\n clearTimeout(timer)\n },\n }\n}\n\n/**\n * Keeps a panel's `subscribe` on, its emits debounced into `onChange`.\n *\n * @param panel - The panel.\n * @param onChange - Called when its content changed.\n * @returns The stop, or `null` when the panel has no live updates.\n */\nexport function subscribeExtensionPanel(panel: ExtensionPanelEntry | undefined, onChange: () => void): (() => void) | null {\n if (!panel?.subscribe)\n return null\n const { emit, cancel } = debounced(onChange)\n const unsubscribe = panel.subscribe(emit)\n return () => {\n cancel()\n unsubscribe()\n }\n}\n\n/**\n * Every provider's items for `cwd`, normalised and stamped with the provider\n * id. A provider that throws or hangs contributes one disabled row naming the\n * failure, so the user sees why an expected command is missing.\n *\n * @param providers - The registry's palette providers.\n * @param cwd - The folder.\n * @param ctx - The client's palette context.\n */\nexport async function listExtensionPaletteItems(providers: readonly ExtensionPaletteProviderEntry[], cwd: string, ctx: PaletteContext): Promise<PaletteItem[]> {\n const results = await Promise.all(providers.map(async (provider) => {\n try {\n return normalizePaletteItems(await timed(() => provider.items({ ...ctx, cwd }), ITEMS_TIMEOUT_MS), provider.id, provider.group)\n }\n catch (err) {\n const failed: PaletteItem = {\n id: `${provider.id}#error`,\n title: `${provider.owner}: palette items failed`,\n description: messageOf(err),\n group: provider.group,\n source: provider.id,\n disabled: 'This extension could not list its commands.',\n }\n return [failed]\n }\n }))\n return results.flat()\n}\n\n/**\n * Runs `itemId` on its provider `source`.\n *\n * @param providers - The registry's palette providers.\n * @param source - The provider's id (`PaletteItem.source`).\n * @param itemId - The item.\n * @param cwd - The folder.\n * @param ctx - The client's palette context.\n */\nexport async function runExtensionPaletteItem(providers: readonly ExtensionPaletteProviderEntry[], source: string, itemId: string, cwd: string, ctx: PaletteContext): Promise<{ ok: true, result: PaletteRunResult } | PanelHostFailure> {\n const provider = providers.find(p => p.id === source)\n if (!provider)\n return { ok: false, error: 'This command is no longer registered.' }\n try {\n const raw = await timed(() => provider.run(itemId, { ...ctx, cwd }), ACTION_TIMEOUT_MS)\n return { ok: true, result: normalizePaletteRunResult(raw, provider.id, provider.group) }\n }\n catch (err) {\n return { ok: false, error: messageOf(err) }\n }\n}\n\n/**\n * Keeps every provider's `subscribe` on, their emits debounced into one `onChange`.\n *\n * @param providers - The registry's palette providers.\n * @param onChange - Called when items may have changed.\n * @returns The stop, or `null` when no provider has live updates.\n */\nexport function subscribeExtensionPalette(providers: readonly ExtensionPaletteProviderEntry[], onChange: () => void): (() => void) | null {\n const { emit, cancel } = debounced(onChange)\n const unsubscribes: (() => void)[] = []\n for (const provider of providers) {\n try {\n if (provider.subscribe)\n unsubscribes.push(provider.subscribe(emit))\n }\n catch {\n // A throwing subscribe just means no live updates from that provider.\n }\n }\n if (unsubscribes.length === 0)\n return null\n return () => {\n cancel()\n for (const unsubscribe of unsubscribes) {\n try {\n unsubscribe()\n }\n catch {\n // An extension's teardown error is its own problem.\n }\n }\n }\n}\n","/**\n * Prompt bridge — the host hand-off behind `ctx.submitPrompt`.\n *\n * Extensions submit prompts at any point in their lifetime; the host (the\n * TUI, post-mount) attaches the single handler that routes them into its\n * real submit machinery (run-or-queue gate, `Agent.steer`, `Agent.followUp`).\n * Same holder idiom as the host runtime bridge. Prompts are deliberately NOT\n * buffered pre-attach: silently replaying stale prompts after mount would\n * be surprising — `submit` returns `false` so callers can react.\n */\n\nexport interface ExtensionPromptDelivery {\n /**\n * `'auto'` (default) — run now when idle, join the follow-up queue when a\n * run is active. `'steer'` — inject into the CURRENT run between turns\n * (falls back to `auto` when idle). `'followUp'` — queue until the current\n * run finishes (falls back to `auto` when idle).\n */\n delivery?: 'auto' | 'steer' | 'followUp'\n}\n\n/** Connects `ctx.submitPrompt` to the host's prompt pipeline. Hosts attach their handler after the UI mounts. */\nexport interface ExtensionPromptBridge {\n /** Route a prompt to the host. `false` when no host handler is attached, the text is blank, or the handler throws. */\n submit: (text: string, opts?: ExtensionPromptDelivery) => boolean\n /** Attach the host handler (last attach wins). Returns a detach fn. */\n attach: (handler: (text: string, opts?: ExtensionPromptDelivery) => void) => () => void\n}\n\n/** Creates a bridge with no handler attached. `submit` returns `false` until a host attaches one. */\nexport function createExtensionPromptBridge(): ExtensionPromptBridge {\n let handler: ((text: string, opts?: ExtensionPromptDelivery) => void) | null = null\n return {\n submit(text, opts) {\n if (!handler || text.trim().length === 0)\n return false\n try {\n handler(text, opts)\n return true\n }\n catch {\n // The host submit path must never throw into extension code.\n return false\n }\n },\n attach(next) {\n handler = next\n return () => {\n if (handler === next)\n handler = null\n }\n },\n }\n}\n","/**\n * Extension API: contracts and registries between extensions.\n *\n * A Contract is an API one extension provides and others use. A Registry\n * is a list one extension owns and others add to. Both are tokens: they\n * carry only an id, so others can import them without the runtime code.\n */\n\nimport type { Disposable, LiveAccessor, Readable } from './core'\n\n/** Token of an API an extension provides. */\nexport interface ContractToken<T> {\n /** Always `'contract'`. */\n readonly kind: 'contract'\n /** `<extension id>.<name>`. */\n readonly id: string\n /** Type-level only. */\n readonly __type?: T\n}\n\n/** Token of a list an extension owns. */\nexport interface RegistryToken<T> {\n /** Always `'registry'`. */\n readonly kind: 'registry'\n /** `<extension id>.<name>`. */\n readonly id: string\n /** Type-level only. */\n readonly __type?: T\n}\n\n/** `ctx.contracts`. */\nexport interface ContractsDomain {\n /** Provides `token`. Its id must be the extension id or start with `<id>.`. */\n provide: <T>(token: ContractToken<T>, impl: T) => Disposable\n /** Follows a contract another extension provides. The same accessor for every call with the token. */\n use: <T>(token: ContractToken<T>) => LiveAccessor<T>\n /** Adds an item to a registry another extension (or this one) owns. */\n add: <T>(registry: RegistryToken<T>, item: T) => Disposable\n /** Every item added to a registry this extension owns, in load order. */\n list: <T>(registry: RegistryToken<T>) => Readable<readonly T[]>\n}\n\n/**\n * Declares a contract token.\n *\n * @param id - `<extension id>.<name>`.\n * @returns The token.\n */\nfunction defineContract<T>(id: string): ContractToken<T> {\n return { kind: 'contract', id }\n}\n\n/**\n * Declares a registry token.\n *\n * @param id - `<extension id>.<name>`.\n * @returns The token.\n */\nfunction defineRegistry<T>(id: string): RegistryToken<T> {\n return { kind: 'registry', id }\n}\n\n/** Helpers to declare contract tokens. */\nexport const Contract = { define: defineContract }\n/** Helpers to declare registry tokens. */\nexport const Registry = { define: defineRegistry }\n","/**\n * Subscriptions shared by the clients that asked for them (an extension\n * panel's or palette's live updates): started on the first request for a\n * key, stopped when the last owner releases it or goes away. Without the\n * count, one window closing a panel would stop the updates of another window\n * showing the same one, and a window that closed without releasing would keep\n * its subscription until the registry was rebuilt.\n */\nexport interface SharedWatches<Owner> {\n /** `start` runs once per key; it resolves to the stop function, or `null` when there is nothing to watch. */\n watch: (key: string, owner: Owner, start: () => Promise<(() => void) | null>) => Promise<void>\n /** Drops one of `owner`'s shares of `key`; the last share stops the watch. */\n unwatch: (key: string, owner: Owner) => void\n /** Every share `owner` holds (it went away). */\n release: (owner: Owner) => void\n /** Stop everything (registry rebuilt, host shutting down). */\n reset: () => void\n /** Who watches `key` now. */\n owners: (key: string) => Owner[]\n}\n\ninterface Entry<Owner> {\n owners: Map<Owner, number>\n stop: (() => void) | null\n}\n\n/** Creates an empty set of shared watches. */\nexport function createSharedWatches<Owner>(): SharedWatches<Owner> {\n const entries = new Map<string, Entry<Owner>>()\n\n const stop = (entry: Entry<Owner>): void => {\n try {\n entry.stop?.()\n }\n catch {\n // An extension's teardown error is its own problem.\n }\n }\n const drop = (key: string, entry: Entry<Owner>, owner: Owner, all: boolean): void => {\n const count = entry.owners.get(owner)\n if (count === undefined)\n return\n if (all || count <= 1)\n entry.owners.delete(owner)\n else\n entry.owners.set(owner, count - 1)\n if (entry.owners.size > 0)\n return\n entries.delete(key)\n stop(entry)\n }\n\n return {\n async watch(key, owner, start) {\n const existing = entries.get(key)\n if (existing) {\n existing.owners.set(owner, (existing.owners.get(owner) ?? 0) + 1)\n return\n }\n const entry: Entry<Owner> = { owners: new Map([[owner, 1]]), stop: null }\n entries.set(key, entry)\n const stopFn = await start().catch(() => null)\n if (entries.get(key) !== entry) {\n // Released (or reset) while starting: nobody is left to see it.\n stop({ ...entry, stop: stopFn })\n return\n }\n if (!stopFn) {\n entries.delete(key)\n return\n }\n entry.stop = stopFn\n },\n unwatch(key, owner) {\n const entry = entries.get(key)\n if (entry)\n drop(key, entry, owner, false)\n },\n release(owner) {\n for (const [key, entry] of [...entries])\n drop(key, entry, owner, true)\n },\n reset() {\n const all = [...entries.values()]\n entries.clear()\n for (const entry of all)\n stop(entry)\n },\n owners: key => [...(entries.get(key)?.owners.keys() ?? [])],\n }\n}\n"],"mappings":"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"}
|