@ai-agent-forge/agent-forge 0.88.0 → 0.88.1
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/CHANGELOG.md +29 -0
- package/bundled-plugins/agent-loop-policy/agent-forge.json +19 -0
- package/bundled-plugins/agent-loop-policy/dist/entry.d.ts +28 -0
- package/bundled-plugins/agent-loop-policy/dist/entry.d.ts.map +1 -0
- package/bundled-plugins/agent-loop-policy/dist/entry.js +69 -0
- package/bundled-plugins/agent-loop-policy/dist/entry.js.map +1 -0
- package/bundled-plugins/agent-loop-policy/dist/loop-guard.d.ts +199 -0
- package/bundled-plugins/agent-loop-policy/dist/loop-guard.d.ts.map +1 -0
- package/bundled-plugins/agent-loop-policy/dist/loop-guard.js +208 -0
- package/bundled-plugins/agent-loop-policy/dist/loop-guard.js.map +1 -0
- package/bundled-plugins/agent-loop-policy/dist/run-loop-strategy.d.ts +17 -0
- package/bundled-plugins/agent-loop-policy/dist/run-loop-strategy.d.ts.map +1 -0
- package/bundled-plugins/agent-loop-policy/dist/run-loop-strategy.js +18 -0
- package/bundled-plugins/agent-loop-policy/dist/run-loop-strategy.js.map +1 -0
- package/bundled-plugins/agent-loop-policy/plugin.json +7 -0
- package/bundled-plugins/coding-tools/agent-forge.json +19 -0
- package/{dist/core/tools → bundled-plugins/coding-tools/dist}/bash.d.ts +5 -44
- package/bundled-plugins/coding-tools/dist/bash.d.ts.map +1 -0
- package/{dist/core/tools → bundled-plugins/coding-tools/dist}/bash.js +15 -119
- package/bundled-plugins/coding-tools/dist/bash.js.map +1 -0
- package/bundled-plugins/coding-tools/dist/capability.d.ts +25 -0
- package/bundled-plugins/coding-tools/dist/capability.d.ts.map +1 -0
- package/bundled-plugins/coding-tools/dist/capability.js +98 -0
- package/bundled-plugins/coding-tools/dist/capability.js.map +1 -0
- package/bundled-plugins/coding-tools/dist/config.d.ts +8 -0
- package/bundled-plugins/coding-tools/dist/config.d.ts.map +1 -0
- package/bundled-plugins/coding-tools/dist/config.js +8 -0
- package/bundled-plugins/coding-tools/dist/config.js.map +1 -0
- package/{dist/core/tools → bundled-plugins/coding-tools/dist}/edit.d.ts +3 -3
- package/bundled-plugins/coding-tools/dist/edit.d.ts.map +1 -0
- package/{dist/core/tools → bundled-plugins/coding-tools/dist}/edit.js +12 -10
- package/bundled-plugins/coding-tools/dist/edit.js.map +1 -0
- package/bundled-plugins/coding-tools/dist/entry.d.ts +14 -0
- package/bundled-plugins/coding-tools/dist/entry.d.ts.map +1 -0
- package/bundled-plugins/coding-tools/dist/entry.js +23 -0
- package/bundled-plugins/coding-tools/dist/entry.js.map +1 -0
- package/{dist/core/tools → bundled-plugins/coding-tools/dist}/find.d.ts +4 -4
- package/bundled-plugins/coding-tools/dist/find.d.ts.map +1 -0
- package/{dist/core/tools → bundled-plugins/coding-tools/dist}/find.js +10 -8
- package/bundled-plugins/coding-tools/dist/find.js.map +1 -0
- package/{dist/core/tools → bundled-plugins/coding-tools/dist}/grep.d.ts +3 -3
- package/bundled-plugins/coding-tools/dist/grep.d.ts.map +1 -0
- package/{dist/core/tools → bundled-plugins/coding-tools/dist}/grep.js +10 -8
- package/bundled-plugins/coding-tools/dist/grep.js.map +1 -0
- package/bundled-plugins/coding-tools/dist/index.d.ts +17 -0
- package/bundled-plugins/coding-tools/dist/index.d.ts.map +1 -0
- package/bundled-plugins/coding-tools/dist/index.js +17 -0
- package/bundled-plugins/coding-tools/dist/index.js.map +1 -0
- package/{dist/core/tools → bundled-plugins/coding-tools/dist}/ls.d.ts +3 -3
- package/bundled-plugins/coding-tools/dist/ls.d.ts.map +1 -0
- package/{dist/core/tools → bundled-plugins/coding-tools/dist}/ls.js +8 -6
- package/{dist/core/tools → bundled-plugins/coding-tools/dist}/ls.js.map +1 -1
- package/{dist/core/tools → bundled-plugins/coding-tools/dist}/powershell.d.ts +2 -1
- package/bundled-plugins/coding-tools/dist/powershell.d.ts.map +1 -0
- package/{dist/core/tools → bundled-plugins/coding-tools/dist}/powershell.js +6 -3
- package/bundled-plugins/coding-tools/dist/powershell.js.map +1 -0
- package/{dist/core/tools → bundled-plugins/coding-tools/dist}/read.d.ts +3 -3
- package/bundled-plugins/coding-tools/dist/read.d.ts.map +1 -0
- package/{dist/core/tools → bundled-plugins/coding-tools/dist}/read.js +15 -13
- package/bundled-plugins/coding-tools/dist/read.js.map +1 -0
- package/bundled-plugins/coding-tools/dist/types.d.ts +74 -0
- package/bundled-plugins/coding-tools/dist/types.d.ts.map +1 -0
- package/bundled-plugins/coding-tools/dist/types.js +28 -0
- package/bundled-plugins/coding-tools/dist/types.js.map +1 -0
- package/{dist/core/tools → bundled-plugins/coding-tools/dist}/write.d.ts +2 -2
- package/bundled-plugins/coding-tools/dist/write.d.ts.map +1 -0
- package/{dist/core/tools → bundled-plugins/coding-tools/dist}/write.js +11 -9
- package/bundled-plugins/coding-tools/dist/write.js.map +1 -0
- package/bundled-plugins/coding-tools/plugin.json +10 -0
- package/bundled-plugins/compaction-policy/agent-forge.json +19 -0
- package/bundled-plugins/compaction-policy/dist/branch-summary-policy.d.ts +6 -0
- package/bundled-plugins/compaction-policy/dist/branch-summary-policy.d.ts.map +1 -0
- package/bundled-plugins/compaction-policy/dist/branch-summary-policy.js +19 -0
- package/bundled-plugins/compaction-policy/dist/branch-summary-policy.js.map +1 -0
- package/bundled-plugins/compaction-policy/dist/compaction-policy.d.ts +6 -0
- package/bundled-plugins/compaction-policy/dist/compaction-policy.d.ts.map +1 -0
- package/bundled-plugins/compaction-policy/dist/compaction-policy.js +38 -0
- package/bundled-plugins/compaction-policy/dist/compaction-policy.js.map +1 -0
- package/bundled-plugins/compaction-policy/dist/entry.d.ts +13 -0
- package/bundled-plugins/compaction-policy/dist/entry.d.ts.map +1 -0
- package/bundled-plugins/compaction-policy/dist/entry.js +23 -0
- package/bundled-plugins/compaction-policy/dist/entry.js.map +1 -0
- package/bundled-plugins/compaction-policy/plugin.json +10 -0
- package/bundled-plugins/mcp-http/dist/index.d.ts +8 -0
- package/bundled-plugins/mcp-http/dist/index.d.ts.map +1 -0
- package/bundled-plugins/mcp-http/dist/index.js +8 -0
- package/bundled-plugins/mcp-http/dist/index.js.map +1 -0
- package/bundled-plugins/mcp-http/dist/mcp-http.d.ts.map +1 -0
- package/{dist/plugins → bundled-plugins/mcp-http/dist}/mcp-http.js +1 -1
- package/bundled-plugins/mcp-http/dist/mcp-http.js.map +1 -0
- package/bundled-plugins/overflow-policy/agent-forge.json +19 -0
- package/bundled-plugins/overflow-policy/dist/entry.d.ts +16 -0
- package/bundled-plugins/overflow-policy/dist/entry.d.ts.map +1 -0
- package/bundled-plugins/overflow-policy/dist/entry.js +35 -0
- package/bundled-plugins/overflow-policy/dist/entry.js.map +1 -0
- package/bundled-plugins/overflow-policy/plugin.json +10 -0
- package/bundled-plugins/provider-failover/agent-forge.json +19 -0
- package/bundled-plugins/provider-failover/dist/entry.d.ts +8 -0
- package/bundled-plugins/provider-failover/dist/entry.d.ts.map +1 -0
- package/bundled-plugins/provider-failover/dist/entry.js +8 -0
- package/bundled-plugins/provider-failover/dist/entry.js.map +1 -0
- package/bundled-plugins/provider-failover/dist/provider-failover.d.ts +122 -0
- package/bundled-plugins/provider-failover/dist/provider-failover.d.ts.map +1 -0
- package/{dist/core/extensions → bundled-plugins/provider-failover/dist}/provider-failover.js +143 -56
- package/bundled-plugins/provider-failover/dist/provider-failover.js.map +1 -0
- package/bundled-plugins/provider-failover/plugin.json +7 -0
- package/bundled-plugins/retry-policy/agent-forge.json +19 -0
- package/bundled-plugins/retry-policy/dist/entry.d.ts +16 -0
- package/bundled-plugins/retry-policy/dist/entry.d.ts.map +1 -0
- package/bundled-plugins/retry-policy/dist/entry.js +34 -0
- package/bundled-plugins/retry-policy/dist/entry.js.map +1 -0
- package/bundled-plugins/retry-policy/plugin.json +10 -0
- package/dist/bundle/.build-manifest.json +61 -117
- package/dist/bundle/chunks/{anthropic-messages-ALDZBUKI.js → anthropic-messages-PLAKXR73.js} +1 -1
- package/dist/bundle/chunks/{azure-openai-responses-A2WJWZFB.js → azure-openai-responses-OUWQ2AZD.js} +1 -1
- package/dist/bundle/chunks/{chunk-CIX3FSBK.js → chunk-A3JYRWB6.js} +1 -1
- package/dist/bundle/chunks/{chunk-SQFG22WN.js → chunk-AC2FIS4G.js} +1 -1
- package/dist/bundle/chunks/chunk-AQLNTW2B.js +664 -0
- package/dist/bundle/chunks/chunk-D3ARGZFR.js +13 -0
- package/dist/bundle/chunks/{chunk-YJCQVXW5.js → chunk-HTEVUY7F.js} +1 -1
- package/dist/bundle/chunks/{chunk-Y7HXTASS.js → chunk-HV64ASMT.js} +1 -1
- package/dist/bundle/chunks/chunk-LZOEQITZ.js +855 -0
- package/dist/bundle/chunks/{chunk-7ZY7IXZD.js → chunk-TRDNDS6A.js} +1 -1
- package/dist/bundle/chunks/chunk-Z72JWUZ4.js +4 -0
- package/dist/bundle/chunks/{google-generative-ai-NIB4WONV.js → google-generative-ai-DLII6DAT.js} +1 -1
- package/dist/bundle/chunks/{google-vertex-DCPYUEUO.js → google-vertex-G7BZL7GM.js} +1 -1
- package/dist/bundle/chunks/image-resize-worker.js +2 -2
- package/dist/bundle/chunks/{mistral-conversations-OC6LA5XL.js → mistral-conversations-JXUK24ID.js} +1 -1
- package/dist/bundle/chunks/{openai-codex-responses-IO2X4Y7L.js → openai-codex-responses-5GSGFIPG.js} +1 -1
- package/dist/bundle/chunks/{openai-completions-XYQQHETU.js → openai-completions-EI2I6DTG.js} +1 -1
- package/dist/bundle/chunks/{openai-responses-DLIRN3CI.js → openai-responses-AUJQ3NWT.js} +1 -1
- package/dist/bundle/chunks/{pi-messages-E6RRYBO7.js → pi-messages-PWU2VJMR.js} +1 -1
- package/dist/bundle/chunks/virtual-modules-WF6WRHP7.js +5 -0
- package/dist/bundle/cli.js +1 -1
- package/dist/bundle/client.js +1 -1
- package/dist/bundle/index.js +3 -3
- package/dist/bundle/rpc-entry.js +1 -1
- package/dist/capabilities/builtin.d.ts +1 -1
- package/dist/capabilities/builtin.d.ts.map +1 -1
- package/dist/capabilities/builtin.js +5 -0
- package/dist/capabilities/builtin.js.map +1 -1
- package/dist/cli/plugin-command.d.ts.map +1 -1
- package/dist/cli/plugin-command.js +17 -1
- package/dist/cli/plugin-command.js.map +1 -1
- package/dist/config.d.ts +2 -3
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +2 -4
- package/dist/config.js.map +1 -1
- package/dist/core/agent-session-bash.d.ts +1 -1
- package/dist/core/agent-session-bash.d.ts.map +1 -1
- package/dist/core/agent-session-bash.js +1 -1
- package/dist/core/agent-session-bash.js.map +1 -1
- package/dist/core/agent-session-compaction.d.ts.map +1 -1
- package/dist/core/agent-session-compaction.js +14 -1
- package/dist/core/agent-session-compaction.js.map +1 -1
- package/dist/core/agent-session-internal.d.ts +1 -1
- package/dist/core/agent-session-internal.d.ts.map +1 -1
- package/dist/core/agent-session-internal.js.map +1 -1
- package/dist/core/agent-session-loop.d.ts +4 -3
- package/dist/core/agent-session-loop.d.ts.map +1 -1
- package/dist/core/agent-session-loop.js +9 -6
- package/dist/core/agent-session-loop.js.map +1 -1
- package/dist/core/agent-session-retry.d.ts +1 -1
- package/dist/core/agent-session-retry.d.ts.map +1 -1
- package/dist/core/agent-session-retry.js +32 -3
- package/dist/core/agent-session-retry.js.map +1 -1
- package/dist/core/agent-session-services.d.ts.map +1 -1
- package/dist/core/agent-session-services.js +30 -9
- package/dist/core/agent-session-services.js.map +1 -1
- package/dist/core/agent-session-tools.d.ts.map +1 -1
- package/dist/core/agent-session-tools.js +5 -1
- package/dist/core/agent-session-tools.js.map +1 -1
- package/dist/core/agent-session.d.ts +12 -13
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +56 -34
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/bash-executor.d.ts +1 -1
- package/dist/core/bash-executor.d.ts.map +1 -1
- package/dist/core/bash-executor.js.map +1 -1
- package/dist/core/extensions/bootstrap-agent-loop.d.ts +23 -151
- package/dist/core/extensions/bootstrap-agent-loop.d.ts.map +1 -1
- package/dist/core/extensions/bootstrap-agent-loop.js +28 -290
- package/dist/core/extensions/bootstrap-agent-loop.js.map +1 -1
- package/dist/core/extensions/capability-runtime-types.d.ts +5 -3
- package/dist/core/extensions/capability-runtime-types.d.ts.map +1 -1
- package/dist/core/extensions/capability-runtime-types.js.map +1 -1
- package/dist/core/extensions/capability-runtime.d.ts.map +1 -1
- package/dist/core/extensions/capability-runtime.js +42 -6
- package/dist/core/extensions/capability-runtime.js.map +1 -1
- package/dist/core/extensions/index.d.ts +12 -5
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/index.js +12 -5
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/virtual-modules.d.ts.map +1 -1
- package/dist/core/extensions/virtual-modules.js +65 -0
- package/dist/core/extensions/virtual-modules.js.map +1 -1
- package/dist/core/facade/coding-agent-facade.d.ts +1 -1
- package/dist/core/facade/coding-agent-facade.d.ts.map +1 -1
- package/dist/core/facade/coding-agent-facade.js.map +1 -1
- package/dist/core/i18n/locales/zh-cn/core-contract-core.d.ts +1 -1
- package/dist/core/i18n/locales/zh-cn/core-contract-core.d.ts.map +1 -1
- package/dist/core/i18n/locales/zh-cn/core-contract-core.js +1 -1
- package/dist/core/i18n/locales/zh-cn/core-contract-core.js.map +1 -1
- package/dist/core/i18n/locales/zh-cn/core-contract-extensions.d.ts.map +1 -1
- package/dist/core/i18n/locales/zh-cn/core-contract-extensions.js +2 -4
- package/dist/core/i18n/locales/zh-cn/core-contract-extensions.js.map +1 -1
- package/dist/core/i18n/locales/zh-cn/core-errors.d.ts.map +1 -1
- package/dist/core/i18n/locales/zh-cn/core-errors.js +3 -1
- package/dist/core/i18n/locales/zh-cn/core-errors.js.map +1 -1
- package/dist/core/sdk.d.ts +10 -3
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +263 -77
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/tools/bash-operations.d.ts +41 -0
- package/dist/core/tools/bash-operations.d.ts.map +1 -0
- package/dist/core/tools/bash-operations.js +113 -0
- package/dist/core/tools/bash-operations.js.map +1 -0
- package/dist/core/tools/index.d.ts +12 -36
- package/dist/core/tools/index.d.ts.map +1 -1
- package/dist/core/tools/index.js +1 -117
- package/dist/core/tools/index.js.map +1 -1
- package/dist/core/tools/readme-path.d.ts +3 -0
- package/dist/core/tools/readme-path.d.ts.map +1 -0
- package/dist/core/tools/readme-path.js +15 -0
- package/dist/core/tools/readme-path.js.map +1 -0
- package/dist/index.d.ts +3 -19
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -39
- package/dist/index.js.map +1 -1
- package/dist/modes/interactive/components/tool-execution.d.ts +0 -1
- package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-execution.js +9 -25
- package/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/dist/plugins/ecosystem/cli.d.ts.map +1 -1
- package/dist/plugins/ecosystem/cli.js +14 -2
- package/dist/plugins/ecosystem/cli.js.map +1 -1
- package/dist/plugins/ecosystem/node-npm-registry-source.d.ts +7 -2
- package/dist/plugins/ecosystem/node-npm-registry-source.d.ts.map +1 -1
- package/dist/plugins/ecosystem/node-npm-registry-source.js +64 -9
- package/dist/plugins/ecosystem/node-npm-registry-source.js.map +1 -1
- package/dist/plugins/ecosystem/node-plugin-acquisition-host.d.ts.map +1 -1
- package/dist/plugins/ecosystem/node-plugin-acquisition-host.js +6 -0
- package/dist/plugins/ecosystem/node-plugin-acquisition-host.js.map +1 -1
- package/dist/profiles/builtin-suites.d.ts +5 -1
- package/dist/profiles/builtin-suites.d.ts.map +1 -1
- package/dist/profiles/builtin-suites.js +6 -1
- package/dist/profiles/builtin-suites.js.map +1 -1
- package/examples/extensions/bash-spawn-hook/index.ts +7 -2
- package/examples/extensions/built-in-tool-renderer/index.ts +4 -2
- package/examples/extensions/minimal-mode/index.ts +2 -2
- package/examples/extensions/truncated-tool/index.ts +1 -1
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/examples/extensions/with-deps/plugin.json +1 -1
- package/package.json +3 -2
- package/dist/bundle/chunks/chunk-6ZKDNZHA.js +0 -145
- package/dist/bundle/chunks/chunk-HLJEVRWP.js +0 -13
- package/dist/bundle/chunks/chunk-YGHQME4V.js +0 -1456
- package/dist/bundle/chunks/virtual-modules-KZ5DRH7Q.js +0 -2
- package/dist/core/extensions/bootstrap-branch-summary-policy.d.ts +0 -7
- package/dist/core/extensions/bootstrap-branch-summary-policy.d.ts.map +0 -1
- package/dist/core/extensions/bootstrap-branch-summary-policy.js +0 -28
- package/dist/core/extensions/bootstrap-branch-summary-policy.js.map +0 -1
- package/dist/core/extensions/bootstrap-compaction-policy.d.ts +0 -7
- package/dist/core/extensions/bootstrap-compaction-policy.d.ts.map +0 -1
- package/dist/core/extensions/bootstrap-compaction-policy.js +0 -48
- package/dist/core/extensions/bootstrap-compaction-policy.js.map +0 -1
- package/dist/core/extensions/bootstrap-overflow-policy.d.ts +0 -7
- package/dist/core/extensions/bootstrap-overflow-policy.d.ts.map +0 -1
- package/dist/core/extensions/bootstrap-overflow-policy.js +0 -30
- package/dist/core/extensions/bootstrap-overflow-policy.js.map +0 -1
- package/dist/core/extensions/bootstrap-retry-policy.d.ts +0 -7
- package/dist/core/extensions/bootstrap-retry-policy.d.ts.map +0 -1
- package/dist/core/extensions/bootstrap-retry-policy.js +0 -29
- package/dist/core/extensions/bootstrap-retry-policy.js.map +0 -1
- package/dist/core/extensions/bootstrap-tools.d.ts +0 -20
- package/dist/core/extensions/bootstrap-tools.d.ts.map +0 -1
- package/dist/core/extensions/bootstrap-tools.js +0 -36
- package/dist/core/extensions/bootstrap-tools.js.map +0 -1
- package/dist/core/extensions/provider-failover.d.ts +0 -110
- package/dist/core/extensions/provider-failover.d.ts.map +0 -1
- package/dist/core/extensions/provider-failover.js.map +0 -1
- package/dist/core/tools/bash.d.ts.map +0 -1
- package/dist/core/tools/bash.js.map +0 -1
- package/dist/core/tools/edit.d.ts.map +0 -1
- package/dist/core/tools/edit.js.map +0 -1
- package/dist/core/tools/find.d.ts.map +0 -1
- package/dist/core/tools/find.js.map +0 -1
- package/dist/core/tools/grep.d.ts.map +0 -1
- package/dist/core/tools/grep.js.map +0 -1
- package/dist/core/tools/ls.d.ts.map +0 -1
- package/dist/core/tools/powershell.d.ts.map +0 -1
- package/dist/core/tools/powershell.js.map +0 -1
- package/dist/core/tools/read.d.ts.map +0 -1
- package/dist/core/tools/read.js.map +0 -1
- package/dist/core/tools/write.d.ts.map +0 -1
- package/dist/core/tools/write.js.map +0 -1
- package/dist/plugins/mcp-http.d.ts.map +0 -1
- package/dist/plugins/mcp-http.js.map +0 -1
- package/dist/profile/child-facade.d.ts +0 -44
- package/dist/profile/child-facade.d.ts.map +0 -1
- package/dist/profile/child-facade.js +0 -56
- package/dist/profile/child-facade.js.map +0 -1
- package/dist/profile/dependency-wiring.d.ts +0 -48
- package/dist/profile/dependency-wiring.d.ts.map +0 -1
- package/dist/profile/dependency-wiring.js +0 -56
- package/dist/profile/dependency-wiring.js.map +0 -1
- package/dist/profile/domain-recovery.d.ts +0 -60
- package/dist/profile/domain-recovery.d.ts.map +0 -1
- package/dist/profile/domain-recovery.js +0 -94
- package/dist/profile/domain-recovery.js.map +0 -1
- package/dist/profile/first-roles.d.ts +0 -30
- package/dist/profile/first-roles.d.ts.map +0 -1
- package/dist/profile/first-roles.js +0 -83
- package/dist/profile/first-roles.js.map +0 -1
- package/dist/profile/goal-plugin.d.ts +0 -38
- package/dist/profile/goal-plugin.d.ts.map +0 -1
- package/dist/profile/goal-plugin.js +0 -132
- package/dist/profile/goal-plugin.js.map +0 -1
- package/dist/profile/plan-plugin.d.ts +0 -44
- package/dist/profile/plan-plugin.d.ts.map +0 -1
- package/dist/profile/plan-plugin.js +0 -157
- package/dist/profile/plan-plugin.js.map +0 -1
- package/dist/profile/policy-manifest.d.ts +0 -53
- package/dist/profile/policy-manifest.d.ts.map +0 -1
- package/dist/profile/policy-manifest.js +0 -53
- package/dist/profile/policy-manifest.js.map +0 -1
- package/dist/profile/role-assembly.d.ts +0 -47
- package/dist/profile/role-assembly.d.ts.map +0 -1
- package/dist/profile/role-assembly.js +0 -31
- package/dist/profile/role-assembly.js.map +0 -1
- package/dist/profile/role-catalog.d.ts +0 -43
- package/dist/profile/role-catalog.d.ts.map +0 -1
- package/dist/profile/role-catalog.js +0 -132
- package/dist/profile/role-catalog.js.map +0 -1
- package/dist/profile/role-orchestrator.d.ts +0 -123
- package/dist/profile/role-orchestrator.d.ts.map +0 -1
- package/dist/profile/role-orchestrator.js +0 -195
- package/dist/profile/role-orchestrator.js.map +0 -1
- package/dist/profile/role-runner.d.ts +0 -99
- package/dist/profile/role-runner.d.ts.map +0 -1
- package/dist/profile/role-runner.js +0 -79
- package/dist/profile/role-runner.js.map +0 -1
- package/dist/profile/root-facade.d.ts +0 -36
- package/dist/profile/root-facade.d.ts.map +0 -1
- package/dist/profile/root-facade.js +0 -49
- package/dist/profile/root-facade.js.map +0 -1
- package/dist/profile/skill-discovery-wiring.d.ts +0 -58
- package/dist/profile/skill-discovery-wiring.d.ts.map +0 -1
- package/dist/profile/skill-discovery-wiring.js +0 -80
- package/dist/profile/skill-discovery-wiring.js.map +0 -1
- package/dist/profile/state-store.d.ts +0 -62
- package/dist/profile/state-store.d.ts.map +0 -1
- package/dist/profile/state-store.js +0 -144
- package/dist/profile/state-store.js.map +0 -1
- package/dist/profile/todo-plugin.d.ts +0 -37
- package/dist/profile/todo-plugin.d.ts.map +0 -1
- package/dist/profile/todo-plugin.js +0 -137
- package/dist/profile/todo-plugin.js.map +0 -1
- /package/{dist/plugins → bundled-plugins/mcp-http/dist}/mcp-http.d.ts +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../../src/plugins/ecosystem/cli.ts"],"names":[],"mappings":"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","sourcesContent":["import { Buffer } from \"node:buffer\";\n\nimport { t } from \"../../core/i18n/index.ts\";\nimport { buildPluginCatalogV1 } from \"./catalog.ts\";\nimport type { PluginDistributionDescriptorV1, PluginDistributionV1 } from \"./distribution.ts\";\nimport { DEFAULT_GLOBAL_PLUGIN_SCOPE_REF_V1, type PluginInstallerV1 } from \"./installer.ts\";\nimport {\n\tisPluginAcquisitionRefTargetV1,\n\tPluginAcquisitionErrorV1,\n\ttype PluginAcquisitionPackageV1,\n} from \"./plugin-acquisition.ts\";\nimport { createPluginSelectionV1, MAX_PLUGIN_SELECTION_IDS_V1, type PluginSelectionV1 } from \"./selection.ts\";\nimport type { PluginSelectionStoreV1 } from \"./selection-store.ts\";\nimport type { PluginStateRecordV1, PluginStateScopeV1, PluginStateStoreV1 } from \"./state.ts\";\nimport type { HostFactsV1, PluginManifestV1 } from \"./types.ts\";\n\nexport const PLUGIN_ECOSYSTEM_CLI_VERSION_V1 = 1 as const;\nexport const MAX_PLUGIN_ECOSYSTEM_CLI_OUTPUT_BYTES_V1 = 64 * 1024;\nexport const MAX_PLUGIN_ECOSYSTEM_CLI_LIST_ENTRIES_V1 = 128;\nexport const MAX_PLUGIN_ECOSYSTEM_CLI_ARGS_V1 = MAX_PLUGIN_SELECTION_IDS_V1 + 8;\n\nexport type PluginEcosystemCliOutputFormatV1 = \"json\" | \"text\";\nexport type PluginEcosystemCliCommandNameV1 =\n\t| \"catalog-list\"\n\t| \"state-list\"\n\t| \"selection-list\"\n\t| \"selection-set\"\n\t| \"selection-clear\"\n\t| \"enable\"\n\t| \"disable\"\n\t| \"remove\"\n\t| \"install\"\n\t| \"update\";\n\n/**\n * The accepted command grammar, rendered into invalid-command diagnostics so a\n * mistyped invocation names what it sent and what would have parsed (live\n * finding from the 0.85.3 user seat test: `plugin state-list` reported a bare\n * \"command is invalid\" with no received argv and no valid-command list).\n */\nexport const PLUGIN_ECOSYSTEM_CLI_COMMAND_USAGE_V1 =\n\t\"catalog list | catalog-list | state list | state-list | selection list | selection-list | \" +\n\t\"selection set <builtinPluginProfileId> <pluginId…> | selection-set <builtinPluginProfileId> <pluginId…> | \" +\n\t\"selection clear <profile> | selection-clear <profile> | enable <pluginId[@version]> | \" +\n\t\"disable <pluginId[@version]> | remove <pluginId[@version]> | state enable|disable|remove <pluginId[@version]> | \" +\n\t\"install <pluginId[@version] | ref> | update <pluginId[@version]> \" +\n\t\"[--scope global|project] [--json | --text | --format json|text]\";\n\nexport interface PluginRegistryPackageV1 {\n\treadonly manifest: PluginManifestV1;\n\treadonly source: string;\n\treadonly expectedDigest?: string;\n\t/** Optional signed package acquisition descriptor. It never contains package bytes or paths. */\n\treadonly distribution?: PluginDistributionDescriptorV1;\n}\n\n/** Registry access is intentionally host-injected; this CLI never downloads itself. */\nexport interface PluginEcosystemRegistryV1 {\n\treadonly list?: (input: {\n\t\treadonly signal?: AbortSignal;\n\t}) => readonly PluginManifestV1[] | Promise<readonly PluginManifestV1[]>;\n\treadonly resolve: (input: {\n\t\treadonly pluginId: string;\n\t\treadonly pluginVersion?: string;\n\t\treadonly signal?: AbortSignal;\n\t}) => PluginRegistryPackageV1 | undefined | Promise<PluginRegistryPackageV1 | undefined>;\n}\n\n/**\n * Host-injected multi-source acquisition boundary for `plugin install <ref>`\n * (npm / custom URL / local). Like registry access it is host-owned; the CLI\n * never downloads by itself.\n */\nexport interface PluginEcosystemCliAcquisitionV1 {\n\treadonly resolvePackage: (input: {\n\t\treadonly ref: string;\n\t\treadonly signal?: AbortSignal;\n\t}) => Promise<PluginAcquisitionPackageV1>;\n}\n\nexport interface PluginEcosystemCliOptionsV1 {\n\treadonly host?: HostFactsV1;\n\treadonly manifests?: readonly PluginManifestV1[];\n\treadonly registry?: PluginEcosystemRegistryV1;\n\t/** Optional multi-source acquisition boundary for `install <ref>` targets. */\n\treadonly acquisition?: PluginEcosystemCliAcquisitionV1;\n\treadonly installer?: PluginInstallerV1;\n\t/** Host-owned descriptor verifier and artifact acquisition boundary. */\n\treadonly distribution?: PluginDistributionV1;\n\treadonly stateStore?: PluginStateStoreV1;\n\t/** Alias for hosts that expose the persistence boundary as a state host. */\n\treadonly stateHost?: PluginStateStoreV1;\n\t/** Optional project-local state store. Global state remains the default. */\n\treadonly projectStateStore?: PluginStateStoreV1;\n\t/** Opaque concrete host namespace for project-scoped installations. */\n\treadonly projectScopeRef?: string;\n\treadonly selectionStore?: PluginSelectionStoreV1;\n\t/** Alias for hosts that expose the persistence boundary as a selection host. */\n\treadonly selectionHost?: PluginSelectionStoreV1;\n\t/** Optional project-local selection store. Global selection remains the default. */\n\treadonly projectSelectionStore?: PluginSelectionStoreV1;\n}\n\nexport interface PluginEcosystemCliRequestV1 {\n\treadonly argv: readonly string[];\n\treadonly format?: PluginEcosystemCliOutputFormatV1;\n\treadonly signal?: AbortSignal;\n}\n\nexport interface PluginEcosystemCliParsedCommandV1 {\n\treadonly version: typeof PLUGIN_ECOSYSTEM_CLI_VERSION_V1;\n\treadonly command: PluginEcosystemCliCommandNameV1;\n\treadonly format: PluginEcosystemCliOutputFormatV1;\n\treadonly pluginId?: string;\n\treadonly pluginVersion?: string;\n\t/** Raw install/update target; kept so ref forms survive the identity split. */\n\treadonly target?: string;\n\treadonly profileId?: string;\n\treadonly selectedPluginIds?: readonly string[];\n\treadonly scope?: PluginStateScopeV1;\n}\n\nexport type PluginEcosystemCliErrorCodeV1 =\n\t| \"invalid_command\"\n\t| \"unsupported_dependencies\"\n\t| \"not_found\"\n\t| \"not_installed\"\n\t| \"selection_failed\"\n\t| \"registry_failed\"\n\t| \"acquisition_failed\"\n\t| \"distribution_failed\"\n\t| \"incompatible\"\n\t| \"already_installed\"\n\t| \"installer_failed\"\n\t| \"uninstall_failed\"\n\t| \"state_failed\"\n\t| \"cancelled\";\n\nexport interface PluginEcosystemCliErrorV1 {\n\treadonly code: PluginEcosystemCliErrorCodeV1;\n\treadonly message: string;\n}\n\nexport interface PluginEcosystemCliResponseV1 {\n\treadonly version: typeof PLUGIN_ECOSYSTEM_CLI_VERSION_V1;\n\treadonly command: PluginEcosystemCliCommandNameV1 | \"invalid\";\n\treadonly format: PluginEcosystemCliOutputFormatV1;\n\treadonly status: \"succeeded\" | \"failed\" | \"unsupported\" | \"cancelled\";\n\treadonly data?: Readonly<Record<string, unknown>>;\n\treadonly text: string;\n\treadonly error?: PluginEcosystemCliErrorV1;\n}\n\nexport interface PluginEcosystemCliV1 {\n\treadonly execute: (input: PluginEcosystemCliRequestV1) => Promise<PluginEcosystemCliResponseV1>;\n}\n\ntype ResultData = Readonly<Record<string, unknown>>;\n\nfunction invalidInput(message: string): never {\n\tthrow new Error(message);\n}\n\n/**\n * Canonical hyphenated command names (the response vocabulary, e.g.\n * `plugin state-list`) map onto the two-word grammar (`state list`) so both\n * spellings parse identically. Live finding from the 0.85.3 user seat test:\n * `plugin state-list` is the natural spelling of the canonical name and was\n * rejected with a generic invalid-command error.\n */\nconst COMMAND_NAME_ALIASES_V1: Readonly<Record<string, readonly [string, string]>> = Object.freeze({\n\t\"catalog-list\": [\"catalog\", \"list\"],\n\t\"state-list\": [\"state\", \"list\"],\n\t\"selection-list\": [\"selection\", \"list\"],\n\t\"selection-set\": [\"selection\", \"set\"],\n\t\"selection-clear\": [\"selection\", \"clear\"],\n});\n\nfunction validateToken(value: string, label: string): string {\n\tif (value.length === 0 || value.length > 256 || /[\\u0000-\\u001f\\s]/u.test(value))\n\t\tinvalidInput(`${label} is invalid`);\n\treturn value;\n}\n\nfunction parseIdentity(value: string): {\n\treadonly pluginId: string;\n\treadonly pluginVersion?: string;\n} {\n\tconst token = validateToken(value, \"plugin identity\");\n\tconst at = token.lastIndexOf(\"@\");\n\tif (at <= 0) return { pluginId: token };\n\tconst pluginId = token.slice(0, at);\n\tconst pluginVersion = token.slice(at + 1);\n\tif (pluginVersion.length === 0) invalidInput(\"plugin version is invalid\");\n\treturn {\n\t\tpluginId: validateToken(pluginId, \"plugin ID\"),\n\t\tpluginVersion: validateToken(pluginVersion, \"plugin version\"),\n\t};\n}\n\n/** Parse only the ecosystem command grammar; legacy package commands are not accepted. */\nexport function parsePluginEcosystemCliCommandV1(\n\targv: readonly string[],\n\tdefaultFormat: PluginEcosystemCliOutputFormatV1 = \"text\",\n): PluginEcosystemCliParsedCommandV1 {\n\tif (!Array.isArray(argv) || argv.length === 0 || argv.length > MAX_PLUGIN_ECOSYSTEM_CLI_ARGS_V1)\n\t\tinvalidInput(\"ecosystem command is invalid\");\n\tlet format = defaultFormat;\n\tif (format !== \"json\" && format !== \"text\") invalidInput(\"output format is invalid\");\n\tlet args = [...argv];\n\tlet explicitFormat: PluginEcosystemCliOutputFormatV1 | undefined;\n\tlet scope: PluginStateScopeV1 | undefined;\n\tlet pluginIdsOption: readonly string[] | undefined;\n\tfor (let index = args.length - 1; index >= 0; index -= 1) {\n\t\tconst token = args[index];\n\t\tconst inlineScope = token.startsWith(\"--scope=\") ? token.slice(\"--scope=\".length) : undefined;\n\t\tconst selectedScope = inlineScope ?? (token === \"--scope\" ? args[index + 1] : undefined);\n\t\tif (selectedScope !== undefined) {\n\t\t\tif (selectedScope !== \"global\" && selectedScope !== \"project\") invalidInput(\"state scope is invalid\");\n\t\t\tif (scope !== undefined && scope !== selectedScope) invalidInput(\"state scope is specified more than once\");\n\t\t\tscope = selectedScope;\n\t\t\targs.splice(index, token === \"--scope\" ? 2 : 1);\n\t\t\tcontinue;\n\t\t}\n\t\tconst inlineFormat = token.startsWith(\"--format=\") ? token.slice(\"--format=\".length) : undefined;\n\t\tconst selected =\n\t\t\ttoken === \"--json\" || token === \"--text\"\n\t\t\t\t? token === \"--json\"\n\t\t\t\t\t? \"json\"\n\t\t\t\t\t: \"text\"\n\t\t\t\t: (inlineFormat ?? (token === \"--format\" ? args[index + 1] : undefined));\n\t\tif (selected !== undefined) {\n\t\t\tif (selected !== \"json\" && selected !== \"text\") invalidInput(\"output format is invalid\");\n\t\t\tif (explicitFormat !== undefined && explicitFormat !== selected)\n\t\t\t\tinvalidInput(\"output format is specified more than once\");\n\t\t\texplicitFormat = selected as PluginEcosystemCliOutputFormatV1;\n\t\t\tformat = explicitFormat;\n\t\t\targs.splice(index, token === \"--format\" ? 2 : 1);\n\t\t\tcontinue;\n\t\t}\n\t\tconst inlinePlugins = token.startsWith(\"--plugins=\") ? token.slice(\"--plugins=\".length) : undefined;\n\t\tconst selectedPlugins = inlinePlugins ?? (token === \"--plugins\" ? args[index + 1] : undefined);\n\t\tif (selectedPlugins !== undefined) {\n\t\t\tif (pluginIdsOption !== undefined) invalidInput(\"plugin IDs are specified more than once\");\n\t\t\tconst ids = selectedPlugins.split(\",\");\n\t\t\tif (ids.length > MAX_PLUGIN_SELECTION_IDS_V1) invalidInput(\"too many plugin IDs\");\n\t\t\tpluginIdsOption = Object.freeze(ids.map((id: string) => validateToken(id, \"plugin ID\")));\n\t\t\targs.splice(index, token === \"--plugins\" ? 2 : 1);\n\t\t}\n\t}\n\tif (args.length === 0) invalidInput(\"ecosystem command is invalid\");\n\t// A leading hyphenated canonical name expands to the two-word grammar; the\n\t// alias sits in the command position only, after option tokens were stripped.\n\tconst commandAlias = COMMAND_NAME_ALIASES_V1[args[0]];\n\tif (commandAlias !== undefined) args = [...commandAlias, ...args.slice(1)];\n\tconst [group, action, target, ...rest] = args;\n\tif (group === \"selection\" && action === \"set\" && target !== undefined) {\n\t\tif (pluginIdsOption !== undefined && rest.length > 0) invalidInput(\"plugin IDs must use one input form\");\n\t\tconst selectedPluginIds = pluginIdsOption ?? Object.freeze(rest.map((id) => validateToken(id, \"plugin ID\")));\n\t\tif (selectedPluginIds.length > MAX_PLUGIN_SELECTION_IDS_V1) invalidInput(\"too many plugin IDs\");\n\t\treturn Object.freeze({\n\t\t\tversion: 1,\n\t\t\tcommand: \"selection-set\",\n\t\t\tformat,\n\t\t\tprofileId: validateToken(target, \"profile ID\"),\n\t\t\tselectedPluginIds,\n\t\t\t...(scope === undefined ? {} : { scope }),\n\t\t});\n\t}\n\tif (rest.length > 0) invalidInput(\"ecosystem command has unsupported arguments\");\n\tif (group === \"catalog\" && action === \"list\" && target === undefined)\n\t\treturn Object.freeze({\n\t\t\tversion: 1,\n\t\t\tcommand: \"catalog-list\",\n\t\t\tformat,\n\t\t\t...(scope === undefined ? {} : { scope }),\n\t\t});\n\tif (group === \"state\" && action === \"list\" && target === undefined)\n\t\treturn Object.freeze({\n\t\t\tversion: 1,\n\t\t\tcommand: \"state-list\",\n\t\t\tformat,\n\t\t\t...(scope === undefined ? {} : { scope }),\n\t\t});\n\tif (group === \"selection\" && action === \"list\" && target === undefined)\n\t\treturn Object.freeze({\n\t\t\tversion: 1,\n\t\t\tcommand: \"selection-list\",\n\t\t\tformat,\n\t\t\t...(scope === undefined ? {} : { scope }),\n\t\t});\n\tif (group === \"selection\" && action === \"clear\" && target !== undefined)\n\t\treturn Object.freeze({\n\t\t\tversion: 1,\n\t\t\tcommand: \"selection-clear\",\n\t\t\tformat,\n\t\t\tprofileId: validateToken(target, \"profile ID\"),\n\t\t\t...(scope === undefined ? {} : { scope }),\n\t\t});\n\tif (group === \"state\" && (action === \"enable\" || action === \"disable\" || action === \"remove\") && target) {\n\t\tconst identity = parseIdentity(target);\n\t\treturn Object.freeze({\n\t\t\tversion: 1,\n\t\t\tcommand: action,\n\t\t\tformat,\n\t\t\t...(scope === undefined ? {} : { scope }),\n\t\t\t...identity,\n\t\t});\n\t}\n\t// Top-level aliases keep the common install/remove workflow concise while\n\t// preserving the explicit `state <action>` grammar for scripts.\n\tif ((group === \"enable\" || group === \"disable\" || group === \"remove\") && action) {\n\t\tconst identity = parseIdentity(action);\n\t\treturn Object.freeze({\n\t\t\tversion: 1,\n\t\t\tcommand: group,\n\t\t\tformat,\n\t\t\t...(scope === undefined ? {} : { scope }),\n\t\t\t...identity,\n\t\t});\n\t}\n\t// Install/update keeps the legacy `pluginId[@version]` identity grammar and\n\t// additionally preserves the raw target: refs with npm/path/URL markers\n\t// (`/`, `:`, `#`, leading `@`, `@^…`/`@~…`/`@latest`) route to the\n\t// acquisition boundary; bare IDs and exact-version identities keep the\n\t// registry resolve path unchanged.\n\tif ((group === \"install\" || group === \"update\") && action) {\n\t\tconst identity = parseIdentity(action);\n\t\treturn Object.freeze({\n\t\t\tversion: 1,\n\t\t\tcommand: group,\n\t\t\tformat,\n\t\t\ttarget: action,\n\t\t\t...(scope === undefined ? {} : { scope }),\n\t\t\t...identity,\n\t\t});\n\t}\n\tinvalidInput(\"ecosystem command is invalid\");\n}\n\nfunction response(\n\tcommand: PluginEcosystemCliResponseV1[\"command\"],\n\tformat: PluginEcosystemCliOutputFormatV1,\n\tstatus: PluginEcosystemCliResponseV1[\"status\"],\n\terror?: PluginEcosystemCliErrorV1,\n\tdata?: ResultData,\n): PluginEcosystemCliResponseV1 {\n\tlet safeData = data === undefined ? undefined : boundData(data);\n\tif (safeData !== undefined && Array.isArray(safeData.entries)) {\n\t\tlet entries = [...safeData.entries];\n\t\tconst originalEntryCount = entries.length;\n\t\twhile (entries.length > 0) {\n\t\t\tconst candidate = {\n\t\t\t\t...safeData,\n\t\t\t\tentries,\n\t\t\t\t...(entries.length < safeData.entries.length ? { truncated: true } : {}),\n\t\t\t};\n\t\t\tif (responseWithinBudget(command, format, status, error, candidate)) {\n\t\t\t\tsafeData = Object.freeze(candidate);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tentries = entries.slice(0, -1);\n\t\t}\n\t\tif (entries.length === 0 && originalEntryCount > 0)\n\t\t\tsafeData = Object.freeze({\n\t\t\t\tentries: Object.freeze([]),\n\t\t\t\ttruncated: true,\n\t\t\t});\n\t}\n\tif (!responseWithinBudget(command, format, status, error, safeData)) safeData = Object.freeze({ truncated: true });\n\tconst base = responseBase(command, format, status, error, safeData);\n\tconst humanText = error ? `${status}: ${error.message}` : formatText(command, status, safeData);\n\tconst text = format === \"json\" ? JSON.stringify(base) : humanText;\n\treturn Object.freeze({\n\t\t...base,\n\t\ttext: boundText(text),\n\t});\n}\n\nfunction responseWithinBudget(\n\tcommand: PluginEcosystemCliResponseV1[\"command\"],\n\tformat: PluginEcosystemCliOutputFormatV1,\n\tstatus: PluginEcosystemCliResponseV1[\"status\"],\n\terror: PluginEcosystemCliErrorV1 | undefined,\n\tdata: ResultData | undefined,\n): boolean {\n\tconst base = responseBase(command, format, status, error, data);\n\tconst humanText = error ? `${status}: ${error.message}` : formatText(command, status, data);\n\tconst text = format === \"json\" ? JSON.stringify(base) : humanText;\n\treturn responseByteLength({ ...base, text: boundText(text) }) <= MAX_PLUGIN_ECOSYSTEM_CLI_OUTPUT_BYTES_V1;\n}\n\nfunction responseBase(\n\tcommand: PluginEcosystemCliResponseV1[\"command\"],\n\tformat: PluginEcosystemCliOutputFormatV1,\n\tstatus: PluginEcosystemCliResponseV1[\"status\"],\n\terror: PluginEcosystemCliErrorV1 | undefined,\n\tdata: ResultData | undefined,\n): Omit<PluginEcosystemCliResponseV1, \"text\"> {\n\treturn {\n\t\tversion: PLUGIN_ECOSYSTEM_CLI_VERSION_V1,\n\t\tcommand,\n\t\tformat,\n\t\tstatus,\n\t\t...(data === undefined ? {} : { data }),\n\t\t...(error === undefined ? {} : { error }),\n\t};\n}\n\nfunction responseByteLength(value: unknown): number {\n\treturn Buffer.byteLength(JSON.stringify(value), \"utf8\");\n}\n\nfunction boundText(value: string): string {\n\tif (Buffer.byteLength(value, \"utf8\") <= MAX_PLUGIN_ECOSYSTEM_CLI_OUTPUT_BYTES_V1) return value;\n\tconst suffix = \"\\n[output truncated]\";\n\tlet lower = 0;\n\tlet upper = value.length;\n\twhile (lower < upper) {\n\t\tconst middle = Math.ceil((lower + upper) / 2);\n\t\tif (Buffer.byteLength(`${value.slice(0, middle)}${suffix}`, \"utf8\") <= MAX_PLUGIN_ECOSYSTEM_CLI_OUTPUT_BYTES_V1)\n\t\t\tlower = middle;\n\t\telse upper = middle - 1;\n\t}\n\treturn `${value.slice(0, lower)}${suffix}`;\n}\n\nfunction boundData(data: ResultData): ResultData {\n\tconst list = data.entries;\n\tif (!Array.isArray(list) || list.length <= MAX_PLUGIN_ECOSYSTEM_CLI_LIST_ENTRIES_V1)\n\t\treturn Object.freeze({ ...data });\n\treturn Object.freeze({\n\t\t...data,\n\t\tentries: Object.freeze(list.slice(0, MAX_PLUGIN_ECOSYSTEM_CLI_LIST_ENTRIES_V1)),\n\t\ttruncated: true,\n\t});\n}\n\nfunction formatText(command: string, status: string, data?: ResultData): string {\n\tif (data === undefined) return `${status}: ${command}`;\n\tconst entries = data.entries;\n\tif (Array.isArray(entries)) {\n\t\tconst lines = entries.map((entry) => {\n\t\t\tif (typeof entry !== \"object\" || entry === null) return String(entry);\n\t\t\tconst item = entry as Record<string, unknown>;\n\t\t\tconst id =\n\t\t\t\ttypeof item.profileId === \"string\"\n\t\t\t\t\t? `profile:${item.profileId}`\n\t\t\t\t\t: typeof item.pluginId === \"string\"\n\t\t\t\t\t\t? item.pluginId\n\t\t\t\t\t\t: \"plugin\";\n\t\t\tconst version = typeof item.pluginVersion === \"string\" ? `@${item.pluginVersion}` : \"\";\n\t\t\tconst state =\n\t\t\t\ttypeof item.status === \"string\"\n\t\t\t\t\t? ` ${item.status}`\n\t\t\t\t\t: typeof item.lifecycle === \"string\"\n\t\t\t\t\t\t? ` ${item.lifecycle}`\n\t\t\t\t\t\t: \"\";\n\t\t\treturn `${id}${version}${state}`;\n\t\t});\n\t\treturn [`${status}: ${command}`, ...lines, ...(data.truncated === true ? [\"[output truncated]\"] : [])].join(\"\\n\");\n\t}\n\tif (typeof data.profileId === \"string\") {\n\t\tconst selected = Array.isArray(data.selectedPluginIds) ? ` selected=${data.selectedPluginIds.join(\",\")}` : \"\";\n\t\tconst disabled = Array.isArray(data.disabledPluginIds) ? ` disabled=${data.disabledPluginIds.join(\",\")}` : \"\";\n\t\treturn `${status}: ${command} profile:${data.profileId}${selected}${disabled}`;\n\t}\n\treturn `${status}: ${command}`;\n}\n\nfunction safeError(code: PluginEcosystemCliErrorCodeV1): PluginEcosystemCliErrorV1 {\n\tconst messages: Record<PluginEcosystemCliErrorCodeV1, string> = {\n\t\tinvalid_command: \"The plugin ecosystem command is invalid\",\n\t\tunsupported_dependencies: \"The plugin ecosystem operation is unavailable on this host\",\n\t\tnot_found: \"The requested plugin was not found\",\n\t\tnot_installed: \"The requested plugin is not installed\",\n\t\tregistry_failed: \"The plugin registry operation failed\",\n\t\tacquisition_failed: \"The plugin package acquisition failed\",\n\t\tdistribution_failed: \"The plugin distribution operation failed\",\n\t\tincompatible: \"The requested plugin is incompatible with this host\",\n\t\talready_installed: \"This plugin version is already installed in the requested scope\",\n\t\tinstaller_failed: \"The plugin installer operation failed\",\n\t\tuninstall_failed: \"The host plugin uninstall operation failed\",\n\t\tstate_failed: \"The plugin state operation failed\",\n\t\tselection_failed: \"The plugin selection operation failed\",\n\t\tcancelled: \"Plugin ecosystem operation was cancelled\",\n\t};\n\treturn Object.freeze({ code, message: messages[code] });\n}\n\n/**\n * Invalid-command diagnostic that names the received argv and the accepted\n * grammar (plus the specific validation reason when one exists — e.g. a bad\n * --scope value), instead of the old bare \"command is invalid\".\n */\nfunction invalidCommandError(argv: readonly string[], cause: unknown): PluginEcosystemCliErrorV1 {\n\tconst genericCauses = new Set([\"ecosystem command is invalid\", \"ecosystem command has unsupported arguments\"]);\n\tconst causeMessage = cause instanceof Error ? cause.message : undefined;\n\tconst reason = causeMessage !== undefined && !genericCauses.has(causeMessage) ? ` (${causeMessage})` : \"\";\n\treturn Object.freeze({\n\t\tcode: \"invalid_command\",\n\t\tmessage: `The plugin ecosystem command is invalid: received argv [${argv.join(\" \")}]${reason}; valid commands: ${PLUGIN_ECOSYSTEM_CLI_COMMAND_USAGE_V1}`,\n\t});\n}\n\nfunction isCancelled(signal: AbortSignal | undefined): boolean {\n\treturn signal?.aborted === true;\n}\n\nfunction stateStoreOf(\n\toptions: PluginEcosystemCliOptionsV1,\n\tscope: PluginStateScopeV1 | undefined,\n): PluginStateStoreV1 | undefined {\n\tif (scope === \"project\") return options.projectStateStore;\n\treturn options.stateStore ?? options.stateHost;\n}\n\nfunction operationScope(scope: PluginStateScopeV1 | undefined): PluginStateScopeV1 {\n\treturn scope ?? \"global\";\n}\n\nfunction scopeRefOf(options: PluginEcosystemCliOptionsV1, scope: PluginStateScopeV1): string | undefined {\n\treturn scope === \"global\" ? DEFAULT_GLOBAL_PLUGIN_SCOPE_REF_V1 : options.projectScopeRef;\n}\n\nfunction installerSupportsScope(installer: PluginInstallerV1 | undefined, scope: PluginStateScopeV1): boolean {\n\treturn installer?.supportedScopes?.includes(scope) === true;\n}\n\nfunction selectionStoreOf(\n\toptions: PluginEcosystemCliOptionsV1,\n\tscope: PluginStateScopeV1 | undefined,\n): PluginSelectionStoreV1 | undefined {\n\tif (scope === \"project\") return options.projectSelectionStore;\n\treturn options.selectionStore ?? options.selectionHost;\n}\n\nfunction stateEntry(record: PluginStateRecordV1): Readonly<Record<string, unknown>> {\n\treturn Object.freeze({\n\t\tpluginId: record.pluginId,\n\t\tpluginVersion: record.pluginVersion,\n\t\tmanifestDigest: record.manifestDigest,\n\t\tscope: record.state.scope,\n\t\tscopeRef: record.state.scopeRef,\n\t\tenabled: record.state.enabled,\n\t\tlifecycle: record.state.lifecycle,\n\t\t...(record.source === undefined ? {} : { source: record.source }),\n\t});\n}\n\nfunction selectionEntry(selection: {\n\treadonly profileId: string;\n\treadonly selectedPluginIds: readonly string[];\n\treadonly disabledPluginIds: readonly string[];\n}): Readonly<Record<string, unknown>> {\n\treturn Object.freeze({\n\t\tprofileId: selection.profileId,\n\t\tselectedPluginIds: Object.freeze([...selection.selectedPluginIds]),\n\t\tdisabledPluginIds: Object.freeze([...selection.disabledPluginIds]),\n\t});\n}\n\nfunction catalogEntry(entry: {\n\treadonly pluginId: string;\n\treadonly pluginVersion: string;\n\treadonly manifestDigest: string;\n\treadonly resolution: {\n\t\treadonly status: string;\n\t\treadonly diagnostics: readonly { readonly code: string }[];\n\t};\n}): Readonly<Record<string, unknown>> {\n\treturn Object.freeze({\n\t\tpluginId: entry.pluginId,\n\t\tpluginVersion: entry.pluginVersion,\n\t\tmanifestDigest: entry.manifestDigest,\n\t\tstatus: entry.resolution.status,\n\t\tdiagnosticCodes: Object.freeze(entry.resolution.diagnostics.map((item) => item.code).slice(0, 16)),\n\t});\n}\n\nfunction findStateRecord(\n\trecords: readonly PluginStateRecordV1[],\n\tpluginId: string,\n\tpluginVersion?: string,\n\tscope?: PluginStateScopeV1,\n\tscopeRef?: string,\n): PluginStateRecordV1 | undefined {\n\treturn records.find(\n\t\t(record) =>\n\t\t\trecord.pluginId === pluginId &&\n\t\t\t(pluginVersion === undefined || record.pluginVersion === pluginVersion) &&\n\t\t\t(scope === undefined || record.state.scope === scope) &&\n\t\t\t(scopeRef === undefined || record.state.scopeRef === scopeRef),\n\t);\n}\n\nfunction findCurrentStateRecord(\n\trecords: readonly PluginStateRecordV1[],\n\tpluginId: string,\n\tscope?: PluginStateScopeV1,\n\tscopeRef?: string,\n): PluginStateRecordV1 | undefined {\n\treturn (\n\t\trecords.find(\n\t\t\t(record) =>\n\t\t\t\trecord.pluginId === pluginId &&\n\t\t\t\t(scope === undefined || record.state.scope === scope) &&\n\t\t\t\t(scopeRef === undefined || record.state.scopeRef === scopeRef) &&\n\t\t\t\trecord.state.lifecycle === \"active\",\n\t\t) ?? findStateRecord(records, pluginId, undefined, scope, scopeRef)\n\t);\n}\n\nfunction requireDependencies(\n\toptions: PluginEcosystemCliOptionsV1,\n\tscope: PluginStateScopeV1 | undefined,\n\tscopeRef: string | undefined,\n): asserts options is PluginEcosystemCliOptionsV1 & {\n\treadonly registry: PluginEcosystemRegistryV1;\n\treadonly installer: PluginInstallerV1;\n\treadonly host: HostFactsV1;\n} {\n\tconst requestedScope = operationScope(scope);\n\tif (\n\t\t!options.registry ||\n\t\t!options.installer ||\n\t\tscopeRef === undefined ||\n\t\t!installerSupportsScope(options.installer, requestedScope) ||\n\t\t!stateStoreOf(options, requestedScope) ||\n\t\t!options.host\n\t)\n\t\tthrow new Error(\"unsupported dependencies\");\n}\n\nasync function listManifests(\n\toptions: PluginEcosystemCliOptionsV1,\n\tsignal?: AbortSignal,\n): Promise<readonly PluginManifestV1[]> {\n\tif (options.registry?.list) return await options.registry.list({ signal });\n\tif (options.manifests) return options.manifests;\n\tthrow new Error(\"unsupported dependencies\");\n}\n\nfunction checkSignal(signal?: AbortSignal): void {\n\tif (isCancelled(signal)) throw new Error(\"cancelled\");\n}\n\nexport function createPluginEcosystemCliV1(options: PluginEcosystemCliOptionsV1): PluginEcosystemCliV1 {\n\t// Host installation and state persistence are a single logical transaction.\n\t// Serializing them prevents two same-version requests from both passing the\n\t// preflight state read and orphaning one physical installation.\n\tlet installTransactionTail: Promise<void> = Promise.resolve();\n\tasync function acquireInstallTransaction(): Promise<() => void> {\n\t\tlet release!: () => void;\n\t\tconst turn = new Promise<void>((resolve) => {\n\t\t\trelease = resolve;\n\t\t});\n\t\tconst previous = installTransactionTail;\n\t\tinstallTransactionTail = previous.then(\n\t\t\t() => turn,\n\t\t\t() => turn,\n\t\t);\n\t\tawait previous;\n\t\treturn release;\n\t}\n\n\tasync function execute(input: PluginEcosystemCliRequestV1): Promise<PluginEcosystemCliResponseV1> {\n\t\tlet parsed: PluginEcosystemCliParsedCommandV1;\n\t\ttry {\n\t\t\tparsed = parsePluginEcosystemCliCommandV1(input.argv, input.format ?? \"text\");\n\t\t} catch (error) {\n\t\t\treturn response(\n\t\t\t\t\"invalid\",\n\t\t\t\tinput.format === \"json\" ? \"json\" : \"text\",\n\t\t\t\t\"failed\",\n\t\t\t\tinvalidCommandError(input.argv, error),\n\t\t\t);\n\t\t}\n\t\tconst releaseInstallTransaction =\n\t\t\tparsed.command === \"install\" || parsed.command === \"update\" ? await acquireInstallTransaction() : undefined;\n\t\ttry {\n\t\t\tconst signal = input.signal;\n\t\t\tconst requestedScope = operationScope(parsed.scope);\n\t\t\tconst scopeRef = scopeRefOf(options, requestedScope);\n\t\t\tif (isCancelled(signal)) return response(parsed.command, parsed.format, \"cancelled\", safeError(\"cancelled\"));\n\t\t\tif (scopeRef === undefined)\n\t\t\t\treturn response(parsed.command, parsed.format, \"unsupported\", safeError(\"unsupported_dependencies\"));\n\t\t\tlet phase: \"registry\" | \"distribution\" | \"state\" | \"selection\" | \"installer\" = \"registry\";\n\t\t\ttry {\n\t\t\t\tif (parsed.command === \"catalog-list\") {\n\t\t\t\t\tif (!options.host)\n\t\t\t\t\t\treturn response(parsed.command, parsed.format, \"unsupported\", safeError(\"unsupported_dependencies\"));\n\t\t\t\t\tconst manifests = await listManifests(options, signal);\n\t\t\t\t\tcheckSignal(signal);\n\t\t\t\t\tconst snapshot = buildPluginCatalogV1({\n\t\t\t\t\t\tmanifests,\n\t\t\t\t\t\thost: options.host,\n\t\t\t\t\t\tmaxEntries: MAX_PLUGIN_ECOSYSTEM_CLI_LIST_ENTRIES_V1,\n\t\t\t\t\t});\n\t\t\t\t\treturn response(parsed.command, parsed.format, \"succeeded\", undefined, {\n\t\t\t\t\t\tversion: snapshot.version,\n\t\t\t\t\t\tentries: snapshot.entries.map(catalogEntry),\n\t\t\t\t\t\ttruncated: snapshot.truncated,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tif (parsed.command === \"selection-list\") {\n\t\t\t\t\tphase = \"selection\";\n\t\t\t\t\tconst selectionStore = selectionStoreOf(options, parsed.scope);\n\t\t\t\t\tif (!selectionStore)\n\t\t\t\t\t\treturn response(parsed.command, parsed.format, \"unsupported\", safeError(\"unsupported_dependencies\"));\n\t\t\t\t\tconst result = await selectionStore.read({ signal });\n\t\t\t\t\tif (result.status === \"cancelled\")\n\t\t\t\t\t\treturn response(parsed.command, parsed.format, \"cancelled\", safeError(\"cancelled\"));\n\t\t\t\t\tif (result.status === \"invalid\")\n\t\t\t\t\t\treturn response(parsed.command, parsed.format, \"failed\", safeError(\"selection_failed\"));\n\t\t\t\t\treturn response(parsed.command, parsed.format, \"succeeded\", undefined, {\n\t\t\t\t\t\tversion: result.snapshot.version,\n\t\t\t\t\t\tscope: parsed.scope ?? \"global\",\n\t\t\t\t\t\tentries: result.snapshot.selections.map(selectionEntry),\n\t\t\t\t\t\ttruncated: false,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tif (parsed.command === \"selection-set\") {\n\t\t\t\t\tphase = \"selection\";\n\t\t\t\t\tconst selectionStore = selectionStoreOf(options, parsed.scope);\n\t\t\t\t\tif (!selectionStore)\n\t\t\t\t\t\treturn response(parsed.command, parsed.format, \"unsupported\", safeError(\"unsupported_dependencies\"));\n\t\t\t\t\tlet selection: PluginSelectionV1;\n\t\t\t\t\ttry {\n\t\t\t\t\t\tselection = createPluginSelectionV1({\n\t\t\t\t\t\t\tprofileId: parsed.profileId as string,\n\t\t\t\t\t\t\tselectedPluginIds: parsed.selectedPluginIds ?? [],\n\t\t\t\t\t\t\tdisabledPluginIds: [],\n\t\t\t\t\t\t});\n\t\t\t\t\t} catch {\n\t\t\t\t\t\treturn response(parsed.command, parsed.format, \"failed\", safeError(\"selection_failed\"));\n\t\t\t\t\t}\n\t\t\t\t\tconst result = await selectionStore.set({ selection, signal });\n\t\t\t\t\tif (result.status === \"cancelled\")\n\t\t\t\t\t\treturn response(parsed.command, parsed.format, \"cancelled\", safeError(\"cancelled\"));\n\t\t\t\t\tif (result.status !== \"ok\")\n\t\t\t\t\t\treturn response(parsed.command, parsed.format, \"failed\", safeError(\"selection_failed\"));\n\t\t\t\t\treturn response(parsed.command, parsed.format, \"succeeded\", undefined, {\n\t\t\t\t\t\tprofileId: selection.profileId,\n\t\t\t\t\t\tscope: parsed.scope ?? \"global\",\n\t\t\t\t\t\tselectedPluginIds: selection.selectedPluginIds,\n\t\t\t\t\t\tdisabledPluginIds: selection.disabledPluginIds,\n\t\t\t\t\t\tchanged: result.changed,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tif (parsed.command === \"selection-clear\") {\n\t\t\t\t\tphase = \"selection\";\n\t\t\t\t\tconst selectionStore = selectionStoreOf(options, parsed.scope);\n\t\t\t\t\tif (!selectionStore)\n\t\t\t\t\t\treturn response(parsed.command, parsed.format, \"unsupported\", safeError(\"unsupported_dependencies\"));\n\t\t\t\t\tconst result = await selectionStore.clear({\n\t\t\t\t\t\tprofileId: parsed.profileId as string,\n\t\t\t\t\t\tsignal,\n\t\t\t\t\t});\n\t\t\t\t\tif (result.status === \"cancelled\")\n\t\t\t\t\t\treturn response(parsed.command, parsed.format, \"cancelled\", safeError(\"cancelled\"));\n\t\t\t\t\tif (result.status !== \"ok\")\n\t\t\t\t\t\treturn response(parsed.command, parsed.format, \"failed\", safeError(\"selection_failed\"));\n\t\t\t\t\treturn response(parsed.command, parsed.format, \"succeeded\", undefined, {\n\t\t\t\t\t\tprofileId: parsed.profileId,\n\t\t\t\t\t\tscope: parsed.scope ?? \"global\",\n\t\t\t\t\t\tchanged: result.changed,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tif (parsed.command === \"state-list\") {\n\t\t\t\t\tphase = \"state\";\n\t\t\t\t\tconst stateStore = stateStoreOf(options, requestedScope);\n\t\t\t\t\tif (!stateStore)\n\t\t\t\t\t\treturn response(parsed.command, parsed.format, \"unsupported\", safeError(\"unsupported_dependencies\"));\n\t\t\t\t\tconst result = await stateStore.read({ signal });\n\t\t\t\t\tif (result.status === \"cancelled\")\n\t\t\t\t\t\treturn response(parsed.command, parsed.format, \"cancelled\", safeError(\"cancelled\"));\n\t\t\t\t\tif (result.status === \"invalid\")\n\t\t\t\t\t\treturn response(parsed.command, parsed.format, \"failed\", safeError(\"state_failed\"));\n\t\t\t\t\tconst records = result.snapshot.records.filter(\n\t\t\t\t\t\t(record) => record.state.scope === requestedScope && record.state.scopeRef === scopeRef,\n\t\t\t\t\t);\n\t\t\t\t\treturn response(parsed.command, parsed.format, \"succeeded\", undefined, {\n\t\t\t\t\t\tversion: result.snapshot.version,\n\t\t\t\t\t\tentries: records.map(stateEntry),\n\t\t\t\t\t\ttruncated: false,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tif (parsed.command === \"enable\" || parsed.command === \"disable\" || parsed.command === \"remove\") {\n\t\t\t\t\tphase = \"state\";\n\t\t\t\t\tif (\n\t\t\t\t\t\tparsed.command === \"remove\" &&\n\t\t\t\t\t\trequestedScope === \"project\" &&\n\t\t\t\t\t\t!installerSupportsScope(options.installer, requestedScope)\n\t\t\t\t\t)\n\t\t\t\t\t\treturn response(parsed.command, parsed.format, \"unsupported\", safeError(\"unsupported_dependencies\"));\n\t\t\t\t\tconst stateStore = stateStoreOf(options, requestedScope);\n\t\t\t\t\tif (!stateStore)\n\t\t\t\t\t\treturn response(parsed.command, parsed.format, \"unsupported\", safeError(\"unsupported_dependencies\"));\n\t\t\t\t\tconst current = await stateStore.read({ signal });\n\t\t\t\t\tif (current.status === \"cancelled\")\n\t\t\t\t\t\treturn response(parsed.command, parsed.format, \"cancelled\", safeError(\"cancelled\"));\n\t\t\t\t\tif (current.status === \"invalid\")\n\t\t\t\t\t\treturn response(parsed.command, parsed.format, \"failed\", safeError(\"state_failed\"));\n\t\t\t\t\tconst record =\n\t\t\t\t\t\tparsed.pluginVersion === undefined\n\t\t\t\t\t\t\t? findCurrentStateRecord(\n\t\t\t\t\t\t\t\t\tcurrent.snapshot.records,\n\t\t\t\t\t\t\t\t\tparsed.pluginId as string,\n\t\t\t\t\t\t\t\t\trequestedScope,\n\t\t\t\t\t\t\t\t\tscopeRef,\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t: findStateRecord(\n\t\t\t\t\t\t\t\t\tcurrent.snapshot.records,\n\t\t\t\t\t\t\t\t\tparsed.pluginId as string,\n\t\t\t\t\t\t\t\t\tparsed.pluginVersion,\n\t\t\t\t\t\t\t\t\trequestedScope,\n\t\t\t\t\t\t\t\t\tscopeRef,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\tif (!record) return response(parsed.command, parsed.format, \"failed\", safeError(\"not_installed\"));\n\t\t\t\t\tif (parsed.command === \"remove\") {\n\t\t\t\t\t\t// Global state-only removal remains available for repairing stale records.\n\t\t\t\t\t\t// Project removal requires a scope-capable installer and host cleanup first.\n\t\t\t\t\t\tif (options.installer !== undefined) {\n\t\t\t\t\t\t\tlet removedFromHost: Awaited<ReturnType<PluginInstallerV1[\"remove\"]>>;\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tremovedFromHost = await options.installer.remove({\n\t\t\t\t\t\t\t\t\tinstallation: {\n\t\t\t\t\t\t\t\t\t\tversion: 1,\n\t\t\t\t\t\t\t\t\t\tpluginId: record.pluginId,\n\t\t\t\t\t\t\t\t\t\tpluginVersion: record.pluginVersion,\n\t\t\t\t\t\t\t\t\t\tmanifestDigest: record.manifestDigest,\n\t\t\t\t\t\t\t\t\t\tscope: record.state.scope,\n\t\t\t\t\t\t\t\t\t\tscopeRef: record.state.scopeRef,\n\t\t\t\t\t\t\t\t\t\tinstallationRef: record.installationRef,\n\t\t\t\t\t\t\t\t\t\tstate: record.state.lifecycle,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\tscope: requestedScope,\n\t\t\t\t\t\t\t\t\tscopeRef,\n\t\t\t\t\t\t\t\t\tsignal,\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t\treturn response(parsed.command, parsed.format, \"failed\", safeError(\"uninstall_failed\"));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (removedFromHost.status !== \"succeeded\")\n\t\t\t\t\t\t\t\treturn response(\n\t\t\t\t\t\t\t\t\tparsed.command,\n\t\t\t\t\t\t\t\t\tparsed.format,\n\t\t\t\t\t\t\t\t\tremovedFromHost.status === \"cancelled\" ? \"cancelled\" : \"failed\",\n\t\t\t\t\t\t\t\t\tsafeError(removedFromHost.status === \"cancelled\" ? \"cancelled\" : \"uninstall_failed\"),\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst removed = await stateStore.remove({\n\t\t\t\t\t\t\tpluginId: record.pluginId,\n\t\t\t\t\t\t\tpluginVersion: record.pluginVersion,\n\t\t\t\t\t\t\tscope: requestedScope,\n\t\t\t\t\t\t\tscopeRef,\n\t\t\t\t\t\t\tsignal,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tif (removed.status === \"cancelled\")\n\t\t\t\t\t\t\treturn response(parsed.command, parsed.format, \"cancelled\", safeError(\"cancelled\"));\n\t\t\t\t\t\tif (removed.status !== \"ok\")\n\t\t\t\t\t\t\treturn response(parsed.command, parsed.format, \"failed\", safeError(\"state_failed\"));\n\t\t\t\t\t\treturn response(parsed.command, parsed.format, \"succeeded\", undefined, {\n\t\t\t\t\t\t\tpluginId: record.pluginId,\n\t\t\t\t\t\t\tpluginVersion: record.pluginVersion,\n\t\t\t\t\t\t\t...(options.installer === undefined ? {} : { hostRemoved: true }),\n\t\t\t\t\t\t\tchanged: removed.changed,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\tconst enabled = parsed.command === \"enable\";\n\t\t\t\t\tconst updated = await stateStore.upsert({\n\t\t\t\t\t\tinstallation: {\n\t\t\t\t\t\t\tversion: 1,\n\t\t\t\t\t\t\tpluginId: record.pluginId,\n\t\t\t\t\t\t\tpluginVersion: record.pluginVersion,\n\t\t\t\t\t\t\tmanifestDigest: record.manifestDigest,\n\t\t\t\t\t\t\tscope: record.state.scope,\n\t\t\t\t\t\t\tscopeRef: record.state.scopeRef,\n\t\t\t\t\t\t\tinstallationRef: record.installationRef,\n\t\t\t\t\t\t\tstate: record.state.lifecycle,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tscope: requestedScope,\n\t\t\t\t\t\tenabled,\n\t\t\t\t\t\t...(record.source === undefined ? {} : { source: record.source }),\n\t\t\t\t\t\tsignal,\n\t\t\t\t\t});\n\t\t\t\t\tif (updated.status === \"cancelled\")\n\t\t\t\t\t\treturn response(parsed.command, parsed.format, \"cancelled\", safeError(\"cancelled\"));\n\t\t\t\t\tif (updated.status !== \"ok\")\n\t\t\t\t\t\treturn response(parsed.command, parsed.format, \"failed\", safeError(\"state_failed\"));\n\t\t\t\t\treturn response(parsed.command, parsed.format, \"succeeded\", undefined, {\n\t\t\t\t\t\tpluginId: record.pluginId,\n\t\t\t\t\t\tpluginVersion: record.pluginVersion,\n\t\t\t\t\t\tenabled,\n\t\t\t\t\t\tchanged: updated.changed,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\t// install/update must have every host boundary injected. They never claim success with partial services.\n\t\t\t\tconst stateStore = stateStoreOf(options, requestedScope);\n\t\t\t\t// Const locals keep the narrowing alive inside the shared install flow closure.\n\t\t\t\tconst installer = options.installer;\n\t\t\t\tconst host = options.host;\n\t\t\t\tconst acquisitionTarget =\n\t\t\t\t\tparsed.command === \"install\" &&\n\t\t\t\t\tparsed.target !== undefined &&\n\t\t\t\t\tisPluginAcquisitionRefTargetV1(parsed.target)\n\t\t\t\t\t\t? parsed.target\n\t\t\t\t\t\t: undefined;\n\t\t\t\tif (\n\t\t\t\t\t!stateStore ||\n\t\t\t\t\t!installer ||\n\t\t\t\t\t!host ||\n\t\t\t\t\t!installerSupportsScope(installer, requestedScope) ||\n\t\t\t\t\t(acquisitionTarget === undefined && !options.registry)\n\t\t\t\t)\n\t\t\t\t\treturn response(parsed.command, parsed.format, \"unsupported\", safeError(\"unsupported_dependencies\"));\n\t\t\t\t// One shared install transaction serves both resolutions: the legacy\n\t\t\t\t// registry resolve path and the multi-source acquisition ref path.\n\t\t\t\tconst runInstallFlow = async (resolved: {\n\t\t\t\t\treadonly manifest: PluginManifestV1;\n\t\t\t\t\treadonly source: string;\n\t\t\t\t\treadonly expectedDigest?: string;\n\t\t\t\t\treadonly distribution?: PluginDistributionDescriptorV1;\n\t\t\t\t\treadonly acquired?: PluginAcquisitionPackageV1;\n\t\t\t\t}): Promise<PluginEcosystemCliResponseV1> => {\n\t\t\t\t\tphase = \"state\";\n\t\t\t\t\tconst current = await stateStore.read({ signal });\n\t\t\t\t\tif (current.status === \"cancelled\")\n\t\t\t\t\t\treturn response(parsed.command, parsed.format, \"cancelled\", safeError(\"cancelled\"));\n\t\t\t\t\tif (current.status === \"invalid\")\n\t\t\t\t\t\treturn response(parsed.command, parsed.format, \"failed\", safeError(\"state_failed\"));\n\t\t\t\t\tconst previous = findCurrentStateRecord(\n\t\t\t\t\t\tcurrent.snapshot.records,\n\t\t\t\t\t\tresolved.manifest.id,\n\t\t\t\t\t\trequestedScope,\n\t\t\t\t\t\tscopeRef,\n\t\t\t\t\t);\n\t\t\t\t\tconst installedVersion = findStateRecord(\n\t\t\t\t\t\tcurrent.snapshot.records,\n\t\t\t\t\t\tresolved.manifest.id,\n\t\t\t\t\t\tresolved.manifest.pluginVersion,\n\t\t\t\t\t\trequestedScope,\n\t\t\t\t\t\tscopeRef,\n\t\t\t\t\t);\n\t\t\t\t\tif (installedVersion !== undefined)\n\t\t\t\t\t\treturn response(parsed.command, parsed.format, \"failed\", safeError(\"already_installed\"));\n\t\t\t\t\tif (parsed.command === \"update\" && (!previous || previous.state.lifecycle !== \"active\"))\n\t\t\t\t\t\treturn response(parsed.command, parsed.format, \"failed\", safeError(\"not_installed\"));\n\t\t\t\t\tphase = \"installer\";\n\t\t\t\t\tconst verified = installer.prepare({\n\t\t\t\t\t\tmanifest: resolved.manifest,\n\t\t\t\t\t\tsource: resolved.source,\n\t\t\t\t\t\thost,\n\t\t\t\t\t\t...(resolved.expectedDigest === undefined ? {} : { expectedDigest: resolved.expectedDigest }),\n\t\t\t\t\t});\n\t\t\t\t\tif (verified.status !== \"verified\")\n\t\t\t\t\t\treturn response(parsed.command, parsed.format, \"failed\", safeError(\"incompatible\"));\n\t\t\t\t\tlet artifact: Awaited<ReturnType<PluginDistributionV1[\"acquireArtifact\"]>> | undefined =\n\t\t\t\t\t\tresolved.acquired?.artifact;\n\t\t\t\t\tif (resolved.distribution !== undefined) {\n\t\t\t\t\t\tif (options.distribution === undefined)\n\t\t\t\t\t\t\treturn response(\n\t\t\t\t\t\t\t\tparsed.command,\n\t\t\t\t\t\t\t\tparsed.format,\n\t\t\t\t\t\t\t\t\"unsupported\",\n\t\t\t\t\t\t\t\tsafeError(\"unsupported_dependencies\"),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\tphase = \"distribution\";\n\t\t\t\t\t\tconst descriptor = options.distribution.validateDescriptor(resolved.distribution);\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\tdescriptor.pluginId !== verified.record.pluginId ||\n\t\t\t\t\t\t\tdescriptor.pluginVersion !== verified.record.pluginVersion ||\n\t\t\t\t\t\t\tdescriptor.manifestDigest !== verified.record.manifestDigest\n\t\t\t\t\t\t)\n\t\t\t\t\t\t\treturn response(parsed.command, parsed.format, \"failed\", safeError(\"incompatible\"));\n\t\t\t\t\t\tartifact = await options.distribution.acquireArtifact({\n\t\t\t\t\t\t\tdescriptor,\n\t\t\t\t\t\t\tsignal,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\tlet artifactReleased = false;\n\t\t\t\t\tconst releaseArtifact = async (): Promise<boolean> => {\n\t\t\t\t\t\tif (artifact === undefined || artifactReleased) return true;\n\t\t\t\t\t\tconst previousPhase = phase;\n\t\t\t\t\t\tphase = \"distribution\";\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tif (resolved.acquired !== undefined) {\n\t\t\t\t\t\t\t\t// Acquisition artifacts are owned by the acquisition boundary.\n\t\t\t\t\t\t\t\tconst released = await resolved.acquired.release();\n\t\t\t\t\t\t\t\tif (!released) return false;\n\t\t\t\t\t\t\t\tartifactReleased = true;\n\t\t\t\t\t\t\t\tphase = previousPhase;\n\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t// Cleanup must complete even after the caller has cancelled the workflow.\n\t\t\t\t\t\t\tif (options.distribution === undefined) return false;\n\t\t\t\t\t\t\tawait options.distribution.releaseArtifact({ artifact });\n\t\t\t\t\t\t\tartifactReleased = true;\n\t\t\t\t\t\t\tphase = previousPhase;\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\t\t\t\t\tlet transactionResponse: PluginEcosystemCliResponseV1 | undefined;\n\t\t\t\t\tlet transactionError: unknown;\n\t\t\t\t\tlet artifactCleanupFailed = false;\n\t\t\t\t\ttry {\n\t\t\t\t\t\ttransactionResponse = await (async (): Promise<PluginEcosystemCliResponseV1> => {\n\t\t\t\t\t\t\tcheckSignal(signal);\n\t\t\t\t\t\t\tphase = \"installer\";\n\t\t\t\t\t\t\tconst installed = await installer.install({\n\t\t\t\t\t\t\t\trecord: verified.record,\n\t\t\t\t\t\t\t\tscope: requestedScope,\n\t\t\t\t\t\t\t\tscopeRef,\n\t\t\t\t\t\t\t\t...(artifact === undefined ? {} : { artifact }),\n\t\t\t\t\t\t\t\tsignal,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tif (installed.status !== \"succeeded\") {\n\t\t\t\t\t\t\t\tif (!(await releaseArtifact()))\n\t\t\t\t\t\t\t\t\treturn response(\n\t\t\t\t\t\t\t\t\t\tparsed.command,\n\t\t\t\t\t\t\t\t\t\tparsed.format,\n\t\t\t\t\t\t\t\t\t\tisCancelled(signal) ? \"cancelled\" : \"failed\",\n\t\t\t\t\t\t\t\t\t\tsafeError(isCancelled(signal) ? \"cancelled\" : \"distribution_failed\"),\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\treturn response(\n\t\t\t\t\t\t\t\t\tparsed.command,\n\t\t\t\t\t\t\t\t\tparsed.format,\n\t\t\t\t\t\t\t\t\tinstalled.status === \"cancelled\" ? \"cancelled\" : \"failed\",\n\t\t\t\t\t\t\t\t\tsafeError(installed.status === \"cancelled\" ? \"cancelled\" : \"installer_failed\"),\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tconst activated = await installer.activate({\n\t\t\t\t\t\t\t\tinstallation: installed.installation,\n\t\t\t\t\t\t\t\trecord: verified.record,\n\t\t\t\t\t\t\t\tscope: requestedScope,\n\t\t\t\t\t\t\t\tscopeRef,\n\t\t\t\t\t\t\t\tsignal,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tif (activated.status !== \"succeeded\") {\n\t\t\t\t\t\t\t\tif (previous && previous.state.lifecycle === \"active\") {\n\t\t\t\t\t\t\t\t\tconst rollback = await installer.rollback({\n\t\t\t\t\t\t\t\t\t\tfailed: installed.installation,\n\t\t\t\t\t\t\t\t\t\tprevious: {\n\t\t\t\t\t\t\t\t\t\t\tversion: 1,\n\t\t\t\t\t\t\t\t\t\t\tpluginId: previous.pluginId,\n\t\t\t\t\t\t\t\t\t\t\tpluginVersion: previous.pluginVersion,\n\t\t\t\t\t\t\t\t\t\t\tmanifestDigest: previous.manifestDigest,\n\t\t\t\t\t\t\t\t\t\t\tscope: previous.state.scope,\n\t\t\t\t\t\t\t\t\t\t\tscopeRef: previous.state.scopeRef,\n\t\t\t\t\t\t\t\t\t\t\tinstallationRef: previous.installationRef,\n\t\t\t\t\t\t\t\t\t\t\tstate: \"active\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\tscope: requestedScope,\n\t\t\t\t\t\t\t\t\t\tscopeRef,\n\t\t\t\t\t\t\t\t\t\tsignal: undefined,\n\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\tif (rollback.status !== \"succeeded\")\n\t\t\t\t\t\t\t\t\t\treturn response(parsed.command, parsed.format, \"failed\", safeError(\"installer_failed\"));\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tconst removed = await installer.remove({\n\t\t\t\t\t\t\t\t\tinstallation: installed.installation,\n\t\t\t\t\t\t\t\t\tscope: requestedScope,\n\t\t\t\t\t\t\t\t\tscopeRef,\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\tif (removed.status !== \"succeeded\")\n\t\t\t\t\t\t\t\t\treturn response(parsed.command, parsed.format, \"failed\", safeError(\"installer_failed\"));\n\t\t\t\t\t\t\t\tif (!(await releaseArtifact()))\n\t\t\t\t\t\t\t\t\treturn response(\n\t\t\t\t\t\t\t\t\t\tparsed.command,\n\t\t\t\t\t\t\t\t\t\tparsed.format,\n\t\t\t\t\t\t\t\t\t\tisCancelled(signal) ? \"cancelled\" : \"failed\",\n\t\t\t\t\t\t\t\t\t\tsafeError(isCancelled(signal) ? \"cancelled\" : \"distribution_failed\"),\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\treturn response(\n\t\t\t\t\t\t\t\t\tparsed.command,\n\t\t\t\t\t\t\t\t\tparsed.format,\n\t\t\t\t\t\t\t\t\tactivated.status === \"cancelled\" ? \"cancelled\" : \"failed\",\n\t\t\t\t\t\t\t\t\tsafeError(activated.status === \"cancelled\" ? \"cancelled\" : \"installer_failed\"),\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tconst restoreActivatedInstallation = async (): Promise<boolean> => {\n\t\t\t\t\t\t\t\tconst replacesPrevious =\n\t\t\t\t\t\t\t\t\tprevious !== undefined &&\n\t\t\t\t\t\t\t\t\t`${previous.pluginId}@${previous.pluginVersion}` !==\n\t\t\t\t\t\t\t\t\t\t`${activated.installation.pluginId}@${activated.installation.pluginVersion}`;\n\t\t\t\t\t\t\t\tif (replacesPrevious && previous.state.lifecycle === \"active\") {\n\t\t\t\t\t\t\t\t\tconst rollback = await installer.rollback({\n\t\t\t\t\t\t\t\t\t\tfailed: activated.installation,\n\t\t\t\t\t\t\t\t\t\tprevious: {\n\t\t\t\t\t\t\t\t\t\t\tversion: 1,\n\t\t\t\t\t\t\t\t\t\t\tpluginId: previous.pluginId,\n\t\t\t\t\t\t\t\t\t\t\tpluginVersion: previous.pluginVersion,\n\t\t\t\t\t\t\t\t\t\t\tmanifestDigest: previous.manifestDigest,\n\t\t\t\t\t\t\t\t\t\t\tscope: previous.state.scope,\n\t\t\t\t\t\t\t\t\t\t\tscopeRef: previous.state.scopeRef,\n\t\t\t\t\t\t\t\t\t\t\tinstallationRef: previous.installationRef,\n\t\t\t\t\t\t\t\t\t\t\tstate: \"active\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\tscope: requestedScope,\n\t\t\t\t\t\t\t\t\t\tscopeRef,\n\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\tif (rollback.status !== \"succeeded\") return false;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (previous !== undefined && !replacesPrevious) return true;\n\t\t\t\t\t\t\t\tconst removed = await installer.remove({\n\t\t\t\t\t\t\t\t\tinstallation: activated.installation,\n\t\t\t\t\t\t\t\t\tscope: requestedScope,\n\t\t\t\t\t\t\t\t\tscopeRef,\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\treturn removed.status === \"succeeded\";\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\tconst restoreState = async (): Promise<boolean> => {\n\t\t\t\t\t\t\t\tconst replacesPrevious =\n\t\t\t\t\t\t\t\t\tprevious !== undefined &&\n\t\t\t\t\t\t\t\t\t`${previous.pluginId}@${previous.pluginVersion}` !==\n\t\t\t\t\t\t\t\t\t\t`${activated.installation.pluginId}@${activated.installation.pluginVersion}`;\n\t\t\t\t\t\t\t\tlet restored = true;\n\t\t\t\t\t\t\t\tif (previous === undefined || replacesPrevious) {\n\t\t\t\t\t\t\t\t\tconst removed = await stateStore\n\t\t\t\t\t\t\t\t\t\t.remove({\n\t\t\t\t\t\t\t\t\t\t\tpluginId: activated.installation.pluginId,\n\t\t\t\t\t\t\t\t\t\t\tpluginVersion: activated.installation.pluginVersion,\n\t\t\t\t\t\t\t\t\t\t\tscope: requestedScope,\n\t\t\t\t\t\t\t\t\t\t\tscopeRef,\n\t\t\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t\t\t.catch(() => undefined);\n\t\t\t\t\t\t\t\t\trestored = removed?.status === \"ok\";\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (previous !== undefined) {\n\t\t\t\t\t\t\t\t\tconst restoredPrevious = await stateStore\n\t\t\t\t\t\t\t\t\t\t.upsert({\n\t\t\t\t\t\t\t\t\t\t\tinstallation: {\n\t\t\t\t\t\t\t\t\t\t\t\tversion: 1,\n\t\t\t\t\t\t\t\t\t\t\t\tpluginId: previous.pluginId,\n\t\t\t\t\t\t\t\t\t\t\t\tpluginVersion: previous.pluginVersion,\n\t\t\t\t\t\t\t\t\t\t\t\tmanifestDigest: previous.manifestDigest,\n\t\t\t\t\t\t\t\t\t\t\t\tscope: previous.state.scope,\n\t\t\t\t\t\t\t\t\t\t\t\tscopeRef: previous.state.scopeRef,\n\t\t\t\t\t\t\t\t\t\t\t\tinstallationRef: previous.installationRef,\n\t\t\t\t\t\t\t\t\t\t\t\tstate: \"active\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tscope: requestedScope,\n\t\t\t\t\t\t\t\t\t\t\tenabled: previous.state.enabled,\n\t\t\t\t\t\t\t\t\t\t\t...(previous.source === undefined ? {} : { source: previous.source }),\n\t\t\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t\t\t.catch(() => undefined);\n\t\t\t\t\t\t\t\t\trestored = restored && restoredPrevious?.status === \"ok\";\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\treturn restored;\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\tconst stateFailure = async (\n\t\t\t\t\t\t\t\tstatus: \"failed\" | \"cancelled\",\n\t\t\t\t\t\t\t): Promise<PluginEcosystemCliResponseV1> => {\n\t\t\t\t\t\t\t\tconst [hostRestored, stateRestored] = await Promise.all([\n\t\t\t\t\t\t\t\t\trestoreActivatedInstallation().catch(() => false),\n\t\t\t\t\t\t\t\t\trestoreState().catch(() => false),\n\t\t\t\t\t\t\t\t]);\n\t\t\t\t\t\t\t\treturn response(\n\t\t\t\t\t\t\t\t\tparsed.command,\n\t\t\t\t\t\t\t\t\tparsed.format,\n\t\t\t\t\t\t\t\t\thostRestored && stateRestored ? status : \"failed\",\n\t\t\t\t\t\t\t\t\tsafeError(\n\t\t\t\t\t\t\t\t\t\thostRestored && stateRestored\n\t\t\t\t\t\t\t\t\t\t\t? status === \"cancelled\"\n\t\t\t\t\t\t\t\t\t\t\t\t? \"cancelled\"\n\t\t\t\t\t\t\t\t\t\t\t\t: \"state_failed\"\n\t\t\t\t\t\t\t\t\t\t\t: \"installer_failed\",\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\tif (!(await releaseArtifact())) {\n\t\t\t\t\t\t\t\tphase = \"installer\";\n\t\t\t\t\t\t\t\tconst restored = await restoreActivatedInstallation().catch(() => false);\n\t\t\t\t\t\t\t\treturn response(\n\t\t\t\t\t\t\t\t\tparsed.command,\n\t\t\t\t\t\t\t\t\tparsed.format,\n\t\t\t\t\t\t\t\t\t\"failed\",\n\t\t\t\t\t\t\t\t\tsafeError(restored ? \"distribution_failed\" : \"installer_failed\"),\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tphase = \"state\";\n\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\tprevious &&\n\t\t\t\t\t\t\t\t`${previous.pluginId}@${previous.pluginVersion}` !==\n\t\t\t\t\t\t\t\t\t`${installed.installation.pluginId}@${installed.installation.pluginVersion}`\n\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\tconst retained = await stateStore.upsert({\n\t\t\t\t\t\t\t\t\tinstallation: {\n\t\t\t\t\t\t\t\t\t\tversion: 1,\n\t\t\t\t\t\t\t\t\t\tpluginId: previous.pluginId,\n\t\t\t\t\t\t\t\t\t\tpluginVersion: previous.pluginVersion,\n\t\t\t\t\t\t\t\t\t\tmanifestDigest: previous.manifestDigest,\n\t\t\t\t\t\t\t\t\t\tscope: previous.state.scope,\n\t\t\t\t\t\t\t\t\t\tscopeRef: previous.state.scopeRef,\n\t\t\t\t\t\t\t\t\t\tinstallationRef: previous.installationRef,\n\t\t\t\t\t\t\t\t\t\tstate: \"retained\",\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\tscope: requestedScope,\n\t\t\t\t\t\t\t\t\tenabled: previous.state.enabled,\n\t\t\t\t\t\t\t\t\t...(previous.source === undefined ? {} : { source: previous.source }),\n\t\t\t\t\t\t\t\t\tsignal: undefined,\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\tif (retained.status !== \"ok\") return await stateFailure(\"failed\");\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tconst persisted = await stateStore.upsert({\n\t\t\t\t\t\t\t\tinstallation: activated.installation,\n\t\t\t\t\t\t\t\tscope: requestedScope,\n\t\t\t\t\t\t\t\tenabled: previous?.state.enabled ?? true,\n\t\t\t\t\t\t\t\t...(resolved.acquired === undefined ? {} : { source: resolved.source }),\n\t\t\t\t\t\t\t\tsignal,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tif (persisted.status === \"cancelled\") return await stateFailure(\"cancelled\");\n\t\t\t\t\t\t\tif (persisted.status !== \"ok\") return await stateFailure(\"failed\");\n\t\t\t\t\t\t\treturn response(parsed.command, parsed.format, \"succeeded\", undefined, {\n\t\t\t\t\t\t\t\tpluginId: activated.installation.pluginId,\n\t\t\t\t\t\t\t\tpluginVersion: activated.installation.pluginVersion,\n\t\t\t\t\t\t\t\tlifecycle: \"active\",\n\t\t\t\t\t\t\t\tchanged: persisted.changed,\n\t\t\t\t\t\t\t\t...(resolved.acquired === undefined ? {} : { source: resolved.source }),\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t})();\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\ttransactionError = error;\n\t\t\t\t\t} finally {\n\t\t\t\t\t\tartifactCleanupFailed = !(await releaseArtifact());\n\t\t\t\t\t}\n\t\t\t\t\tif (artifactCleanupFailed)\n\t\t\t\t\t\treturn response(parsed.command, parsed.format, \"failed\", safeError(\"distribution_failed\"));\n\t\t\t\t\tif (transactionError !== undefined) throw transactionError;\n\t\t\t\t\tif (transactionResponse === undefined)\n\t\t\t\t\t\tthrow new Error(t(\"plugin installation transaction did not complete\"));\n\t\t\t\t\treturn transactionResponse;\n\t\t\t\t};\n\t\t\t\tif (acquisitionTarget !== undefined) {\n\t\t\t\t\t// Ref installs consult the acquisition boundary instead of the\n\t\t\t\t\t// registry; the shared guard above already verified installer,\n\t\t\t\t\t// host, state store, and scope support.\n\t\t\t\t\tif (options.acquisition === undefined)\n\t\t\t\t\t\treturn response(parsed.command, parsed.format, \"unsupported\", safeError(\"unsupported_dependencies\"));\n\t\t\t\t\tphase = \"distribution\";\n\t\t\t\t\tlet acquired: PluginAcquisitionPackageV1;\n\t\t\t\t\ttry {\n\t\t\t\t\t\tacquired = await options.acquisition.resolvePackage({ ref: acquisitionTarget, signal });\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tif (isCancelled(signal) || (error instanceof PluginAcquisitionErrorV1 && error.code === \"cancelled\"))\n\t\t\t\t\t\t\treturn response(parsed.command, parsed.format, \"cancelled\", safeError(\"cancelled\"));\n\t\t\t\t\t\tif (error instanceof PluginAcquisitionErrorV1)\n\t\t\t\t\t\t\treturn response(parsed.command, parsed.format, \"failed\", {\n\t\t\t\t\t\t\t\tcode: \"acquisition_failed\",\n\t\t\t\t\t\t\t\tmessage: error.message,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\tthrow error;\n\t\t\t\t\t}\n\t\t\t\t\tcheckSignal(signal);\n\t\t\t\t\treturn await runInstallFlow({\n\t\t\t\t\t\tmanifest: acquired.manifest,\n\t\t\t\t\t\tsource: acquired.source,\n\t\t\t\t\t\tacquired,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\ttry {\n\t\t\t\t\trequireDependencies(options, requestedScope, scopeRef);\n\t\t\t\t} catch {\n\t\t\t\t\treturn response(parsed.command, parsed.format, \"unsupported\", safeError(\"unsupported_dependencies\"));\n\t\t\t\t}\n\t\t\t\tconst identity = parsed.pluginId as string;\n\t\t\t\tconst packageValue = await options.registry.resolve({\n\t\t\t\t\tpluginId: identity,\n\t\t\t\t\tpluginVersion: parsed.pluginVersion,\n\t\t\t\t\tsignal,\n\t\t\t\t});\n\t\t\t\tcheckSignal(signal);\n\t\t\t\tif (!packageValue) return response(parsed.command, parsed.format, \"failed\", safeError(\"not_found\"));\n\t\t\t\tif (\n\t\t\t\t\tpackageValue.manifest.id !== identity ||\n\t\t\t\t\t(parsed.pluginVersion !== undefined && packageValue.manifest.pluginVersion !== parsed.pluginVersion)\n\t\t\t\t)\n\t\t\t\t\treturn response(parsed.command, parsed.format, \"failed\", safeError(\"not_found\"));\n\t\t\t\treturn await runInstallFlow({\n\t\t\t\t\tmanifest: packageValue.manifest,\n\t\t\t\t\tsource: packageValue.source,\n\t\t\t\t\t...(packageValue.expectedDigest === undefined ? {} : { expectedDigest: packageValue.expectedDigest }),\n\t\t\t\t\t...(packageValue.distribution === undefined ? {} : { distribution: packageValue.distribution }),\n\t\t\t\t});\n\t\t\t} catch (error) {\n\t\t\t\tif (isCancelled(signal) || (error instanceof Error && error.message === \"cancelled\"))\n\t\t\t\t\treturn response(parsed.command, parsed.format, \"cancelled\", safeError(\"cancelled\"));\n\t\t\t\tif (error instanceof Error && error.message === \"unsupported dependencies\")\n\t\t\t\t\treturn response(parsed.command, parsed.format, \"unsupported\", safeError(\"unsupported_dependencies\"));\n\t\t\t\treturn response(\n\t\t\t\t\tparsed.command,\n\t\t\t\t\tparsed.format,\n\t\t\t\t\t\"failed\",\n\t\t\t\t\tsafeError(\n\t\t\t\t\t\tphase === \"registry\"\n\t\t\t\t\t\t\t? \"registry_failed\"\n\t\t\t\t\t\t\t: phase === \"distribution\"\n\t\t\t\t\t\t\t\t? \"distribution_failed\"\n\t\t\t\t\t\t\t\t: phase === \"state\"\n\t\t\t\t\t\t\t\t\t? \"state_failed\"\n\t\t\t\t\t\t\t\t\t: phase === \"selection\"\n\t\t\t\t\t\t\t\t\t\t? \"selection_failed\"\n\t\t\t\t\t\t\t\t\t\t: \"installer_failed\",\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\t\t} finally {\n\t\t\treleaseInstallTransaction?.();\n\t\t}\n\t}\n\treturn { execute };\n}\n\nexport async function runPluginEcosystemCliV1(\n\toptions: PluginEcosystemCliOptionsV1,\n\tinput: PluginEcosystemCliRequestV1,\n): Promise<PluginEcosystemCliResponseV1> {\n\treturn await createPluginEcosystemCliV1(options).execute(input);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../../src/plugins/ecosystem/cli.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,8BAA8B,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAC9F,OAAO,EAAsC,KAAK,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAC5F,OAAO,EAGN,KAAK,0BAA0B,EAC/B,MAAM,yBAAyB,CAAC;AAEjC,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AACnE,OAAO,KAAK,EAAuB,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAC9F,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEhE,eAAO,MAAM,+BAA+B,GAAa,CAAC;AAC1D,eAAO,MAAM,wCAAwC,QAAY,CAAC;AAClE,eAAO,MAAM,wCAAwC,MAAM,CAAC;AAC5D,eAAO,MAAM,gCAAgC,QAAkC,CAAC;AAEhF,MAAM,MAAM,gCAAgC,GAAG,MAAM,GAAG,MAAM,CAAC;AAC/D,MAAM,MAAM,+BAA+B,GACxC,cAAc,GACd,YAAY,GACZ,gBAAgB,GAChB,eAAe,GACf,iBAAiB,GACjB,QAAQ,GACR,SAAS,GACT,QAAQ,GACR,SAAS,GACT,QAAQ,CAAC;AAEZ;;;;;GAKG;AACH,eAAO,MAAM,qCAAqC,QAMgB,CAAC;AAEnE,MAAM,WAAW,uBAAuB;IACvC,QAAQ,CAAC,QAAQ,EAAE,gBAAgB,CAAC;IACpC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC,gGAAgG;IAChG,QAAQ,CAAC,YAAY,CAAC,EAAE,8BAA8B,CAAC;CACvD;AAED,uFAAuF;AACvF,MAAM,WAAW,yBAAyB;IACzC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE;QACvB,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC;KAC9B,KAAK,SAAS,gBAAgB,EAAE,GAAG,OAAO,CAAC,SAAS,gBAAgB,EAAE,CAAC,CAAC;IACzE,QAAQ,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE;QACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;QAC1B,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;QAChC,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC;KAC9B,KAAK,uBAAuB,GAAG,SAAS,GAAG,OAAO,CAAC,uBAAuB,GAAG,SAAS,CAAC,CAAC;CACzF;AAED;;;;GAIG;AACH,MAAM,WAAW,+BAA+B;IAC/C,QAAQ,CAAC,cAAc,EAAE,CAAC,KAAK,EAAE;QAChC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;QACrB,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC;KAC9B,KAAK,OAAO,CAAC,0BAA0B,CAAC,CAAC;CAC1C;AAED,MAAM,WAAW,2BAA2B;IAC3C,QAAQ,CAAC,IAAI,CAAC,EAAE,WAAW,CAAC;IAC5B,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,gBAAgB,EAAE,CAAC;IACjD,QAAQ,CAAC,QAAQ,CAAC,EAAE,yBAAyB,CAAC;IAC9C,8EAA8E;IAC9E,QAAQ,CAAC,WAAW,CAAC,EAAE,+BAA+B,CAAC;IACvD,QAAQ,CAAC,SAAS,CAAC,EAAE,iBAAiB,CAAC;IACvC,wEAAwE;IACxE,QAAQ,CAAC,YAAY,CAAC,EAAE,oBAAoB,CAAC;IAC7C,QAAQ,CAAC,UAAU,CAAC,EAAE,kBAAkB,CAAC;IACzC,4EAA4E;IAC5E,QAAQ,CAAC,SAAS,CAAC,EAAE,kBAAkB,CAAC;IACxC,4EAA4E;IAC5E,QAAQ,CAAC,iBAAiB,CAAC,EAAE,kBAAkB,CAAC;IAChD,uEAAuE;IACvE,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,cAAc,CAAC,EAAE,sBAAsB,CAAC;IACjD,gFAAgF;IAChF,QAAQ,CAAC,aAAa,CAAC,EAAE,sBAAsB,CAAC;IAChD,oFAAoF;IACpF,QAAQ,CAAC,qBAAqB,CAAC,EAAE,sBAAsB,CAAC;CACxD;AAED,MAAM,WAAW,2BAA2B;IAC3C,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,QAAQ,CAAC,MAAM,CAAC,EAAE,gCAAgC,CAAC;IACnD,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC;CAC9B;AAED,MAAM,WAAW,iCAAiC;IACjD,QAAQ,CAAC,OAAO,EAAE,OAAO,+BAA+B,CAAC;IACzD,QAAQ,CAAC,OAAO,EAAE,+BAA+B,CAAC;IAClD,QAAQ,CAAC,MAAM,EAAE,gCAAgC,CAAC;IAClD,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,+EAA+E;IAC/E,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,iBAAiB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/C,QAAQ,CAAC,KAAK,CAAC,EAAE,kBAAkB,CAAC;CACpC;AAED,MAAM,MAAM,6BAA6B,GACtC,iBAAiB,GACjB,0BAA0B,GAC1B,WAAW,GACX,eAAe,GACf,kBAAkB,GAClB,iBAAiB,GACjB,oBAAoB,GACpB,qBAAqB,GACrB,cAAc,GACd,mBAAmB,GACnB,kBAAkB,GAClB,kBAAkB,GAClB,cAAc,GACd,WAAW,CAAC;AAEf,MAAM,WAAW,yBAAyB;IACzC,QAAQ,CAAC,IAAI,EAAE,6BAA6B,CAAC;IAC7C,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,4BAA4B;IAC5C,QAAQ,CAAC,OAAO,EAAE,OAAO,+BAA+B,CAAC;IACzD,QAAQ,CAAC,OAAO,EAAE,+BAA+B,GAAG,SAAS,CAAC;IAC9D,QAAQ,CAAC,MAAM,EAAE,gCAAgC,CAAC;IAClD,QAAQ,CAAC,MAAM,EAAE,WAAW,GAAG,QAAQ,GAAG,aAAa,GAAG,WAAW,CAAC;IACtE,QAAQ,CAAC,IAAI,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAClD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,CAAC,EAAE,yBAAyB,CAAC;CAC3C;AAED,MAAM,WAAW,oBAAoB;IACpC,QAAQ,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,2BAA2B,KAAK,OAAO,CAAC,4BAA4B,CAAC,CAAC;CAChG;AA6CD,0FAA0F;AAC1F,wBAAgB,gCAAgC,CAC/C,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,aAAa,GAAE,gCAAyC,GACtD,iCAAiC,CAsInC;AAyTD,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,2BAA2B,GAAG,oBAAoB,CAuqBrG;AAED,wBAAsB,uBAAuB,CAC5C,OAAO,EAAE,2BAA2B,EACpC,KAAK,EAAE,2BAA2B,GAChC,OAAO,CAAC,4BAA4B,CAAC,CAEvC","sourcesContent":["import { Buffer } from \"node:buffer\";\n\nimport { t } from \"../../core/i18n/index.ts\";\nimport { buildPluginCatalogV1 } from \"./catalog.ts\";\nimport type { PluginDistributionDescriptorV1, PluginDistributionV1 } from \"./distribution.ts\";\nimport { DEFAULT_GLOBAL_PLUGIN_SCOPE_REF_V1, type PluginInstallerV1 } from \"./installer.ts\";\nimport {\n\tisPluginAcquisitionRefTargetV1,\n\tPluginAcquisitionErrorV1,\n\ttype PluginAcquisitionPackageV1,\n} from \"./plugin-acquisition.ts\";\nimport { createPluginSelectionV1, MAX_PLUGIN_SELECTION_IDS_V1, type PluginSelectionV1 } from \"./selection.ts\";\nimport type { PluginSelectionStoreV1 } from \"./selection-store.ts\";\nimport type { PluginStateRecordV1, PluginStateScopeV1, PluginStateStoreV1 } from \"./state.ts\";\nimport type { HostFactsV1, PluginManifestV1 } from \"./types.ts\";\n\nexport const PLUGIN_ECOSYSTEM_CLI_VERSION_V1 = 1 as const;\nexport const MAX_PLUGIN_ECOSYSTEM_CLI_OUTPUT_BYTES_V1 = 64 * 1024;\nexport const MAX_PLUGIN_ECOSYSTEM_CLI_LIST_ENTRIES_V1 = 128;\nexport const MAX_PLUGIN_ECOSYSTEM_CLI_ARGS_V1 = MAX_PLUGIN_SELECTION_IDS_V1 + 8;\n\nexport type PluginEcosystemCliOutputFormatV1 = \"json\" | \"text\";\nexport type PluginEcosystemCliCommandNameV1 =\n\t| \"catalog-list\"\n\t| \"state-list\"\n\t| \"selection-list\"\n\t| \"selection-set\"\n\t| \"selection-clear\"\n\t| \"enable\"\n\t| \"disable\"\n\t| \"remove\"\n\t| \"install\"\n\t| \"update\";\n\n/**\n * The accepted command grammar, rendered into invalid-command diagnostics so a\n * mistyped invocation names what it sent and what would have parsed (live\n * finding from the 0.85.3 user seat test: `plugin state-list` reported a bare\n * \"command is invalid\" with no received argv and no valid-command list).\n */\nexport const PLUGIN_ECOSYSTEM_CLI_COMMAND_USAGE_V1 =\n\t\"catalog list | catalog-list | state list | state-list | selection list | selection-list | \" +\n\t\"selection set <builtinPluginProfileId> <pluginId…> | selection-set <builtinPluginProfileId> <pluginId…> | \" +\n\t\"selection clear <profile> | selection-clear <profile> | enable <pluginId[@version]> | \" +\n\t\"disable <pluginId[@version]> | remove <pluginId[@version]> | state enable|disable|remove <pluginId[@version]> | \" +\n\t\"install <pluginId[@version] | ref> | update <pluginId[@version]> \" +\n\t\"[--scope global|project] [--json | --text | --format json|text]\";\n\nexport interface PluginRegistryPackageV1 {\n\treadonly manifest: PluginManifestV1;\n\treadonly source: string;\n\treadonly expectedDigest?: string;\n\t/** Optional signed package acquisition descriptor. It never contains package bytes or paths. */\n\treadonly distribution?: PluginDistributionDescriptorV1;\n}\n\n/** Registry access is intentionally host-injected; this CLI never downloads itself. */\nexport interface PluginEcosystemRegistryV1 {\n\treadonly list?: (input: {\n\t\treadonly signal?: AbortSignal;\n\t}) => readonly PluginManifestV1[] | Promise<readonly PluginManifestV1[]>;\n\treadonly resolve: (input: {\n\t\treadonly pluginId: string;\n\t\treadonly pluginVersion?: string;\n\t\treadonly signal?: AbortSignal;\n\t}) => PluginRegistryPackageV1 | undefined | Promise<PluginRegistryPackageV1 | undefined>;\n}\n\n/**\n * Host-injected multi-source acquisition boundary for `plugin install <ref>`\n * (npm / custom URL / local). Like registry access it is host-owned; the CLI\n * never downloads by itself.\n */\nexport interface PluginEcosystemCliAcquisitionV1 {\n\treadonly resolvePackage: (input: {\n\t\treadonly ref: string;\n\t\treadonly signal?: AbortSignal;\n\t}) => Promise<PluginAcquisitionPackageV1>;\n}\n\nexport interface PluginEcosystemCliOptionsV1 {\n\treadonly host?: HostFactsV1;\n\treadonly manifests?: readonly PluginManifestV1[];\n\treadonly registry?: PluginEcosystemRegistryV1;\n\t/** Optional multi-source acquisition boundary for `install <ref>` targets. */\n\treadonly acquisition?: PluginEcosystemCliAcquisitionV1;\n\treadonly installer?: PluginInstallerV1;\n\t/** Host-owned descriptor verifier and artifact acquisition boundary. */\n\treadonly distribution?: PluginDistributionV1;\n\treadonly stateStore?: PluginStateStoreV1;\n\t/** Alias for hosts that expose the persistence boundary as a state host. */\n\treadonly stateHost?: PluginStateStoreV1;\n\t/** Optional project-local state store. Global state remains the default. */\n\treadonly projectStateStore?: PluginStateStoreV1;\n\t/** Opaque concrete host namespace for project-scoped installations. */\n\treadonly projectScopeRef?: string;\n\treadonly selectionStore?: PluginSelectionStoreV1;\n\t/** Alias for hosts that expose the persistence boundary as a selection host. */\n\treadonly selectionHost?: PluginSelectionStoreV1;\n\t/** Optional project-local selection store. Global selection remains the default. */\n\treadonly projectSelectionStore?: PluginSelectionStoreV1;\n}\n\nexport interface PluginEcosystemCliRequestV1 {\n\treadonly argv: readonly string[];\n\treadonly format?: PluginEcosystemCliOutputFormatV1;\n\treadonly signal?: AbortSignal;\n}\n\nexport interface PluginEcosystemCliParsedCommandV1 {\n\treadonly version: typeof PLUGIN_ECOSYSTEM_CLI_VERSION_V1;\n\treadonly command: PluginEcosystemCliCommandNameV1;\n\treadonly format: PluginEcosystemCliOutputFormatV1;\n\treadonly pluginId?: string;\n\treadonly pluginVersion?: string;\n\t/** Raw install/update target; kept so ref forms survive the identity split. */\n\treadonly target?: string;\n\treadonly profileId?: string;\n\treadonly selectedPluginIds?: readonly string[];\n\treadonly scope?: PluginStateScopeV1;\n}\n\nexport type PluginEcosystemCliErrorCodeV1 =\n\t| \"invalid_command\"\n\t| \"unsupported_dependencies\"\n\t| \"not_found\"\n\t| \"not_installed\"\n\t| \"selection_failed\"\n\t| \"registry_failed\"\n\t| \"acquisition_failed\"\n\t| \"distribution_failed\"\n\t| \"incompatible\"\n\t| \"already_installed\"\n\t| \"installer_failed\"\n\t| \"uninstall_failed\"\n\t| \"state_failed\"\n\t| \"cancelled\";\n\nexport interface PluginEcosystemCliErrorV1 {\n\treadonly code: PluginEcosystemCliErrorCodeV1;\n\treadonly message: string;\n}\n\nexport interface PluginEcosystemCliResponseV1 {\n\treadonly version: typeof PLUGIN_ECOSYSTEM_CLI_VERSION_V1;\n\treadonly command: PluginEcosystemCliCommandNameV1 | \"invalid\";\n\treadonly format: PluginEcosystemCliOutputFormatV1;\n\treadonly status: \"succeeded\" | \"failed\" | \"unsupported\" | \"cancelled\";\n\treadonly data?: Readonly<Record<string, unknown>>;\n\treadonly text: string;\n\treadonly error?: PluginEcosystemCliErrorV1;\n}\n\nexport interface PluginEcosystemCliV1 {\n\treadonly execute: (input: PluginEcosystemCliRequestV1) => Promise<PluginEcosystemCliResponseV1>;\n}\n\ntype ResultData = Readonly<Record<string, unknown>>;\n\nfunction invalidInput(message: string): never {\n\tthrow new Error(message);\n}\n\n/**\n * Canonical hyphenated command names (the response vocabulary, e.g.\n * `plugin state-list`) map onto the two-word grammar (`state list`) so both\n * spellings parse identically. Live finding from the 0.85.3 user seat test:\n * `plugin state-list` is the natural spelling of the canonical name and was\n * rejected with a generic invalid-command error.\n */\nconst COMMAND_NAME_ALIASES_V1: Readonly<Record<string, readonly [string, string]>> = Object.freeze({\n\t\"catalog-list\": [\"catalog\", \"list\"],\n\t\"state-list\": [\"state\", \"list\"],\n\t\"selection-list\": [\"selection\", \"list\"],\n\t\"selection-set\": [\"selection\", \"set\"],\n\t\"selection-clear\": [\"selection\", \"clear\"],\n});\n\nfunction validateToken(value: string, label: string): string {\n\tif (value.length === 0 || value.length > 256 || /[\\u0000-\\u001f\\s]/u.test(value))\n\t\tinvalidInput(`${label} is invalid`);\n\treturn value;\n}\n\nfunction parseIdentity(value: string): {\n\treadonly pluginId: string;\n\treadonly pluginVersion?: string;\n} {\n\tconst token = validateToken(value, \"plugin identity\");\n\tconst at = token.lastIndexOf(\"@\");\n\tif (at <= 0) return { pluginId: token };\n\tconst pluginId = token.slice(0, at);\n\tconst pluginVersion = token.slice(at + 1);\n\tif (pluginVersion.length === 0) invalidInput(\"plugin version is invalid\");\n\treturn {\n\t\tpluginId: validateToken(pluginId, \"plugin ID\"),\n\t\tpluginVersion: validateToken(pluginVersion, \"plugin version\"),\n\t};\n}\n\n/** Parse only the ecosystem command grammar; legacy package commands are not accepted. */\nexport function parsePluginEcosystemCliCommandV1(\n\targv: readonly string[],\n\tdefaultFormat: PluginEcosystemCliOutputFormatV1 = \"text\",\n): PluginEcosystemCliParsedCommandV1 {\n\tif (!Array.isArray(argv) || argv.length === 0 || argv.length > MAX_PLUGIN_ECOSYSTEM_CLI_ARGS_V1)\n\t\tinvalidInput(\"ecosystem command is invalid\");\n\tlet format = defaultFormat;\n\tif (format !== \"json\" && format !== \"text\") invalidInput(\"output format is invalid\");\n\tlet args = [...argv];\n\tlet explicitFormat: PluginEcosystemCliOutputFormatV1 | undefined;\n\tlet scope: PluginStateScopeV1 | undefined;\n\tlet pluginIdsOption: readonly string[] | undefined;\n\tfor (let index = args.length - 1; index >= 0; index -= 1) {\n\t\tconst token = args[index];\n\t\tconst inlineScope = token.startsWith(\"--scope=\") ? token.slice(\"--scope=\".length) : undefined;\n\t\tconst selectedScope = inlineScope ?? (token === \"--scope\" ? args[index + 1] : undefined);\n\t\tif (selectedScope !== undefined) {\n\t\t\tif (selectedScope !== \"global\" && selectedScope !== \"project\") invalidInput(\"state scope is invalid\");\n\t\t\tif (scope !== undefined && scope !== selectedScope) invalidInput(\"state scope is specified more than once\");\n\t\t\tscope = selectedScope;\n\t\t\targs.splice(index, token === \"--scope\" ? 2 : 1);\n\t\t\tcontinue;\n\t\t}\n\t\tconst inlineFormat = token.startsWith(\"--format=\") ? token.slice(\"--format=\".length) : undefined;\n\t\tconst selected =\n\t\t\ttoken === \"--json\" || token === \"--text\"\n\t\t\t\t? token === \"--json\"\n\t\t\t\t\t? \"json\"\n\t\t\t\t\t: \"text\"\n\t\t\t\t: (inlineFormat ?? (token === \"--format\" ? args[index + 1] : undefined));\n\t\tif (selected !== undefined) {\n\t\t\tif (selected !== \"json\" && selected !== \"text\") invalidInput(\"output format is invalid\");\n\t\t\tif (explicitFormat !== undefined && explicitFormat !== selected)\n\t\t\t\tinvalidInput(\"output format is specified more than once\");\n\t\t\texplicitFormat = selected as PluginEcosystemCliOutputFormatV1;\n\t\t\tformat = explicitFormat;\n\t\t\targs.splice(index, token === \"--format\" ? 2 : 1);\n\t\t\tcontinue;\n\t\t}\n\t\tconst inlinePlugins = token.startsWith(\"--plugins=\") ? token.slice(\"--plugins=\".length) : undefined;\n\t\tconst selectedPlugins = inlinePlugins ?? (token === \"--plugins\" ? args[index + 1] : undefined);\n\t\tif (selectedPlugins !== undefined) {\n\t\t\tif (pluginIdsOption !== undefined) invalidInput(\"plugin IDs are specified more than once\");\n\t\t\tconst ids = selectedPlugins.split(\",\");\n\t\t\tif (ids.length > MAX_PLUGIN_SELECTION_IDS_V1) invalidInput(\"too many plugin IDs\");\n\t\t\tpluginIdsOption = Object.freeze(ids.map((id: string) => validateToken(id, \"plugin ID\")));\n\t\t\targs.splice(index, token === \"--plugins\" ? 2 : 1);\n\t\t}\n\t}\n\tif (args.length === 0) invalidInput(\"ecosystem command is invalid\");\n\t// A leading hyphenated canonical name expands to the two-word grammar; the\n\t// alias sits in the command position only, after option tokens were stripped.\n\tconst commandAlias = COMMAND_NAME_ALIASES_V1[args[0]];\n\tif (commandAlias !== undefined) args = [...commandAlias, ...args.slice(1)];\n\tconst [group, action, target, ...rest] = args;\n\tif (group === \"selection\" && action === \"set\" && target !== undefined) {\n\t\tif (pluginIdsOption !== undefined && rest.length > 0) invalidInput(\"plugin IDs must use one input form\");\n\t\tconst selectedPluginIds = pluginIdsOption ?? Object.freeze(rest.map((id) => validateToken(id, \"plugin ID\")));\n\t\tif (selectedPluginIds.length > MAX_PLUGIN_SELECTION_IDS_V1) invalidInput(\"too many plugin IDs\");\n\t\treturn Object.freeze({\n\t\t\tversion: 1,\n\t\t\tcommand: \"selection-set\",\n\t\t\tformat,\n\t\t\tprofileId: validateToken(target, \"profile ID\"),\n\t\t\tselectedPluginIds,\n\t\t\t...(scope === undefined ? {} : { scope }),\n\t\t});\n\t}\n\tif (rest.length > 0) invalidInput(\"ecosystem command has unsupported arguments\");\n\tif (group === \"catalog\" && action === \"list\" && target === undefined)\n\t\treturn Object.freeze({\n\t\t\tversion: 1,\n\t\t\tcommand: \"catalog-list\",\n\t\t\tformat,\n\t\t\t...(scope === undefined ? {} : { scope }),\n\t\t});\n\tif (group === \"state\" && action === \"list\" && target === undefined)\n\t\treturn Object.freeze({\n\t\t\tversion: 1,\n\t\t\tcommand: \"state-list\",\n\t\t\tformat,\n\t\t\t...(scope === undefined ? {} : { scope }),\n\t\t});\n\tif (group === \"selection\" && action === \"list\" && target === undefined)\n\t\treturn Object.freeze({\n\t\t\tversion: 1,\n\t\t\tcommand: \"selection-list\",\n\t\t\tformat,\n\t\t\t...(scope === undefined ? {} : { scope }),\n\t\t});\n\tif (group === \"selection\" && action === \"clear\" && target !== undefined)\n\t\treturn Object.freeze({\n\t\t\tversion: 1,\n\t\t\tcommand: \"selection-clear\",\n\t\t\tformat,\n\t\t\tprofileId: validateToken(target, \"profile ID\"),\n\t\t\t...(scope === undefined ? {} : { scope }),\n\t\t});\n\tif (group === \"state\" && (action === \"enable\" || action === \"disable\" || action === \"remove\") && target) {\n\t\tconst identity = parseIdentity(target);\n\t\treturn Object.freeze({\n\t\t\tversion: 1,\n\t\t\tcommand: action,\n\t\t\tformat,\n\t\t\t...(scope === undefined ? {} : { scope }),\n\t\t\t...identity,\n\t\t});\n\t}\n\t// Top-level aliases keep the common install/remove workflow concise while\n\t// preserving the explicit `state <action>` grammar for scripts.\n\tif ((group === \"enable\" || group === \"disable\" || group === \"remove\") && action) {\n\t\tconst identity = parseIdentity(action);\n\t\treturn Object.freeze({\n\t\t\tversion: 1,\n\t\t\tcommand: group,\n\t\t\tformat,\n\t\t\t...(scope === undefined ? {} : { scope }),\n\t\t\t...identity,\n\t\t});\n\t}\n\t// Install/update keeps the legacy `pluginId[@version]` identity grammar and\n\t// additionally preserves the raw target: refs with npm/path/URL markers\n\t// (`/`, `:`, `#`, leading `@`, `@^…`/`@~…`/`@latest`) route to the\n\t// acquisition boundary; bare IDs and exact-version identities keep the\n\t// registry resolve path unchanged.\n\tif ((group === \"install\" || group === \"update\") && action) {\n\t\tconst identity = parseIdentity(action);\n\t\treturn Object.freeze({\n\t\t\tversion: 1,\n\t\t\tcommand: group,\n\t\t\tformat,\n\t\t\ttarget: action,\n\t\t\t...(scope === undefined ? {} : { scope }),\n\t\t\t...identity,\n\t\t});\n\t}\n\tinvalidInput(\"ecosystem command is invalid\");\n}\n\nfunction response(\n\tcommand: PluginEcosystemCliResponseV1[\"command\"],\n\tformat: PluginEcosystemCliOutputFormatV1,\n\tstatus: PluginEcosystemCliResponseV1[\"status\"],\n\terror?: PluginEcosystemCliErrorV1,\n\tdata?: ResultData,\n): PluginEcosystemCliResponseV1 {\n\tlet safeData = data === undefined ? undefined : boundData(data);\n\tif (safeData !== undefined && Array.isArray(safeData.entries)) {\n\t\tlet entries = [...safeData.entries];\n\t\tconst originalEntryCount = entries.length;\n\t\twhile (entries.length > 0) {\n\t\t\tconst candidate = {\n\t\t\t\t...safeData,\n\t\t\t\tentries,\n\t\t\t\t...(entries.length < safeData.entries.length ? { truncated: true } : {}),\n\t\t\t};\n\t\t\tif (responseWithinBudget(command, format, status, error, candidate)) {\n\t\t\t\tsafeData = Object.freeze(candidate);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tentries = entries.slice(0, -1);\n\t\t}\n\t\tif (entries.length === 0 && originalEntryCount > 0)\n\t\t\tsafeData = Object.freeze({\n\t\t\t\tentries: Object.freeze([]),\n\t\t\t\ttruncated: true,\n\t\t\t});\n\t}\n\tif (!responseWithinBudget(command, format, status, error, safeData)) safeData = Object.freeze({ truncated: true });\n\tconst base = responseBase(command, format, status, error, safeData);\n\tconst humanText = error ? `${status}: ${error.message}` : formatText(command, status, safeData);\n\tconst text = format === \"json\" ? JSON.stringify(base) : humanText;\n\treturn Object.freeze({\n\t\t...base,\n\t\ttext: boundText(text),\n\t});\n}\n\nfunction responseWithinBudget(\n\tcommand: PluginEcosystemCliResponseV1[\"command\"],\n\tformat: PluginEcosystemCliOutputFormatV1,\n\tstatus: PluginEcosystemCliResponseV1[\"status\"],\n\terror: PluginEcosystemCliErrorV1 | undefined,\n\tdata: ResultData | undefined,\n): boolean {\n\tconst base = responseBase(command, format, status, error, data);\n\tconst humanText = error ? `${status}: ${error.message}` : formatText(command, status, data);\n\tconst text = format === \"json\" ? JSON.stringify(base) : humanText;\n\treturn responseByteLength({ ...base, text: boundText(text) }) <= MAX_PLUGIN_ECOSYSTEM_CLI_OUTPUT_BYTES_V1;\n}\n\nfunction responseBase(\n\tcommand: PluginEcosystemCliResponseV1[\"command\"],\n\tformat: PluginEcosystemCliOutputFormatV1,\n\tstatus: PluginEcosystemCliResponseV1[\"status\"],\n\terror: PluginEcosystemCliErrorV1 | undefined,\n\tdata: ResultData | undefined,\n): Omit<PluginEcosystemCliResponseV1, \"text\"> {\n\treturn {\n\t\tversion: PLUGIN_ECOSYSTEM_CLI_VERSION_V1,\n\t\tcommand,\n\t\tformat,\n\t\tstatus,\n\t\t...(data === undefined ? {} : { data }),\n\t\t...(error === undefined ? {} : { error }),\n\t};\n}\n\nfunction responseByteLength(value: unknown): number {\n\treturn Buffer.byteLength(JSON.stringify(value), \"utf8\");\n}\n\nfunction boundText(value: string): string {\n\tif (Buffer.byteLength(value, \"utf8\") <= MAX_PLUGIN_ECOSYSTEM_CLI_OUTPUT_BYTES_V1) return value;\n\tconst suffix = \"\\n[output truncated]\";\n\tlet lower = 0;\n\tlet upper = value.length;\n\twhile (lower < upper) {\n\t\tconst middle = Math.ceil((lower + upper) / 2);\n\t\tif (Buffer.byteLength(`${value.slice(0, middle)}${suffix}`, \"utf8\") <= MAX_PLUGIN_ECOSYSTEM_CLI_OUTPUT_BYTES_V1)\n\t\t\tlower = middle;\n\t\telse upper = middle - 1;\n\t}\n\treturn `${value.slice(0, lower)}${suffix}`;\n}\n\nfunction boundData(data: ResultData): ResultData {\n\tconst list = data.entries;\n\tif (!Array.isArray(list) || list.length <= MAX_PLUGIN_ECOSYSTEM_CLI_LIST_ENTRIES_V1)\n\t\treturn Object.freeze({ ...data });\n\treturn Object.freeze({\n\t\t...data,\n\t\tentries: Object.freeze(list.slice(0, MAX_PLUGIN_ECOSYSTEM_CLI_LIST_ENTRIES_V1)),\n\t\ttruncated: true,\n\t});\n}\n\nfunction formatText(command: string, status: string, data?: ResultData): string {\n\tif (data === undefined) return `${status}: ${command}`;\n\tconst entries = data.entries;\n\tif (Array.isArray(entries)) {\n\t\tconst lines = entries.map((entry) => {\n\t\t\tif (typeof entry !== \"object\" || entry === null) return String(entry);\n\t\t\tconst item = entry as Record<string, unknown>;\n\t\t\tconst id =\n\t\t\t\ttypeof item.profileId === \"string\"\n\t\t\t\t\t? `profile:${item.profileId}`\n\t\t\t\t\t: typeof item.pluginId === \"string\"\n\t\t\t\t\t\t? item.pluginId\n\t\t\t\t\t\t: \"plugin\";\n\t\t\tconst version = typeof item.pluginVersion === \"string\" ? `@${item.pluginVersion}` : \"\";\n\t\t\tconst state =\n\t\t\t\ttypeof item.status === \"string\"\n\t\t\t\t\t? ` ${item.status}`\n\t\t\t\t\t: typeof item.lifecycle === \"string\"\n\t\t\t\t\t\t? ` ${item.lifecycle}`\n\t\t\t\t\t\t: \"\";\n\t\t\t// A disabled record stays listed but the runtime will not load it — the\n\t\t\t// suffix keeps the visibility readable without adding noise to enabled rows.\n\t\t\tconst visibility = item.enabled === false ? \" disabled\" : \"\";\n\t\t\treturn `${id}${version}${state}${visibility}`;\n\t\t});\n\t\treturn [`${status}: ${command}`, ...lines, ...(data.truncated === true ? [\"[output truncated]\"] : [])].join(\"\\n\");\n\t}\n\tif (typeof data.profileId === \"string\") {\n\t\tconst selected = Array.isArray(data.selectedPluginIds) ? ` selected=${data.selectedPluginIds.join(\",\")}` : \"\";\n\t\tconst disabled = Array.isArray(data.disabledPluginIds) ? ` disabled=${data.disabledPluginIds.join(\",\")}` : \"\";\n\t\treturn `${status}: ${command} profile:${data.profileId}${selected}${disabled}`;\n\t}\n\tconst note = typeof data.note === \"string\" ? ` ${data.note}` : \"\";\n\treturn `${status}: ${command}${note}`;\n}\n\nfunction safeError(code: PluginEcosystemCliErrorCodeV1): PluginEcosystemCliErrorV1 {\n\tconst messages: Record<PluginEcosystemCliErrorCodeV1, string> = {\n\t\tinvalid_command: \"The plugin ecosystem command is invalid\",\n\t\tunsupported_dependencies: \"The plugin ecosystem operation is unavailable on this host\",\n\t\tnot_found: \"The requested plugin was not found\",\n\t\tnot_installed: \"The requested plugin is not installed\",\n\t\tregistry_failed: \"The plugin registry operation failed\",\n\t\tacquisition_failed: \"The plugin package acquisition failed\",\n\t\tdistribution_failed: \"The plugin distribution operation failed\",\n\t\tincompatible: \"The requested plugin is incompatible with this host\",\n\t\talready_installed: \"This plugin version is already installed in the requested scope\",\n\t\tinstaller_failed: \"The plugin installer operation failed\",\n\t\tuninstall_failed: \"The host plugin uninstall operation failed\",\n\t\tstate_failed: \"The plugin state operation failed\",\n\t\tselection_failed: \"The plugin selection operation failed\",\n\t\tcancelled: \"Plugin ecosystem operation was cancelled\",\n\t};\n\treturn Object.freeze({ code, message: messages[code] });\n}\n\n/**\n * Invalid-command diagnostic that names the received argv and the accepted\n * grammar (plus the specific validation reason when one exists — e.g. a bad\n * --scope value), instead of the old bare \"command is invalid\".\n */\nfunction invalidCommandError(argv: readonly string[], cause: unknown): PluginEcosystemCliErrorV1 {\n\tconst genericCauses = new Set([\"ecosystem command is invalid\", \"ecosystem command has unsupported arguments\"]);\n\tconst causeMessage = cause instanceof Error ? cause.message : undefined;\n\tconst reason = causeMessage !== undefined && !genericCauses.has(causeMessage) ? ` (${causeMessage})` : \"\";\n\treturn Object.freeze({\n\t\tcode: \"invalid_command\",\n\t\tmessage: `The plugin ecosystem command is invalid: received argv [${argv.join(\" \")}]${reason}; valid commands: ${PLUGIN_ECOSYSTEM_CLI_COMMAND_USAGE_V1}`,\n\t});\n}\n\nfunction isCancelled(signal: AbortSignal | undefined): boolean {\n\treturn signal?.aborted === true;\n}\n\nfunction stateStoreOf(\n\toptions: PluginEcosystemCliOptionsV1,\n\tscope: PluginStateScopeV1 | undefined,\n): PluginStateStoreV1 | undefined {\n\tif (scope === \"project\") return options.projectStateStore;\n\treturn options.stateStore ?? options.stateHost;\n}\n\nfunction operationScope(scope: PluginStateScopeV1 | undefined): PluginStateScopeV1 {\n\treturn scope ?? \"global\";\n}\n\nfunction scopeRefOf(options: PluginEcosystemCliOptionsV1, scope: PluginStateScopeV1): string | undefined {\n\treturn scope === \"global\" ? DEFAULT_GLOBAL_PLUGIN_SCOPE_REF_V1 : options.projectScopeRef;\n}\n\nfunction installerSupportsScope(installer: PluginInstallerV1 | undefined, scope: PluginStateScopeV1): boolean {\n\treturn installer?.supportedScopes?.includes(scope) === true;\n}\n\nfunction selectionStoreOf(\n\toptions: PluginEcosystemCliOptionsV1,\n\tscope: PluginStateScopeV1 | undefined,\n): PluginSelectionStoreV1 | undefined {\n\tif (scope === \"project\") return options.projectSelectionStore;\n\treturn options.selectionStore ?? options.selectionHost;\n}\n\nfunction stateEntry(record: PluginStateRecordV1): Readonly<Record<string, unknown>> {\n\treturn Object.freeze({\n\t\tpluginId: record.pluginId,\n\t\tpluginVersion: record.pluginVersion,\n\t\tmanifestDigest: record.manifestDigest,\n\t\tscope: record.state.scope,\n\t\tscopeRef: record.state.scopeRef,\n\t\tenabled: record.state.enabled,\n\t\tlifecycle: record.state.lifecycle,\n\t\t...(record.source === undefined ? {} : { source: record.source }),\n\t});\n}\n\nfunction selectionEntry(selection: {\n\treadonly profileId: string;\n\treadonly selectedPluginIds: readonly string[];\n\treadonly disabledPluginIds: readonly string[];\n}): Readonly<Record<string, unknown>> {\n\treturn Object.freeze({\n\t\tprofileId: selection.profileId,\n\t\tselectedPluginIds: Object.freeze([...selection.selectedPluginIds]),\n\t\tdisabledPluginIds: Object.freeze([...selection.disabledPluginIds]),\n\t});\n}\n\nfunction catalogEntry(entry: {\n\treadonly pluginId: string;\n\treadonly pluginVersion: string;\n\treadonly manifestDigest: string;\n\treadonly resolution: {\n\t\treadonly status: string;\n\t\treadonly diagnostics: readonly { readonly code: string }[];\n\t};\n}): Readonly<Record<string, unknown>> {\n\treturn Object.freeze({\n\t\tpluginId: entry.pluginId,\n\t\tpluginVersion: entry.pluginVersion,\n\t\tmanifestDigest: entry.manifestDigest,\n\t\tstatus: entry.resolution.status,\n\t\tdiagnosticCodes: Object.freeze(entry.resolution.diagnostics.map((item) => item.code).slice(0, 16)),\n\t});\n}\n\nfunction findStateRecord(\n\trecords: readonly PluginStateRecordV1[],\n\tpluginId: string,\n\tpluginVersion?: string,\n\tscope?: PluginStateScopeV1,\n\tscopeRef?: string,\n): PluginStateRecordV1 | undefined {\n\treturn records.find(\n\t\t(record) =>\n\t\t\trecord.pluginId === pluginId &&\n\t\t\t(pluginVersion === undefined || record.pluginVersion === pluginVersion) &&\n\t\t\t(scope === undefined || record.state.scope === scope) &&\n\t\t\t(scopeRef === undefined || record.state.scopeRef === scopeRef),\n\t);\n}\n\nfunction findCurrentStateRecord(\n\trecords: readonly PluginStateRecordV1[],\n\tpluginId: string,\n\tscope?: PluginStateScopeV1,\n\tscopeRef?: string,\n): PluginStateRecordV1 | undefined {\n\treturn (\n\t\trecords.find(\n\t\t\t(record) =>\n\t\t\t\trecord.pluginId === pluginId &&\n\t\t\t\t(scope === undefined || record.state.scope === scope) &&\n\t\t\t\t(scopeRef === undefined || record.state.scopeRef === scopeRef) &&\n\t\t\t\trecord.state.lifecycle === \"active\",\n\t\t) ?? findStateRecord(records, pluginId, undefined, scope, scopeRef)\n\t);\n}\n\nfunction requireDependencies(\n\toptions: PluginEcosystemCliOptionsV1,\n\tscope: PluginStateScopeV1 | undefined,\n\tscopeRef: string | undefined,\n): asserts options is PluginEcosystemCliOptionsV1 & {\n\treadonly registry: PluginEcosystemRegistryV1;\n\treadonly installer: PluginInstallerV1;\n\treadonly host: HostFactsV1;\n} {\n\tconst requestedScope = operationScope(scope);\n\tif (\n\t\t!options.registry ||\n\t\t!options.installer ||\n\t\tscopeRef === undefined ||\n\t\t!installerSupportsScope(options.installer, requestedScope) ||\n\t\t!stateStoreOf(options, requestedScope) ||\n\t\t!options.host\n\t)\n\t\tthrow new Error(\"unsupported dependencies\");\n}\n\nasync function listManifests(\n\toptions: PluginEcosystemCliOptionsV1,\n\tsignal?: AbortSignal,\n): Promise<readonly PluginManifestV1[]> {\n\tif (options.registry?.list) return await options.registry.list({ signal });\n\tif (options.manifests) return options.manifests;\n\tthrow new Error(\"unsupported dependencies\");\n}\n\nfunction checkSignal(signal?: AbortSignal): void {\n\tif (isCancelled(signal)) throw new Error(\"cancelled\");\n}\n\nexport function createPluginEcosystemCliV1(options: PluginEcosystemCliOptionsV1): PluginEcosystemCliV1 {\n\t// Host installation and state persistence are a single logical transaction.\n\t// Serializing them prevents two same-version requests from both passing the\n\t// preflight state read and orphaning one physical installation.\n\tlet installTransactionTail: Promise<void> = Promise.resolve();\n\tasync function acquireInstallTransaction(): Promise<() => void> {\n\t\tlet release!: () => void;\n\t\tconst turn = new Promise<void>((resolve) => {\n\t\t\trelease = resolve;\n\t\t});\n\t\tconst previous = installTransactionTail;\n\t\tinstallTransactionTail = previous.then(\n\t\t\t() => turn,\n\t\t\t() => turn,\n\t\t);\n\t\tawait previous;\n\t\treturn release;\n\t}\n\n\tasync function execute(input: PluginEcosystemCliRequestV1): Promise<PluginEcosystemCliResponseV1> {\n\t\tlet parsed: PluginEcosystemCliParsedCommandV1;\n\t\ttry {\n\t\t\tparsed = parsePluginEcosystemCliCommandV1(input.argv, input.format ?? \"text\");\n\t\t} catch (error) {\n\t\t\treturn response(\n\t\t\t\t\"invalid\",\n\t\t\t\tinput.format === \"json\" ? \"json\" : \"text\",\n\t\t\t\t\"failed\",\n\t\t\t\tinvalidCommandError(input.argv, error),\n\t\t\t);\n\t\t}\n\t\tconst releaseInstallTransaction =\n\t\t\tparsed.command === \"install\" || parsed.command === \"update\" ? await acquireInstallTransaction() : undefined;\n\t\ttry {\n\t\t\tconst signal = input.signal;\n\t\t\tconst requestedScope = operationScope(parsed.scope);\n\t\t\tconst scopeRef = scopeRefOf(options, requestedScope);\n\t\t\tif (isCancelled(signal)) return response(parsed.command, parsed.format, \"cancelled\", safeError(\"cancelled\"));\n\t\t\tif (scopeRef === undefined)\n\t\t\t\treturn response(parsed.command, parsed.format, \"unsupported\", safeError(\"unsupported_dependencies\"));\n\t\t\tlet phase: \"registry\" | \"distribution\" | \"state\" | \"selection\" | \"installer\" = \"registry\";\n\t\t\ttry {\n\t\t\t\tif (parsed.command === \"catalog-list\") {\n\t\t\t\t\tif (!options.host)\n\t\t\t\t\t\treturn response(parsed.command, parsed.format, \"unsupported\", safeError(\"unsupported_dependencies\"));\n\t\t\t\t\tconst manifests = await listManifests(options, signal);\n\t\t\t\t\tcheckSignal(signal);\n\t\t\t\t\tconst snapshot = buildPluginCatalogV1({\n\t\t\t\t\t\tmanifests,\n\t\t\t\t\t\thost: options.host,\n\t\t\t\t\t\tmaxEntries: MAX_PLUGIN_ECOSYSTEM_CLI_LIST_ENTRIES_V1,\n\t\t\t\t\t});\n\t\t\t\t\treturn response(parsed.command, parsed.format, \"succeeded\", undefined, {\n\t\t\t\t\t\tversion: snapshot.version,\n\t\t\t\t\t\tentries: snapshot.entries.map(catalogEntry),\n\t\t\t\t\t\ttruncated: snapshot.truncated,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tif (parsed.command === \"selection-list\") {\n\t\t\t\t\tphase = \"selection\";\n\t\t\t\t\tconst selectionStore = selectionStoreOf(options, parsed.scope);\n\t\t\t\t\tif (!selectionStore)\n\t\t\t\t\t\treturn response(parsed.command, parsed.format, \"unsupported\", safeError(\"unsupported_dependencies\"));\n\t\t\t\t\tconst result = await selectionStore.read({ signal });\n\t\t\t\t\tif (result.status === \"cancelled\")\n\t\t\t\t\t\treturn response(parsed.command, parsed.format, \"cancelled\", safeError(\"cancelled\"));\n\t\t\t\t\tif (result.status === \"invalid\")\n\t\t\t\t\t\treturn response(parsed.command, parsed.format, \"failed\", safeError(\"selection_failed\"));\n\t\t\t\t\treturn response(parsed.command, parsed.format, \"succeeded\", undefined, {\n\t\t\t\t\t\tversion: result.snapshot.version,\n\t\t\t\t\t\tscope: parsed.scope ?? \"global\",\n\t\t\t\t\t\tentries: result.snapshot.selections.map(selectionEntry),\n\t\t\t\t\t\ttruncated: false,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tif (parsed.command === \"selection-set\") {\n\t\t\t\t\tphase = \"selection\";\n\t\t\t\t\tconst selectionStore = selectionStoreOf(options, parsed.scope);\n\t\t\t\t\tif (!selectionStore)\n\t\t\t\t\t\treturn response(parsed.command, parsed.format, \"unsupported\", safeError(\"unsupported_dependencies\"));\n\t\t\t\t\tlet selection: PluginSelectionV1;\n\t\t\t\t\ttry {\n\t\t\t\t\t\tselection = createPluginSelectionV1({\n\t\t\t\t\t\t\tprofileId: parsed.profileId as string,\n\t\t\t\t\t\t\tselectedPluginIds: parsed.selectedPluginIds ?? [],\n\t\t\t\t\t\t\tdisabledPluginIds: [],\n\t\t\t\t\t\t});\n\t\t\t\t\t} catch {\n\t\t\t\t\t\treturn response(parsed.command, parsed.format, \"failed\", safeError(\"selection_failed\"));\n\t\t\t\t\t}\n\t\t\t\t\tconst result = await selectionStore.set({ selection, signal });\n\t\t\t\t\tif (result.status === \"cancelled\")\n\t\t\t\t\t\treturn response(parsed.command, parsed.format, \"cancelled\", safeError(\"cancelled\"));\n\t\t\t\t\tif (result.status !== \"ok\")\n\t\t\t\t\t\treturn response(parsed.command, parsed.format, \"failed\", safeError(\"selection_failed\"));\n\t\t\t\t\treturn response(parsed.command, parsed.format, \"succeeded\", undefined, {\n\t\t\t\t\t\tprofileId: selection.profileId,\n\t\t\t\t\t\tscope: parsed.scope ?? \"global\",\n\t\t\t\t\t\tselectedPluginIds: selection.selectedPluginIds,\n\t\t\t\t\t\tdisabledPluginIds: selection.disabledPluginIds,\n\t\t\t\t\t\tchanged: result.changed,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tif (parsed.command === \"selection-clear\") {\n\t\t\t\t\tphase = \"selection\";\n\t\t\t\t\tconst selectionStore = selectionStoreOf(options, parsed.scope);\n\t\t\t\t\tif (!selectionStore)\n\t\t\t\t\t\treturn response(parsed.command, parsed.format, \"unsupported\", safeError(\"unsupported_dependencies\"));\n\t\t\t\t\tconst result = await selectionStore.clear({\n\t\t\t\t\t\tprofileId: parsed.profileId as string,\n\t\t\t\t\t\tsignal,\n\t\t\t\t\t});\n\t\t\t\t\tif (result.status === \"cancelled\")\n\t\t\t\t\t\treturn response(parsed.command, parsed.format, \"cancelled\", safeError(\"cancelled\"));\n\t\t\t\t\tif (result.status !== \"ok\")\n\t\t\t\t\t\treturn response(parsed.command, parsed.format, \"failed\", safeError(\"selection_failed\"));\n\t\t\t\t\treturn response(parsed.command, parsed.format, \"succeeded\", undefined, {\n\t\t\t\t\t\tprofileId: parsed.profileId,\n\t\t\t\t\t\tscope: parsed.scope ?? \"global\",\n\t\t\t\t\t\tchanged: result.changed,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tif (parsed.command === \"state-list\") {\n\t\t\t\t\tphase = \"state\";\n\t\t\t\t\tconst stateStore = stateStoreOf(options, requestedScope);\n\t\t\t\t\tif (!stateStore)\n\t\t\t\t\t\treturn response(parsed.command, parsed.format, \"unsupported\", safeError(\"unsupported_dependencies\"));\n\t\t\t\t\tconst result = await stateStore.read({ signal });\n\t\t\t\t\tif (result.status === \"cancelled\")\n\t\t\t\t\t\treturn response(parsed.command, parsed.format, \"cancelled\", safeError(\"cancelled\"));\n\t\t\t\t\tif (result.status === \"invalid\")\n\t\t\t\t\t\treturn response(parsed.command, parsed.format, \"failed\", safeError(\"state_failed\"));\n\t\t\t\t\tconst records = result.snapshot.records.filter(\n\t\t\t\t\t\t(record) => record.state.scope === requestedScope && record.state.scopeRef === scopeRef,\n\t\t\t\t\t);\n\t\t\t\t\treturn response(parsed.command, parsed.format, \"succeeded\", undefined, {\n\t\t\t\t\t\tversion: result.snapshot.version,\n\t\t\t\t\t\tentries: records.map(stateEntry),\n\t\t\t\t\t\ttruncated: false,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tif (parsed.command === \"enable\" || parsed.command === \"disable\" || parsed.command === \"remove\") {\n\t\t\t\t\tphase = \"state\";\n\t\t\t\t\tif (\n\t\t\t\t\t\tparsed.command === \"remove\" &&\n\t\t\t\t\t\trequestedScope === \"project\" &&\n\t\t\t\t\t\t!installerSupportsScope(options.installer, requestedScope)\n\t\t\t\t\t)\n\t\t\t\t\t\treturn response(parsed.command, parsed.format, \"unsupported\", safeError(\"unsupported_dependencies\"));\n\t\t\t\t\tconst stateStore = stateStoreOf(options, requestedScope);\n\t\t\t\t\tif (!stateStore)\n\t\t\t\t\t\treturn response(parsed.command, parsed.format, \"unsupported\", safeError(\"unsupported_dependencies\"));\n\t\t\t\t\tconst current = await stateStore.read({ signal });\n\t\t\t\t\tif (current.status === \"cancelled\")\n\t\t\t\t\t\treturn response(parsed.command, parsed.format, \"cancelled\", safeError(\"cancelled\"));\n\t\t\t\t\tif (current.status === \"invalid\")\n\t\t\t\t\t\treturn response(parsed.command, parsed.format, \"failed\", safeError(\"state_failed\"));\n\t\t\t\t\tconst record =\n\t\t\t\t\t\tparsed.pluginVersion === undefined\n\t\t\t\t\t\t\t? findCurrentStateRecord(\n\t\t\t\t\t\t\t\t\tcurrent.snapshot.records,\n\t\t\t\t\t\t\t\t\tparsed.pluginId as string,\n\t\t\t\t\t\t\t\t\trequestedScope,\n\t\t\t\t\t\t\t\t\tscopeRef,\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t: findStateRecord(\n\t\t\t\t\t\t\t\t\tcurrent.snapshot.records,\n\t\t\t\t\t\t\t\t\tparsed.pluginId as string,\n\t\t\t\t\t\t\t\t\tparsed.pluginVersion,\n\t\t\t\t\t\t\t\t\trequestedScope,\n\t\t\t\t\t\t\t\t\tscopeRef,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\tif (!record) return response(parsed.command, parsed.format, \"failed\", safeError(\"not_installed\"));\n\t\t\t\t\tif (parsed.command === \"remove\") {\n\t\t\t\t\t\t// Global state-only removal remains available for repairing stale records.\n\t\t\t\t\t\t// Project removal requires a scope-capable installer and host cleanup first.\n\t\t\t\t\t\tif (options.installer !== undefined) {\n\t\t\t\t\t\t\tlet removedFromHost: Awaited<ReturnType<PluginInstallerV1[\"remove\"]>>;\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tremovedFromHost = await options.installer.remove({\n\t\t\t\t\t\t\t\t\tinstallation: {\n\t\t\t\t\t\t\t\t\t\tversion: 1,\n\t\t\t\t\t\t\t\t\t\tpluginId: record.pluginId,\n\t\t\t\t\t\t\t\t\t\tpluginVersion: record.pluginVersion,\n\t\t\t\t\t\t\t\t\t\tmanifestDigest: record.manifestDigest,\n\t\t\t\t\t\t\t\t\t\tscope: record.state.scope,\n\t\t\t\t\t\t\t\t\t\tscopeRef: record.state.scopeRef,\n\t\t\t\t\t\t\t\t\t\tinstallationRef: record.installationRef,\n\t\t\t\t\t\t\t\t\t\tstate: record.state.lifecycle,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\tscope: requestedScope,\n\t\t\t\t\t\t\t\t\tscopeRef,\n\t\t\t\t\t\t\t\t\tsignal,\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t\treturn response(parsed.command, parsed.format, \"failed\", safeError(\"uninstall_failed\"));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (removedFromHost.status !== \"succeeded\")\n\t\t\t\t\t\t\t\treturn response(\n\t\t\t\t\t\t\t\t\tparsed.command,\n\t\t\t\t\t\t\t\t\tparsed.format,\n\t\t\t\t\t\t\t\t\tremovedFromHost.status === \"cancelled\" ? \"cancelled\" : \"failed\",\n\t\t\t\t\t\t\t\t\tsafeError(removedFromHost.status === \"cancelled\" ? \"cancelled\" : \"uninstall_failed\"),\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst removed = await stateStore.remove({\n\t\t\t\t\t\t\tpluginId: record.pluginId,\n\t\t\t\t\t\t\tpluginVersion: record.pluginVersion,\n\t\t\t\t\t\t\tscope: requestedScope,\n\t\t\t\t\t\t\tscopeRef,\n\t\t\t\t\t\t\tsignal,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tif (removed.status === \"cancelled\")\n\t\t\t\t\t\t\treturn response(parsed.command, parsed.format, \"cancelled\", safeError(\"cancelled\"));\n\t\t\t\t\t\tif (removed.status !== \"ok\")\n\t\t\t\t\t\t\treturn response(parsed.command, parsed.format, \"failed\", safeError(\"state_failed\"));\n\t\t\t\t\t\treturn response(parsed.command, parsed.format, \"succeeded\", undefined, {\n\t\t\t\t\t\t\tpluginId: record.pluginId,\n\t\t\t\t\t\t\tpluginVersion: record.pluginVersion,\n\t\t\t\t\t\t\t...(options.installer === undefined ? {} : { hostRemoved: true }),\n\t\t\t\t\t\t\tchanged: removed.changed,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\tconst enabled = parsed.command === \"enable\";\n\t\t\t\t\tconst updated = await stateStore.upsert({\n\t\t\t\t\t\tinstallation: {\n\t\t\t\t\t\t\tversion: 1,\n\t\t\t\t\t\t\tpluginId: record.pluginId,\n\t\t\t\t\t\t\tpluginVersion: record.pluginVersion,\n\t\t\t\t\t\t\tmanifestDigest: record.manifestDigest,\n\t\t\t\t\t\t\tscope: record.state.scope,\n\t\t\t\t\t\t\tscopeRef: record.state.scopeRef,\n\t\t\t\t\t\t\tinstallationRef: record.installationRef,\n\t\t\t\t\t\t\tstate: record.state.lifecycle,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tscope: requestedScope,\n\t\t\t\t\t\tenabled,\n\t\t\t\t\t\t...(record.source === undefined ? {} : { source: record.source }),\n\t\t\t\t\t\tsignal,\n\t\t\t\t\t});\n\t\t\t\t\tif (updated.status === \"cancelled\")\n\t\t\t\t\t\treturn response(parsed.command, parsed.format, \"cancelled\", safeError(\"cancelled\"));\n\t\t\t\t\tif (updated.status !== \"ok\")\n\t\t\t\t\t\treturn response(parsed.command, parsed.format, \"failed\", safeError(\"state_failed\"));\n\t\t\t\t\t// Enabling a retained record only flips the flag; the runtime keeps\n\t\t\t\t\t// skipping it. The response must say so instead of implying load.\n\t\t\t\t\tconst retainedNote =\n\t\t\t\t\t\tparsed.command === \"enable\" && record.state.lifecycle !== \"active\"\n\t\t\t\t\t\t\t? t(\n\t\t\t\t\t\t\t\t\t\"only toggles the enabled flag; the record lifecycle is {lifecycle} and the runtime will not load it\",\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tlifecycle: record.state.lifecycle,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t: undefined;\n\t\t\t\t\treturn response(parsed.command, parsed.format, \"succeeded\", undefined, {\n\t\t\t\t\t\tpluginId: record.pluginId,\n\t\t\t\t\t\tpluginVersion: record.pluginVersion,\n\t\t\t\t\t\tenabled,\n\t\t\t\t\t\tchanged: updated.changed,\n\t\t\t\t\t\t...(retainedNote === undefined ? {} : { note: retainedNote }),\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\t// install/update must have every host boundary injected. They never claim success with partial services.\n\t\t\t\tconst stateStore = stateStoreOf(options, requestedScope);\n\t\t\t\t// Const locals keep the narrowing alive inside the shared install flow closure.\n\t\t\t\tconst installer = options.installer;\n\t\t\t\tconst host = options.host;\n\t\t\t\tconst acquisitionTarget =\n\t\t\t\t\tparsed.command === \"install\" &&\n\t\t\t\t\tparsed.target !== undefined &&\n\t\t\t\t\tisPluginAcquisitionRefTargetV1(parsed.target)\n\t\t\t\t\t\t? parsed.target\n\t\t\t\t\t\t: undefined;\n\t\t\t\tif (\n\t\t\t\t\t!stateStore ||\n\t\t\t\t\t!installer ||\n\t\t\t\t\t!host ||\n\t\t\t\t\t!installerSupportsScope(installer, requestedScope) ||\n\t\t\t\t\t(acquisitionTarget === undefined && !options.registry)\n\t\t\t\t)\n\t\t\t\t\treturn response(parsed.command, parsed.format, \"unsupported\", safeError(\"unsupported_dependencies\"));\n\t\t\t\t// One shared install transaction serves both resolutions: the legacy\n\t\t\t\t// registry resolve path and the multi-source acquisition ref path.\n\t\t\t\tconst runInstallFlow = async (resolved: {\n\t\t\t\t\treadonly manifest: PluginManifestV1;\n\t\t\t\t\treadonly source: string;\n\t\t\t\t\treadonly expectedDigest?: string;\n\t\t\t\t\treadonly distribution?: PluginDistributionDescriptorV1;\n\t\t\t\t\treadonly acquired?: PluginAcquisitionPackageV1;\n\t\t\t\t}): Promise<PluginEcosystemCliResponseV1> => {\n\t\t\t\t\tphase = \"state\";\n\t\t\t\t\tconst current = await stateStore.read({ signal });\n\t\t\t\t\tif (current.status === \"cancelled\")\n\t\t\t\t\t\treturn response(parsed.command, parsed.format, \"cancelled\", safeError(\"cancelled\"));\n\t\t\t\t\tif (current.status === \"invalid\")\n\t\t\t\t\t\treturn response(parsed.command, parsed.format, \"failed\", safeError(\"state_failed\"));\n\t\t\t\t\tconst previous = findCurrentStateRecord(\n\t\t\t\t\t\tcurrent.snapshot.records,\n\t\t\t\t\t\tresolved.manifest.id,\n\t\t\t\t\t\trequestedScope,\n\t\t\t\t\t\tscopeRef,\n\t\t\t\t\t);\n\t\t\t\t\tconst installedVersion = findStateRecord(\n\t\t\t\t\t\tcurrent.snapshot.records,\n\t\t\t\t\t\tresolved.manifest.id,\n\t\t\t\t\t\tresolved.manifest.pluginVersion,\n\t\t\t\t\t\trequestedScope,\n\t\t\t\t\t\tscopeRef,\n\t\t\t\t\t);\n\t\t\t\t\tif (installedVersion !== undefined)\n\t\t\t\t\t\treturn response(parsed.command, parsed.format, \"failed\", safeError(\"already_installed\"));\n\t\t\t\t\tif (parsed.command === \"update\" && (!previous || previous.state.lifecycle !== \"active\"))\n\t\t\t\t\t\treturn response(parsed.command, parsed.format, \"failed\", safeError(\"not_installed\"));\n\t\t\t\t\tphase = \"installer\";\n\t\t\t\t\tconst verified = installer.prepare({\n\t\t\t\t\t\tmanifest: resolved.manifest,\n\t\t\t\t\t\tsource: resolved.source,\n\t\t\t\t\t\thost,\n\t\t\t\t\t\t...(resolved.expectedDigest === undefined ? {} : { expectedDigest: resolved.expectedDigest }),\n\t\t\t\t\t});\n\t\t\t\t\tif (verified.status !== \"verified\")\n\t\t\t\t\t\treturn response(parsed.command, parsed.format, \"failed\", safeError(\"incompatible\"));\n\t\t\t\t\tlet artifact: Awaited<ReturnType<PluginDistributionV1[\"acquireArtifact\"]>> | undefined =\n\t\t\t\t\t\tresolved.acquired?.artifact;\n\t\t\t\t\tif (resolved.distribution !== undefined) {\n\t\t\t\t\t\tif (options.distribution === undefined)\n\t\t\t\t\t\t\treturn response(\n\t\t\t\t\t\t\t\tparsed.command,\n\t\t\t\t\t\t\t\tparsed.format,\n\t\t\t\t\t\t\t\t\"unsupported\",\n\t\t\t\t\t\t\t\tsafeError(\"unsupported_dependencies\"),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\tphase = \"distribution\";\n\t\t\t\t\t\tconst descriptor = options.distribution.validateDescriptor(resolved.distribution);\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\tdescriptor.pluginId !== verified.record.pluginId ||\n\t\t\t\t\t\t\tdescriptor.pluginVersion !== verified.record.pluginVersion ||\n\t\t\t\t\t\t\tdescriptor.manifestDigest !== verified.record.manifestDigest\n\t\t\t\t\t\t)\n\t\t\t\t\t\t\treturn response(parsed.command, parsed.format, \"failed\", safeError(\"incompatible\"));\n\t\t\t\t\t\tartifact = await options.distribution.acquireArtifact({\n\t\t\t\t\t\t\tdescriptor,\n\t\t\t\t\t\t\tsignal,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\tlet artifactReleased = false;\n\t\t\t\t\tconst releaseArtifact = async (): Promise<boolean> => {\n\t\t\t\t\t\tif (artifact === undefined || artifactReleased) return true;\n\t\t\t\t\t\tconst previousPhase = phase;\n\t\t\t\t\t\tphase = \"distribution\";\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tif (resolved.acquired !== undefined) {\n\t\t\t\t\t\t\t\t// Acquisition artifacts are owned by the acquisition boundary.\n\t\t\t\t\t\t\t\tconst released = await resolved.acquired.release();\n\t\t\t\t\t\t\t\tif (!released) return false;\n\t\t\t\t\t\t\t\tartifactReleased = true;\n\t\t\t\t\t\t\t\tphase = previousPhase;\n\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t// Cleanup must complete even after the caller has cancelled the workflow.\n\t\t\t\t\t\t\tif (options.distribution === undefined) return false;\n\t\t\t\t\t\t\tawait options.distribution.releaseArtifact({ artifact });\n\t\t\t\t\t\t\tartifactReleased = true;\n\t\t\t\t\t\t\tphase = previousPhase;\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\t\t\t\t\tlet transactionResponse: PluginEcosystemCliResponseV1 | undefined;\n\t\t\t\t\tlet transactionError: unknown;\n\t\t\t\t\tlet artifactCleanupFailed = false;\n\t\t\t\t\ttry {\n\t\t\t\t\t\ttransactionResponse = await (async (): Promise<PluginEcosystemCliResponseV1> => {\n\t\t\t\t\t\t\tcheckSignal(signal);\n\t\t\t\t\t\t\tphase = \"installer\";\n\t\t\t\t\t\t\tconst installed = await installer.install({\n\t\t\t\t\t\t\t\trecord: verified.record,\n\t\t\t\t\t\t\t\tscope: requestedScope,\n\t\t\t\t\t\t\t\tscopeRef,\n\t\t\t\t\t\t\t\t...(artifact === undefined ? {} : { artifact }),\n\t\t\t\t\t\t\t\tsignal,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tif (installed.status !== \"succeeded\") {\n\t\t\t\t\t\t\t\tif (!(await releaseArtifact()))\n\t\t\t\t\t\t\t\t\treturn response(\n\t\t\t\t\t\t\t\t\t\tparsed.command,\n\t\t\t\t\t\t\t\t\t\tparsed.format,\n\t\t\t\t\t\t\t\t\t\tisCancelled(signal) ? \"cancelled\" : \"failed\",\n\t\t\t\t\t\t\t\t\t\tsafeError(isCancelled(signal) ? \"cancelled\" : \"distribution_failed\"),\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\treturn response(\n\t\t\t\t\t\t\t\t\tparsed.command,\n\t\t\t\t\t\t\t\t\tparsed.format,\n\t\t\t\t\t\t\t\t\tinstalled.status === \"cancelled\" ? \"cancelled\" : \"failed\",\n\t\t\t\t\t\t\t\t\tsafeError(installed.status === \"cancelled\" ? \"cancelled\" : \"installer_failed\"),\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tconst activated = await installer.activate({\n\t\t\t\t\t\t\t\tinstallation: installed.installation,\n\t\t\t\t\t\t\t\trecord: verified.record,\n\t\t\t\t\t\t\t\tscope: requestedScope,\n\t\t\t\t\t\t\t\tscopeRef,\n\t\t\t\t\t\t\t\tsignal,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tif (activated.status !== \"succeeded\") {\n\t\t\t\t\t\t\t\tif (previous && previous.state.lifecycle === \"active\") {\n\t\t\t\t\t\t\t\t\tconst rollback = await installer.rollback({\n\t\t\t\t\t\t\t\t\t\tfailed: installed.installation,\n\t\t\t\t\t\t\t\t\t\tprevious: {\n\t\t\t\t\t\t\t\t\t\t\tversion: 1,\n\t\t\t\t\t\t\t\t\t\t\tpluginId: previous.pluginId,\n\t\t\t\t\t\t\t\t\t\t\tpluginVersion: previous.pluginVersion,\n\t\t\t\t\t\t\t\t\t\t\tmanifestDigest: previous.manifestDigest,\n\t\t\t\t\t\t\t\t\t\t\tscope: previous.state.scope,\n\t\t\t\t\t\t\t\t\t\t\tscopeRef: previous.state.scopeRef,\n\t\t\t\t\t\t\t\t\t\t\tinstallationRef: previous.installationRef,\n\t\t\t\t\t\t\t\t\t\t\tstate: \"active\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\tscope: requestedScope,\n\t\t\t\t\t\t\t\t\t\tscopeRef,\n\t\t\t\t\t\t\t\t\t\tsignal: undefined,\n\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\tif (rollback.status !== \"succeeded\")\n\t\t\t\t\t\t\t\t\t\treturn response(parsed.command, parsed.format, \"failed\", safeError(\"installer_failed\"));\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tconst removed = await installer.remove({\n\t\t\t\t\t\t\t\t\tinstallation: installed.installation,\n\t\t\t\t\t\t\t\t\tscope: requestedScope,\n\t\t\t\t\t\t\t\t\tscopeRef,\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\tif (removed.status !== \"succeeded\")\n\t\t\t\t\t\t\t\t\treturn response(parsed.command, parsed.format, \"failed\", safeError(\"installer_failed\"));\n\t\t\t\t\t\t\t\tif (!(await releaseArtifact()))\n\t\t\t\t\t\t\t\t\treturn response(\n\t\t\t\t\t\t\t\t\t\tparsed.command,\n\t\t\t\t\t\t\t\t\t\tparsed.format,\n\t\t\t\t\t\t\t\t\t\tisCancelled(signal) ? \"cancelled\" : \"failed\",\n\t\t\t\t\t\t\t\t\t\tsafeError(isCancelled(signal) ? \"cancelled\" : \"distribution_failed\"),\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\treturn response(\n\t\t\t\t\t\t\t\t\tparsed.command,\n\t\t\t\t\t\t\t\t\tparsed.format,\n\t\t\t\t\t\t\t\t\tactivated.status === \"cancelled\" ? \"cancelled\" : \"failed\",\n\t\t\t\t\t\t\t\t\tsafeError(activated.status === \"cancelled\" ? \"cancelled\" : \"installer_failed\"),\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tconst restoreActivatedInstallation = async (): Promise<boolean> => {\n\t\t\t\t\t\t\t\tconst replacesPrevious =\n\t\t\t\t\t\t\t\t\tprevious !== undefined &&\n\t\t\t\t\t\t\t\t\t`${previous.pluginId}@${previous.pluginVersion}` !==\n\t\t\t\t\t\t\t\t\t\t`${activated.installation.pluginId}@${activated.installation.pluginVersion}`;\n\t\t\t\t\t\t\t\tif (replacesPrevious && previous.state.lifecycle === \"active\") {\n\t\t\t\t\t\t\t\t\tconst rollback = await installer.rollback({\n\t\t\t\t\t\t\t\t\t\tfailed: activated.installation,\n\t\t\t\t\t\t\t\t\t\tprevious: {\n\t\t\t\t\t\t\t\t\t\t\tversion: 1,\n\t\t\t\t\t\t\t\t\t\t\tpluginId: previous.pluginId,\n\t\t\t\t\t\t\t\t\t\t\tpluginVersion: previous.pluginVersion,\n\t\t\t\t\t\t\t\t\t\t\tmanifestDigest: previous.manifestDigest,\n\t\t\t\t\t\t\t\t\t\t\tscope: previous.state.scope,\n\t\t\t\t\t\t\t\t\t\t\tscopeRef: previous.state.scopeRef,\n\t\t\t\t\t\t\t\t\t\t\tinstallationRef: previous.installationRef,\n\t\t\t\t\t\t\t\t\t\t\tstate: \"active\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\tscope: requestedScope,\n\t\t\t\t\t\t\t\t\t\tscopeRef,\n\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\tif (rollback.status !== \"succeeded\") return false;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (previous !== undefined && !replacesPrevious) return true;\n\t\t\t\t\t\t\t\tconst removed = await installer.remove({\n\t\t\t\t\t\t\t\t\tinstallation: activated.installation,\n\t\t\t\t\t\t\t\t\tscope: requestedScope,\n\t\t\t\t\t\t\t\t\tscopeRef,\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\treturn removed.status === \"succeeded\";\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\tconst restoreState = async (): Promise<boolean> => {\n\t\t\t\t\t\t\t\tconst replacesPrevious =\n\t\t\t\t\t\t\t\t\tprevious !== undefined &&\n\t\t\t\t\t\t\t\t\t`${previous.pluginId}@${previous.pluginVersion}` !==\n\t\t\t\t\t\t\t\t\t\t`${activated.installation.pluginId}@${activated.installation.pluginVersion}`;\n\t\t\t\t\t\t\t\tlet restored = true;\n\t\t\t\t\t\t\t\tif (previous === undefined || replacesPrevious) {\n\t\t\t\t\t\t\t\t\tconst removed = await stateStore\n\t\t\t\t\t\t\t\t\t\t.remove({\n\t\t\t\t\t\t\t\t\t\t\tpluginId: activated.installation.pluginId,\n\t\t\t\t\t\t\t\t\t\t\tpluginVersion: activated.installation.pluginVersion,\n\t\t\t\t\t\t\t\t\t\t\tscope: requestedScope,\n\t\t\t\t\t\t\t\t\t\t\tscopeRef,\n\t\t\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t\t\t.catch(() => undefined);\n\t\t\t\t\t\t\t\t\trestored = removed?.status === \"ok\";\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (previous !== undefined) {\n\t\t\t\t\t\t\t\t\tconst restoredPrevious = await stateStore\n\t\t\t\t\t\t\t\t\t\t.upsert({\n\t\t\t\t\t\t\t\t\t\t\tinstallation: {\n\t\t\t\t\t\t\t\t\t\t\t\tversion: 1,\n\t\t\t\t\t\t\t\t\t\t\t\tpluginId: previous.pluginId,\n\t\t\t\t\t\t\t\t\t\t\t\tpluginVersion: previous.pluginVersion,\n\t\t\t\t\t\t\t\t\t\t\t\tmanifestDigest: previous.manifestDigest,\n\t\t\t\t\t\t\t\t\t\t\t\tscope: previous.state.scope,\n\t\t\t\t\t\t\t\t\t\t\t\tscopeRef: previous.state.scopeRef,\n\t\t\t\t\t\t\t\t\t\t\t\tinstallationRef: previous.installationRef,\n\t\t\t\t\t\t\t\t\t\t\t\tstate: \"active\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tscope: requestedScope,\n\t\t\t\t\t\t\t\t\t\t\tenabled: previous.state.enabled,\n\t\t\t\t\t\t\t\t\t\t\t...(previous.source === undefined ? {} : { source: previous.source }),\n\t\t\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t\t\t.catch(() => undefined);\n\t\t\t\t\t\t\t\t\trestored = restored && restoredPrevious?.status === \"ok\";\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\treturn restored;\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\tconst stateFailure = async (\n\t\t\t\t\t\t\t\tstatus: \"failed\" | \"cancelled\",\n\t\t\t\t\t\t\t): Promise<PluginEcosystemCliResponseV1> => {\n\t\t\t\t\t\t\t\tconst [hostRestored, stateRestored] = await Promise.all([\n\t\t\t\t\t\t\t\t\trestoreActivatedInstallation().catch(() => false),\n\t\t\t\t\t\t\t\t\trestoreState().catch(() => false),\n\t\t\t\t\t\t\t\t]);\n\t\t\t\t\t\t\t\treturn response(\n\t\t\t\t\t\t\t\t\tparsed.command,\n\t\t\t\t\t\t\t\t\tparsed.format,\n\t\t\t\t\t\t\t\t\thostRestored && stateRestored ? status : \"failed\",\n\t\t\t\t\t\t\t\t\tsafeError(\n\t\t\t\t\t\t\t\t\t\thostRestored && stateRestored\n\t\t\t\t\t\t\t\t\t\t\t? status === \"cancelled\"\n\t\t\t\t\t\t\t\t\t\t\t\t? \"cancelled\"\n\t\t\t\t\t\t\t\t\t\t\t\t: \"state_failed\"\n\t\t\t\t\t\t\t\t\t\t\t: \"installer_failed\",\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\tif (!(await releaseArtifact())) {\n\t\t\t\t\t\t\t\tphase = \"installer\";\n\t\t\t\t\t\t\t\tconst restored = await restoreActivatedInstallation().catch(() => false);\n\t\t\t\t\t\t\t\treturn response(\n\t\t\t\t\t\t\t\t\tparsed.command,\n\t\t\t\t\t\t\t\t\tparsed.format,\n\t\t\t\t\t\t\t\t\t\"failed\",\n\t\t\t\t\t\t\t\t\tsafeError(restored ? \"distribution_failed\" : \"installer_failed\"),\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tphase = \"state\";\n\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\tprevious &&\n\t\t\t\t\t\t\t\t`${previous.pluginId}@${previous.pluginVersion}` !==\n\t\t\t\t\t\t\t\t\t`${installed.installation.pluginId}@${installed.installation.pluginVersion}`\n\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\tconst retained = await stateStore.upsert({\n\t\t\t\t\t\t\t\t\tinstallation: {\n\t\t\t\t\t\t\t\t\t\tversion: 1,\n\t\t\t\t\t\t\t\t\t\tpluginId: previous.pluginId,\n\t\t\t\t\t\t\t\t\t\tpluginVersion: previous.pluginVersion,\n\t\t\t\t\t\t\t\t\t\tmanifestDigest: previous.manifestDigest,\n\t\t\t\t\t\t\t\t\t\tscope: previous.state.scope,\n\t\t\t\t\t\t\t\t\t\tscopeRef: previous.state.scopeRef,\n\t\t\t\t\t\t\t\t\t\tinstallationRef: previous.installationRef,\n\t\t\t\t\t\t\t\t\t\tstate: \"retained\",\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\tscope: requestedScope,\n\t\t\t\t\t\t\t\t\tenabled: previous.state.enabled,\n\t\t\t\t\t\t\t\t\t...(previous.source === undefined ? {} : { source: previous.source }),\n\t\t\t\t\t\t\t\t\tsignal: undefined,\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\tif (retained.status !== \"ok\") return await stateFailure(\"failed\");\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tconst persisted = await stateStore.upsert({\n\t\t\t\t\t\t\t\tinstallation: activated.installation,\n\t\t\t\t\t\t\t\tscope: requestedScope,\n\t\t\t\t\t\t\t\tenabled: previous?.state.enabled ?? true,\n\t\t\t\t\t\t\t\t...(resolved.acquired === undefined ? {} : { source: resolved.source }),\n\t\t\t\t\t\t\t\tsignal,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tif (persisted.status === \"cancelled\") return await stateFailure(\"cancelled\");\n\t\t\t\t\t\t\tif (persisted.status !== \"ok\") return await stateFailure(\"failed\");\n\t\t\t\t\t\t\treturn response(parsed.command, parsed.format, \"succeeded\", undefined, {\n\t\t\t\t\t\t\t\tpluginId: activated.installation.pluginId,\n\t\t\t\t\t\t\t\tpluginVersion: activated.installation.pluginVersion,\n\t\t\t\t\t\t\t\tlifecycle: \"active\",\n\t\t\t\t\t\t\t\tchanged: persisted.changed,\n\t\t\t\t\t\t\t\t...(resolved.acquired === undefined ? {} : { source: resolved.source }),\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t})();\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\ttransactionError = error;\n\t\t\t\t\t} finally {\n\t\t\t\t\t\tartifactCleanupFailed = !(await releaseArtifact());\n\t\t\t\t\t}\n\t\t\t\t\tif (artifactCleanupFailed)\n\t\t\t\t\t\treturn response(parsed.command, parsed.format, \"failed\", safeError(\"distribution_failed\"));\n\t\t\t\t\tif (transactionError !== undefined) throw transactionError;\n\t\t\t\t\tif (transactionResponse === undefined)\n\t\t\t\t\t\tthrow new Error(t(\"plugin installation transaction did not complete\"));\n\t\t\t\t\treturn transactionResponse;\n\t\t\t\t};\n\t\t\t\tif (acquisitionTarget !== undefined) {\n\t\t\t\t\t// Ref installs consult the acquisition boundary instead of the\n\t\t\t\t\t// registry; the shared guard above already verified installer,\n\t\t\t\t\t// host, state store, and scope support.\n\t\t\t\t\tif (options.acquisition === undefined)\n\t\t\t\t\t\treturn response(parsed.command, parsed.format, \"unsupported\", safeError(\"unsupported_dependencies\"));\n\t\t\t\t\tphase = \"distribution\";\n\t\t\t\t\tlet acquired: PluginAcquisitionPackageV1;\n\t\t\t\t\ttry {\n\t\t\t\t\t\tacquired = await options.acquisition.resolvePackage({ ref: acquisitionTarget, signal });\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tif (isCancelled(signal) || (error instanceof PluginAcquisitionErrorV1 && error.code === \"cancelled\"))\n\t\t\t\t\t\t\treturn response(parsed.command, parsed.format, \"cancelled\", safeError(\"cancelled\"));\n\t\t\t\t\t\tif (error instanceof PluginAcquisitionErrorV1)\n\t\t\t\t\t\t\treturn response(parsed.command, parsed.format, \"failed\", {\n\t\t\t\t\t\t\t\tcode: \"acquisition_failed\",\n\t\t\t\t\t\t\t\tmessage: error.message,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\tthrow error;\n\t\t\t\t\t}\n\t\t\t\t\tcheckSignal(signal);\n\t\t\t\t\treturn await runInstallFlow({\n\t\t\t\t\t\tmanifest: acquired.manifest,\n\t\t\t\t\t\tsource: acquired.source,\n\t\t\t\t\t\tacquired,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\ttry {\n\t\t\t\t\trequireDependencies(options, requestedScope, scopeRef);\n\t\t\t\t} catch {\n\t\t\t\t\treturn response(parsed.command, parsed.format, \"unsupported\", safeError(\"unsupported_dependencies\"));\n\t\t\t\t}\n\t\t\t\tconst identity = parsed.pluginId as string;\n\t\t\t\tconst packageValue = await options.registry.resolve({\n\t\t\t\t\tpluginId: identity,\n\t\t\t\t\tpluginVersion: parsed.pluginVersion,\n\t\t\t\t\tsignal,\n\t\t\t\t});\n\t\t\t\tcheckSignal(signal);\n\t\t\t\tif (!packageValue) return response(parsed.command, parsed.format, \"failed\", safeError(\"not_found\"));\n\t\t\t\tif (\n\t\t\t\t\tpackageValue.manifest.id !== identity ||\n\t\t\t\t\t(parsed.pluginVersion !== undefined && packageValue.manifest.pluginVersion !== parsed.pluginVersion)\n\t\t\t\t)\n\t\t\t\t\treturn response(parsed.command, parsed.format, \"failed\", safeError(\"not_found\"));\n\t\t\t\treturn await runInstallFlow({\n\t\t\t\t\tmanifest: packageValue.manifest,\n\t\t\t\t\tsource: packageValue.source,\n\t\t\t\t\t...(packageValue.expectedDigest === undefined ? {} : { expectedDigest: packageValue.expectedDigest }),\n\t\t\t\t\t...(packageValue.distribution === undefined ? {} : { distribution: packageValue.distribution }),\n\t\t\t\t});\n\t\t\t} catch (error) {\n\t\t\t\tif (isCancelled(signal) || (error instanceof Error && error.message === \"cancelled\"))\n\t\t\t\t\treturn response(parsed.command, parsed.format, \"cancelled\", safeError(\"cancelled\"));\n\t\t\t\tif (error instanceof Error && error.message === \"unsupported dependencies\")\n\t\t\t\t\treturn response(parsed.command, parsed.format, \"unsupported\", safeError(\"unsupported_dependencies\"));\n\t\t\t\treturn response(\n\t\t\t\t\tparsed.command,\n\t\t\t\t\tparsed.format,\n\t\t\t\t\t\"failed\",\n\t\t\t\t\tsafeError(\n\t\t\t\t\t\tphase === \"registry\"\n\t\t\t\t\t\t\t? \"registry_failed\"\n\t\t\t\t\t\t\t: phase === \"distribution\"\n\t\t\t\t\t\t\t\t? \"distribution_failed\"\n\t\t\t\t\t\t\t\t: phase === \"state\"\n\t\t\t\t\t\t\t\t\t? \"state_failed\"\n\t\t\t\t\t\t\t\t\t: phase === \"selection\"\n\t\t\t\t\t\t\t\t\t\t? \"selection_failed\"\n\t\t\t\t\t\t\t\t\t\t: \"installer_failed\",\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\t\t} finally {\n\t\t\treleaseInstallTransaction?.();\n\t\t}\n\t}\n\treturn { execute };\n}\n\nexport async function runPluginEcosystemCliV1(\n\toptions: PluginEcosystemCliOptionsV1,\n\tinput: PluginEcosystemCliRequestV1,\n): Promise<PluginEcosystemCliResponseV1> {\n\treturn await createPluginEcosystemCliV1(options).execute(input);\n}\n"]}
|
|
@@ -299,7 +299,10 @@ function formatText(command, status, data) {
|
|
|
299
299
|
: typeof item.lifecycle === "string"
|
|
300
300
|
? ` ${item.lifecycle}`
|
|
301
301
|
: "";
|
|
302
|
-
|
|
302
|
+
// A disabled record stays listed but the runtime will not load it — the
|
|
303
|
+
// suffix keeps the visibility readable without adding noise to enabled rows.
|
|
304
|
+
const visibility = item.enabled === false ? " disabled" : "";
|
|
305
|
+
return `${id}${version}${state}${visibility}`;
|
|
303
306
|
});
|
|
304
307
|
return [`${status}: ${command}`, ...lines, ...(data.truncated === true ? ["[output truncated]"] : [])].join("\n");
|
|
305
308
|
}
|
|
@@ -308,7 +311,8 @@ function formatText(command, status, data) {
|
|
|
308
311
|
const disabled = Array.isArray(data.disabledPluginIds) ? ` disabled=${data.disabledPluginIds.join(",")}` : "";
|
|
309
312
|
return `${status}: ${command} profile:${data.profileId}${selected}${disabled}`;
|
|
310
313
|
}
|
|
311
|
-
|
|
314
|
+
const note = typeof data.note === "string" ? ` ${data.note}` : "";
|
|
315
|
+
return `${status}: ${command}${note}`;
|
|
312
316
|
}
|
|
313
317
|
function safeError(code) {
|
|
314
318
|
const messages = {
|
|
@@ -644,11 +648,19 @@ export function createPluginEcosystemCliV1(options) {
|
|
|
644
648
|
return response(parsed.command, parsed.format, "cancelled", safeError("cancelled"));
|
|
645
649
|
if (updated.status !== "ok")
|
|
646
650
|
return response(parsed.command, parsed.format, "failed", safeError("state_failed"));
|
|
651
|
+
// Enabling a retained record only flips the flag; the runtime keeps
|
|
652
|
+
// skipping it. The response must say so instead of implying load.
|
|
653
|
+
const retainedNote = parsed.command === "enable" && record.state.lifecycle !== "active"
|
|
654
|
+
? t("only toggles the enabled flag; the record lifecycle is {lifecycle} and the runtime will not load it", {
|
|
655
|
+
lifecycle: record.state.lifecycle,
|
|
656
|
+
})
|
|
657
|
+
: undefined;
|
|
647
658
|
return response(parsed.command, parsed.format, "succeeded", undefined, {
|
|
648
659
|
pluginId: record.pluginId,
|
|
649
660
|
pluginVersion: record.pluginVersion,
|
|
650
661
|
enabled,
|
|
651
662
|
changed: updated.changed,
|
|
663
|
+
...(retainedNote === undefined ? {} : { note: retainedNote }),
|
|
652
664
|
});
|
|
653
665
|
}
|
|
654
666
|
// install/update must have every host boundary injected. They never claim success with partial services.
|