dsh-agent-plugins-market 0.9.0 → 0.9.2
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/README.md +64 -154
- package/README.zh.md +74 -164
- package/assets/dsh-agent-plugins.png +0 -0
- package/client/client.js +5371 -1085
- package/client/client.js.map +1 -1
- package/lib/index.js +2 -257
- package/lib/{application → packages/market-bundle/src/application}/catalog.js +207 -41
- package/lib/{application → packages/market-bundle/src/application}/details.js +73 -29
- package/lib/packages/market-bundle/src/application/extension-inventory.js +408 -0
- package/lib/packages/market-bundle/src/application/extension-project.js +64 -0
- package/lib/packages/market-bundle/src/application/resource-inventory.js +96 -0
- package/lib/packages/market-bundle/src/application/server-config.js +9 -0
- package/lib/packages/market-bundle/src/application/suite-queries.js +86 -0
- package/lib/packages/market-bundle/src/index.js +372 -0
- package/lib/{runtime/host → packages/market-bundle/src/platform}/feedback-tool.js +2 -2
- package/lib/{runtime/host → packages/market-bundle/src/platform}/settings-namespace.js +55 -7
- package/lib/packages/market-bundle/src/platform/settings-schema.js +25 -0
- package/lib/packages/market-bundle/src/routes-extension-presets.js +161 -0
- package/lib/packages/market-bundle/src/routes-resources.js +127 -0
- package/lib/{routes.js → packages/market-bundle/src/routes.js} +225 -21
- package/lib/packages/market-bundle/src/runtime-adapters.js +57 -0
- package/lib/packages/market-bundle/src/session-extension.js +337 -0
- package/lib/{application → packages/market-catalog/src/application}/catalog-context.js +7 -4
- package/lib/{application → packages/market-catalog/src/application}/install-store.js +3 -3
- package/lib/{application → packages/market-catalog/src/application}/snapshot-cache.js +100 -11
- package/lib/{application → packages/market-catalog/src/application}/source-store.js +24 -11
- package/lib/{application → packages/market-catalog/src/application}/state/state-store.js +1 -1
- package/lib/{application → packages/market-catalog/src/application}/state/storage-migration.js +1 -1
- package/lib/packages/market-catalog/src/index.js +19 -0
- package/lib/{catalog → packages/market-catalog/src/scanning}/archive.js +1 -1
- package/lib/{catalog → packages/market-catalog/src/scanning}/codex-mcp.js +1 -1
- package/lib/{catalog → packages/market-catalog/src/scanning}/component-files.js +2 -2
- package/lib/{catalog → packages/market-catalog/src/scanning}/manifests.js +2 -2
- package/lib/{catalog → packages/market-catalog/src/scanning}/native-project.js +1 -1
- package/lib/{catalog → packages/market-catalog/src/scanning}/paths.js +1 -1
- package/lib/{catalog → packages/market-catalog/src/scanning}/plugin-variables.js +21 -1
- package/lib/{catalog → packages/market-catalog/src/scanning}/scan-resolvers.js +35 -2
- package/lib/{catalog → packages/market-catalog/src/scanning}/skills-parse.js +40 -10
- package/lib/{catalog → packages/market-catalog/src/scanning}/validate.js +15 -2
- package/lib/packages/market-contracts/src/contracts/extension-presets.js +125 -0
- package/lib/{contracts → packages/market-contracts/src/contracts}/market.js +33 -5
- package/lib/packages/market-contracts/src/contracts/mcp-overrides.js +2 -0
- package/lib/packages/market-contracts/src/contracts/resource-window.js +29 -0
- package/lib/packages/market-contracts/src/contracts/settings.js +130 -0
- package/lib/packages/market-contracts/src/contracts/surface-toggles.js +29 -0
- package/lib/packages/market-contracts/src/contracts/translation.js +28 -0
- package/lib/packages/market-contracts/src/index.js +4 -0
- package/lib/{model → packages/market-contracts/src/model}/layouts.js +11 -0
- package/lib/{application → packages/market-contracts/src/ports}/ports.js +3 -0
- package/lib/{application/mcp/mcp-redaction.js → packages/market-contracts/src/redaction.js} +17 -1
- package/lib/{application → packages/market-lsp/src/application}/lsp/lsp-direct-config.js +2 -2
- package/lib/{application → packages/market-lsp/src/application}/lsp/lsp-server-state.js +1 -1
- package/lib/{application → packages/market-lsp/src/application}/lsp/lsp-status.js +20 -3
- package/lib/{application → packages/market-lsp/src/application}/lsp/profile-seam.js +1 -1
- package/lib/packages/market-lsp/src/application/lsp/validation.js +46 -0
- package/lib/{application → packages/market-lsp/src/application}/lsp-service.js +61 -3
- package/lib/packages/market-lsp/src/index.js +8 -0
- package/lib/{runtime → packages/market-lsp/src/runtime}/lsp/lsp-mounts.js +79 -40
- package/lib/{application → packages/market-mcp/src/application}/mcp/mcp-backend.js +0 -16
- package/lib/{application → packages/market-mcp/src/application}/mcp/mcp-config.js +104 -21
- package/lib/{application → packages/market-mcp/src/application}/mcp/mcp-direct-config.js +12 -4
- package/lib/{application → packages/market-mcp/src/application}/mcp/mcp-overrides.js +4 -4
- package/lib/{application → packages/market-mcp/src/application}/mcp/mcp-status.js +49 -10
- package/lib/packages/market-mcp/src/application/mcp/validation.js +63 -0
- package/lib/{application → packages/market-mcp/src/application}/mcp-service.js +111 -91
- package/lib/packages/market-mcp/src/index.js +10 -0
- package/lib/{runtime → packages/market-mcp/src/runtime}/mcp/bridge/bridge.js +12 -9
- package/lib/{runtime → packages/market-mcp/src/runtime}/mcp/bridge/connection.js +1 -1
- package/lib/{runtime → packages/market-mcp/src/runtime}/mcp/bridge/oauth.js +1 -1
- package/lib/packages/market-mcp/src/runtime/mcp/bridge/tool-ownership.js +26 -0
- package/lib/{runtime → packages/market-mcp/src/runtime}/mcp/bridge/tools.js +1 -1
- package/lib/{runtime → packages/market-mcp/src/runtime}/mcp/mcp-auth-record.js +35 -4
- package/lib/{runtime → packages/market-mcp/src/runtime}/mcp/mcp-mounts.js +35 -4
- package/lib/packages/market-runtime/src/adapter-contracts.js +1 -0
- package/lib/packages/market-runtime/src/application/command-resources.js +74 -0
- package/lib/packages/market-runtime/src/application/extension-authorization.js +27 -0
- package/lib/packages/market-runtime/src/application/extension-hook-selection.js +56 -0
- package/lib/packages/market-runtime/src/application/extension-suite-declarations.js +57 -0
- package/lib/packages/market-runtime/src/application/extension-suite-selection.js +84 -0
- package/lib/packages/market-runtime/src/application/fs-probe.js +43 -0
- package/lib/packages/market-runtime/src/application/panel-resources.js +370 -0
- package/lib/{application → packages/market-runtime/src/application}/panels/user-hooks.js +2 -2
- package/lib/{application → packages/market-runtime/src/application}/panels/user-store.js +53 -13
- package/lib/{application → packages/market-runtime/src/application}/project-agent-roles.js +20 -11
- package/lib/packages/market-runtime/src/application/state/extension-presets.js +144 -0
- package/lib/packages/market-runtime/src/application/state/resource-favorites.js +90 -0
- package/lib/packages/market-runtime/src/application/state/resource-filters.js +2 -0
- package/lib/packages/market-runtime/src/application/state/surface-toggles.js +10 -0
- package/lib/packages/market-runtime/src/application/state/workspace-policy.js +56 -0
- package/lib/packages/market-runtime/src/catalog-port.js +1 -0
- package/lib/packages/market-runtime/src/extension-service.js +1 -0
- package/lib/packages/market-runtime/src/index.js +31 -0
- package/lib/{runtime → packages/market-runtime/src/runtime}/agents/agent-role-router.js +74 -79
- package/lib/packages/market-runtime/src/runtime/agents/agent-teams-seat.js +58 -0
- package/lib/{runtime → packages/market-runtime/src/runtime}/agents/subagent-catalog.js +89 -21
- package/lib/packages/market-runtime/src/runtime/agents/team-coordination.js +51 -0
- package/lib/packages/market-runtime/src/runtime/agents/teammate-role-runtime.js +241 -0
- package/lib/packages/market-runtime/src/runtime/agents/teammate-role-tool.js +130 -0
- package/lib/{runtime → packages/market-runtime/src/runtime}/core/reconcile-scheduler.js +2 -2
- package/lib/packages/market-runtime/src/runtime/core/reconciler.js +457 -0
- package/lib/packages/market-runtime/src/runtime/host/command-name-allocator.js +168 -0
- package/lib/packages/market-runtime/src/runtime/host/extension-progress.js +120 -0
- package/lib/packages/market-runtime/src/runtime/host/extension-runtime.js +405 -0
- package/lib/packages/market-runtime/src/runtime/host/extension-session-state.js +839 -0
- package/lib/packages/market-runtime/src/runtime/host/extension-tool-gates.js +96 -0
- package/lib/{runtime → packages/market-runtime/src/runtime}/host/failure-detail.js +1 -1
- package/lib/{runtime → packages/market-runtime/src/runtime}/host/host-locale.js +2 -0
- package/lib/packages/market-runtime/src/runtime/host/menu-row-identities.js +38 -0
- package/lib/packages/market-runtime/src/runtime/host/resource-filter-service.js +81 -0
- package/lib/packages/market-runtime/src/runtime/host/scoped-contributors.js +304 -0
- package/lib/packages/market-runtime/src/runtime/host/surface-toggle-service.js +15 -0
- package/lib/packages/market-runtime/src/runtime/panels/user-commands.js +211 -0
- package/lib/{runtime → packages/market-runtime/src/runtime}/panels/user-panels.js +34 -14
- package/lib/packages/market-runtime/src/runtime/surfaces/commands-mounts.js +256 -0
- package/lib/packages/market-runtime/src/runtime/surfaces/extension-hooks.js +294 -0
- package/lib/packages/market-runtime/src/runtime/surfaces/hook-dry-run.js +122 -0
- package/lib/{runtime → packages/market-runtime/src/runtime}/surfaces/hooks-mounts.js +1 -1
- package/lib/{runtime → packages/market-runtime/src/runtime}/surfaces/project-runtime.js +23 -13
- package/lib/packages/market-runtime/src/runtime/surfaces/skills-provider.js +241 -0
- package/lib/packages/market-translation/src/application/state/translation-cache.js +122 -0
- package/lib/packages/market-translation/src/application/translation/chain.js +99 -0
- package/lib/packages/market-translation/src/application/translation/document.js +384 -0
- package/lib/packages/market-translation/src/application/translation/localizer.js +642 -0
- package/lib/packages/market-translation/src/application/translation/service.js +113 -0
- package/lib/packages/market-translation/src/application/translation/unit.js +19 -0
- package/lib/packages/market-translation/src/index.js +4 -0
- package/lib/packages/market-translation/src/runtime/host/llm-translator.js +278 -0
- package/lib/packages/market-translation/src/runtime/host/machine-translator.js +152 -0
- package/lib/packages/market-translation/src/runtime/host/text-masking.js +96 -0
- package/lib/packages/market-translation/src/runtime/host/translation-providers.js +116 -0
- package/lib/types/index.d.ts +2 -130
- package/lib/types/{application → packages/market-bundle/src/application}/catalog.d.ts +117 -22
- package/lib/types/packages/market-bundle/src/application/details.d.ts +24 -0
- package/lib/types/packages/market-bundle/src/application/extension-inventory.d.ts +45 -0
- package/lib/types/packages/market-bundle/src/application/extension-project.d.ts +26 -0
- package/lib/types/packages/market-bundle/src/application/resource-inventory.d.ts +42 -0
- package/lib/types/packages/market-bundle/src/application/server-config.d.ts +9 -0
- package/lib/types/packages/market-bundle/src/application/suite-queries.d.ts +84 -0
- package/lib/types/packages/market-bundle/src/index.d.ts +125 -0
- package/lib/types/{runtime/host → packages/market-bundle/src/platform}/settings-namespace.d.ts +44 -9
- package/lib/types/{application/mcp/mcp-backend.d.ts → packages/market-bundle/src/platform/settings-schema.d.ts} +13 -28
- package/lib/types/packages/market-bundle/src/routes-extension-presets.d.ts +15 -0
- package/lib/types/packages/market-bundle/src/routes-resources.d.ts +17 -0
- package/lib/types/packages/market-bundle/src/routes.d.ts +32 -0
- package/lib/types/packages/market-bundle/src/runtime-adapters.d.ts +42 -0
- package/lib/types/packages/market-bundle/src/session-extension.d.ts +62 -0
- package/lib/types/{application → packages/market-catalog/src/application}/catalog-context.d.ts +11 -3
- package/lib/types/{application → packages/market-catalog/src/application}/install-store.d.ts +1 -1
- package/lib/types/{application → packages/market-catalog/src/application}/regions.d.ts +1 -1
- package/lib/types/{application → packages/market-catalog/src/application}/snapshot-cache.d.ts +44 -2
- package/lib/types/{application → packages/market-catalog/src/application}/source-store.d.ts +12 -3
- package/lib/types/{application → packages/market-catalog/src/application}/state/state-store.d.ts +1 -1
- package/lib/types/packages/market-catalog/src/index.d.ts +22 -0
- package/lib/types/{catalog → packages/market-catalog/src/scanning}/archive.d.ts +1 -1
- package/lib/types/{catalog → packages/market-catalog/src/scanning}/codex-mcp.d.ts +1 -1
- package/lib/types/{catalog → packages/market-catalog/src/scanning}/component-files.d.ts +1 -1
- package/lib/types/{catalog → packages/market-catalog/src/scanning}/lsp-spec.d.ts +1 -1
- package/lib/types/{catalog → packages/market-catalog/src/scanning}/manifests.d.ts +3 -3
- package/lib/types/{catalog → packages/market-catalog/src/scanning}/native-project.d.ts +2 -2
- package/lib/types/{catalog → packages/market-catalog/src/scanning}/plugin-variables.d.ts +12 -1
- package/lib/types/{catalog → packages/market-catalog/src/scanning}/project-config.d.ts +2 -2
- package/lib/types/{catalog → packages/market-catalog/src/scanning}/project-hooks.d.ts +2 -2
- package/lib/types/{catalog → packages/market-catalog/src/scanning}/scan-pipeline.d.ts +1 -1
- package/lib/types/{catalog → packages/market-catalog/src/scanning}/scan-resolvers.d.ts +3 -3
- package/lib/types/{catalog → packages/market-catalog/src/scanning}/source-catalog.d.ts +1 -1
- package/lib/types/{catalog → packages/market-catalog/src/scanning}/suite-components.d.ts +1 -1
- package/lib/types/{catalog → packages/market-catalog/src/scanning}/suite-scanner.d.ts +1 -1
- package/lib/types/{catalog → packages/market-catalog/src/scanning}/surfaces.d.ts +1 -1
- package/lib/types/{catalog → packages/market-catalog/src/scanning}/validate.d.ts +1 -1
- package/lib/types/packages/market-contracts/src/contracts/extension-presets.d.ts +237 -0
- package/lib/types/{contracts → packages/market-contracts/src/contracts}/market.d.ts +87 -16
- package/lib/types/packages/market-contracts/src/contracts/mcp-overrides.d.ts +39 -0
- package/lib/types/{contracts → packages/market-contracts/src/contracts}/mcp-status.d.ts +9 -0
- package/lib/types/packages/market-contracts/src/contracts/resource-window.d.ts +70 -0
- package/lib/types/packages/market-contracts/src/contracts/settings.d.ts +121 -0
- package/lib/types/packages/market-contracts/src/contracts/surface-toggles.d.ts +28 -0
- package/lib/types/packages/market-contracts/src/contracts/translation.d.ts +81 -0
- package/lib/types/{runtime → packages/market-contracts/src}/host/plugin-message-source.d.ts +1 -1
- package/lib/types/packages/market-contracts/src/index.d.ts +5 -0
- package/lib/types/{model → packages/market-contracts/src/model}/layouts.d.ts +7 -0
- package/lib/types/{model → packages/market-contracts/src/model}/types.d.ts +2 -2
- package/lib/types/packages/market-contracts/src/ports/ports.d.ts +183 -0
- package/lib/types/{application → packages/market-contracts/src/ports}/queries.d.ts +27 -6
- package/lib/types/{application/mcp/mcp-redaction.d.ts → packages/market-contracts/src/redaction.d.ts} +2 -0
- package/lib/types/{application → packages/market-lsp/src/application}/lsp/lsp-direct-config.d.ts +1 -1
- package/lib/types/{application → packages/market-lsp/src/application}/lsp/lsp-status.d.ts +21 -5
- package/lib/types/packages/market-lsp/src/application/lsp/validation.d.ts +8 -0
- package/lib/types/{application → packages/market-lsp/src/application}/lsp-service.d.ts +19 -6
- package/lib/types/packages/market-lsp/src/index.d.ts +8 -0
- package/lib/types/{runtime → packages/market-lsp/src/runtime}/lsp/lsp-mounts.d.ts +26 -6
- package/lib/types/packages/market-mcp/src/application/mcp/mcp-backend.d.ts +28 -0
- package/lib/types/{application → packages/market-mcp/src/application}/mcp/mcp-bridge-config.d.ts +1 -1
- package/lib/types/{application → packages/market-mcp/src/application}/mcp/mcp-config.d.ts +2 -2
- package/lib/types/{application → packages/market-mcp/src/application}/mcp/mcp-direct-config.d.ts +6 -1
- package/lib/types/{application → packages/market-mcp/src/application}/mcp/mcp-overrides.d.ts +4 -38
- package/lib/types/packages/market-mcp/src/application/mcp/mcp-status.d.ts +40 -0
- package/lib/types/{application/server-config.d.ts → packages/market-mcp/src/application/mcp/validation.d.ts} +2 -10
- package/lib/types/{application → packages/market-mcp/src/application}/mcp-service.d.ts +22 -16
- package/lib/types/packages/market-mcp/src/index.d.ts +12 -0
- package/lib/types/packages/market-mcp/src/runtime/mcp/bridge/tool-ownership.d.ts +14 -0
- package/lib/types/{runtime → packages/market-mcp/src/runtime}/mcp/mcp-auth-record.d.ts +4 -0
- package/lib/types/{runtime → packages/market-mcp/src/runtime}/mcp/mcp-mounts.d.ts +19 -3
- package/lib/types/packages/market-runtime/src/adapter-contracts.d.ts +89 -0
- package/lib/types/{application → packages/market-runtime/src/application}/agent-roles.d.ts +2 -0
- package/lib/types/packages/market-runtime/src/application/command-resources.d.ts +26 -0
- package/lib/types/packages/market-runtime/src/application/extension-authorization.d.ts +12 -0
- package/lib/types/packages/market-runtime/src/application/extension-hook-selection.d.ts +23 -0
- package/lib/types/packages/market-runtime/src/application/extension-suite-declarations.d.ts +10 -0
- package/lib/types/packages/market-runtime/src/application/extension-suite-selection.d.ts +30 -0
- package/lib/types/packages/market-runtime/src/application/fs-probe.d.ts +12 -0
- package/lib/types/packages/market-runtime/src/application/panel-resources.d.ts +100 -0
- package/lib/types/{application → packages/market-runtime/src/application}/panels/user-hooks.d.ts +1 -1
- package/lib/types/packages/market-runtime/src/application/project-agent-roles.d.ts +10 -0
- package/lib/types/packages/market-runtime/src/application/state/extension-presets.d.ts +24 -0
- package/lib/types/packages/market-runtime/src/application/state/resource-favorites.d.ts +9 -0
- package/lib/types/packages/market-runtime/src/application/state/resource-filters.d.ts +2 -0
- package/lib/types/packages/market-runtime/src/application/state/surface-toggles.d.ts +6 -0
- package/lib/types/packages/market-runtime/src/application/state/workspace-policy.d.ts +19 -0
- package/lib/types/packages/market-runtime/src/catalog-port.d.ts +30 -0
- package/lib/types/packages/market-runtime/src/extension-service.d.ts +14 -0
- package/lib/types/packages/market-runtime/src/index.d.ts +41 -0
- package/lib/types/{runtime → packages/market-runtime/src/runtime}/agents/agent-role-router.d.ts +66 -31
- package/lib/types/packages/market-runtime/src/runtime/agents/agent-teams-seat.d.ts +41 -0
- package/lib/types/{runtime → packages/market-runtime/src/runtime}/agents/subagent-catalog.d.ts +34 -2
- package/lib/types/packages/market-runtime/src/runtime/agents/team-coordination.d.ts +8 -0
- package/lib/types/packages/market-runtime/src/runtime/agents/teammate-role-runtime.d.ts +74 -0
- package/lib/types/packages/market-runtime/src/runtime/agents/teammate-role-tool.d.ts +6 -0
- package/lib/types/{runtime → packages/market-runtime/src/runtime}/core/reconcile-scheduler.d.ts +5 -2
- package/lib/types/packages/market-runtime/src/runtime/core/reconciler.d.ts +141 -0
- package/lib/types/packages/market-runtime/src/runtime/host/command-name-allocator.d.ts +132 -0
- package/lib/types/packages/market-runtime/src/runtime/host/extension-progress.d.ts +91 -0
- package/lib/types/packages/market-runtime/src/runtime/host/extension-runtime.d.ts +77 -0
- package/lib/types/packages/market-runtime/src/runtime/host/extension-session-state.d.ts +242 -0
- package/lib/types/packages/market-runtime/src/runtime/host/extension-tool-gates.d.ts +38 -0
- package/lib/types/{runtime → packages/market-runtime/src/runtime}/host/host-locale.d.ts +1 -1
- package/lib/types/packages/market-runtime/src/runtime/host/menu-row-identities.d.ts +50 -0
- package/lib/types/{runtime → packages/market-runtime/src/runtime}/host/model-catalog.d.ts +1 -1
- package/lib/types/packages/market-runtime/src/runtime/host/resource-filter-service.d.ts +34 -0
- package/lib/types/packages/market-runtime/src/runtime/host/scoped-contributors.d.ts +58 -0
- package/lib/types/packages/market-runtime/src/runtime/host/surface-toggle-service.d.ts +10 -0
- package/lib/types/packages/market-runtime/src/runtime/panels/user-commands.d.ts +74 -0
- package/lib/types/{runtime → packages/market-runtime/src/runtime}/panels/user-panels.d.ts +7 -1
- package/lib/types/packages/market-runtime/src/runtime/surfaces/commands-mounts.d.ts +81 -0
- package/lib/types/packages/market-runtime/src/runtime/surfaces/extension-hooks.d.ts +59 -0
- package/lib/types/packages/market-runtime/src/runtime/surfaces/hook-dry-run.d.ts +91 -0
- package/lib/types/{runtime → packages/market-runtime/src/runtime}/surfaces/hooks-mounts.d.ts +1 -1
- package/lib/types/{runtime → packages/market-runtime/src/runtime}/surfaces/project-runtime.d.ts +8 -5
- package/lib/types/packages/market-runtime/src/runtime/surfaces/skills-provider.d.ts +71 -0
- package/lib/types/packages/market-translation/src/application/state/translation-cache.d.ts +56 -0
- package/lib/types/packages/market-translation/src/application/translation/chain.d.ts +47 -0
- package/lib/types/packages/market-translation/src/application/translation/document.d.ts +54 -0
- package/lib/types/packages/market-translation/src/application/translation/localizer.d.ts +325 -0
- package/lib/types/packages/market-translation/src/application/translation/service.d.ts +89 -0
- package/lib/types/packages/market-translation/src/application/translation/unit.d.ts +35 -0
- package/lib/types/packages/market-translation/src/index.d.ts +4 -0
- package/lib/types/packages/market-translation/src/runtime/host/llm-translator.d.ts +30 -0
- package/lib/types/packages/market-translation/src/runtime/host/machine-translator.d.ts +52 -0
- package/lib/types/packages/market-translation/src/runtime/host/text-masking.d.ts +42 -0
- package/lib/types/packages/market-translation/src/runtime/host/translation-providers.d.ts +42 -0
- package/locale/en.json +6 -0
- package/locale/zh.json +6 -0
- package/package.json +47 -10
- package/schemas/README.md +4 -4
- package/schemas/agent-plugins/spec.md +2 -2
- package/schemas/com.deepseek.harness/spec.md +1 -1
- package/schemas/skill-collection/spec.md +10 -2
- package/lib/application/panel-resources.js +0 -161
- package/lib/application/server-config.js +0 -109
- package/lib/contracts/settings.js +0 -63
- package/lib/runtime/core/reconciler.js +0 -100
- package/lib/runtime/panels/user-commands.js +0 -105
- package/lib/runtime/surfaces/commands-mounts.js +0 -186
- package/lib/runtime/surfaces/skills-provider.js +0 -160
- package/lib/types/application/details.d.ts +0 -7
- package/lib/types/application/mcp/mcp-status.d.ts +0 -24
- package/lib/types/application/panel-resources.d.ts +0 -28
- package/lib/types/application/ports.d.ts +0 -86
- package/lib/types/application/project-agent-roles.d.ts +0 -3
- package/lib/types/contracts/settings.d.ts +0 -59
- package/lib/types/routes.d.ts +0 -16
- package/lib/types/runtime/core/reconciler.d.ts +0 -58
- package/lib/types/runtime/panels/user-commands.d.ts +0 -27
- package/lib/types/runtime/surfaces/commands-mounts.d.ts +0 -48
- package/lib/types/runtime/surfaces/skills-provider.d.ts +0 -23
- /package/lib/{application → packages/market-catalog/src/application}/deadline.js +0 -0
- /package/lib/{application → packages/market-catalog/src/application}/json-file.js +0 -0
- /package/lib/{application → packages/market-catalog/src/application}/regions.js +0 -0
- /package/lib/{catalog → packages/market-catalog/src/scanning}/fs-probes.js +0 -0
- /package/lib/{catalog → packages/market-catalog/src/scanning}/git.js +0 -0
- /package/lib/{catalog → packages/market-catalog/src/scanning}/lsp-spec.js +0 -0
- /package/lib/{catalog → packages/market-catalog/src/scanning}/project-config.js +0 -0
- /package/lib/{catalog → packages/market-catalog/src/scanning}/project-hooks.js +0 -0
- /package/lib/{catalog → packages/market-catalog/src/scanning}/scan-pipeline.js +0 -0
- /package/lib/{catalog → packages/market-catalog/src/scanning}/source-catalog.js +0 -0
- /package/lib/{catalog → packages/market-catalog/src/scanning}/suite-components.js +0 -0
- /package/lib/{catalog → packages/market-catalog/src/scanning}/suite-scanner.js +0 -0
- /package/lib/{catalog → packages/market-catalog/src/scanning}/surfaces.js +0 -0
- /package/lib/{contracts → packages/market-contracts/src/contracts}/lsp-status.js +0 -0
- /package/lib/{contracts → packages/market-contracts/src/contracts}/lsp.js +0 -0
- /package/lib/{contracts → packages/market-contracts/src/contracts}/mcp-status.js +0 -0
- /package/lib/{contracts → packages/market-contracts/src/contracts}/mcp.js +0 -0
- /package/lib/{runtime → packages/market-contracts/src}/host/plugin-message-source.js +0 -0
- /package/lib/{model → packages/market-contracts/src/model}/command-names.js +0 -0
- /package/lib/{model → packages/market-contracts/src/model}/preset-source.js +0 -0
- /package/lib/{model → packages/market-contracts/src/model}/types.js +0 -0
- /package/lib/{application → packages/market-contracts/src/ports}/queries.js +0 -0
- /package/lib/{application → packages/market-mcp/src/application}/mcp/mcp-bridge-config.js +0 -0
- /package/lib/{runtime → packages/market-mcp/src/runtime}/mcp/bridge/host-contract.js +0 -0
- /package/lib/{runtime → packages/market-mcp/src/runtime}/mcp/bridge/host-seams.js +0 -0
- /package/lib/{runtime → packages/market-mcp/src/runtime}/mcp/bridge/plugin-identity.js +0 -0
- /package/lib/{runtime → packages/market-mcp/src/runtime}/mcp/bridge/projection.js +0 -0
- /package/lib/{runtime → packages/market-mcp/src/runtime}/mcp/bridge/transport.js +0 -0
- /package/lib/{runtime → packages/market-mcp/src/runtime}/mcp/mcp-credentials.js +0 -0
- /package/lib/{application → packages/market-runtime/src/application}/agent-roles.js +0 -0
- /package/lib/{runtime → packages/market-runtime/src/runtime}/agents/agent-role-names.js +0 -0
- /package/lib/{runtime → packages/market-runtime/src/runtime}/core/context.js +0 -0
- /package/lib/{runtime → packages/market-runtime/src/runtime}/core/mount-lifecycle.js +0 -0
- /package/lib/{runtime → packages/market-runtime/src/runtime}/core/source-auto-update.js +0 -0
- /package/lib/{runtime → packages/market-runtime/src/runtime}/core/timer-seat.js +0 -0
- /package/lib/{runtime → packages/market-runtime/src/runtime}/host/model-catalog.js +0 -0
- /package/lib/{runtime → packages/market-runtime/src/runtime}/host/shell-path.js +0 -0
- /package/lib/{runtime → packages/market-runtime/src/runtime}/host/tool-registry-observer.js +0 -0
- /package/lib/{runtime → packages/market-runtime/src/runtime}/surfaces/dynamic-context.js +0 -0
- /package/lib/types/{runtime/host → packages/market-bundle/src/platform}/feedback-tool.d.ts +0 -0
- /package/lib/types/{application → packages/market-catalog/src/application}/deadline.d.ts +0 -0
- /package/lib/types/{application → packages/market-catalog/src/application}/json-file.d.ts +0 -0
- /package/lib/types/{application → packages/market-catalog/src/application}/state/storage-migration.d.ts +0 -0
- /package/lib/types/{catalog → packages/market-catalog/src/scanning}/fs-probes.d.ts +0 -0
- /package/lib/types/{catalog → packages/market-catalog/src/scanning}/git.d.ts +0 -0
- /package/lib/types/{catalog → packages/market-catalog/src/scanning}/paths.d.ts +0 -0
- /package/lib/types/{catalog → packages/market-catalog/src/scanning}/skills-parse.d.ts +0 -0
- /package/lib/types/{contracts → packages/market-contracts/src/contracts}/lsp-status.d.ts +0 -0
- /package/lib/types/{contracts → packages/market-contracts/src/contracts}/lsp.d.ts +0 -0
- /package/lib/types/{contracts → packages/market-contracts/src/contracts}/mcp.d.ts +0 -0
- /package/lib/types/{model → packages/market-contracts/src/model}/command-names.d.ts +0 -0
- /package/lib/types/{model → packages/market-contracts/src/model}/preset-source.d.ts +0 -0
- /package/lib/types/{application → packages/market-lsp/src/application}/lsp/lsp-server-state.d.ts +0 -0
- /package/lib/types/{application → packages/market-lsp/src/application}/lsp/profile-seam.d.ts +0 -0
- /package/lib/types/{runtime → packages/market-mcp/src/runtime}/mcp/bridge/bridge.d.ts +0 -0
- /package/lib/types/{runtime → packages/market-mcp/src/runtime}/mcp/bridge/connection.d.ts +0 -0
- /package/lib/types/{runtime → packages/market-mcp/src/runtime}/mcp/bridge/host-contract.d.ts +0 -0
- /package/lib/types/{runtime → packages/market-mcp/src/runtime}/mcp/bridge/host-seams.d.ts +0 -0
- /package/lib/types/{runtime → packages/market-mcp/src/runtime}/mcp/bridge/oauth.d.ts +0 -0
- /package/lib/types/{runtime → packages/market-mcp/src/runtime}/mcp/bridge/plugin-identity.d.ts +0 -0
- /package/lib/types/{runtime → packages/market-mcp/src/runtime}/mcp/bridge/projection.d.ts +0 -0
- /package/lib/types/{runtime → packages/market-mcp/src/runtime}/mcp/bridge/tools.d.ts +0 -0
- /package/lib/types/{runtime → packages/market-mcp/src/runtime}/mcp/bridge/transport.d.ts +0 -0
- /package/lib/types/{runtime → packages/market-mcp/src/runtime}/mcp/mcp-credentials.d.ts +0 -0
- /package/lib/types/{application → packages/market-runtime/src/application}/panels/user-store.d.ts +0 -0
- /package/lib/types/{runtime → packages/market-runtime/src/runtime}/agents/agent-role-names.d.ts +0 -0
- /package/lib/types/{runtime → packages/market-runtime/src/runtime}/core/context.d.ts +0 -0
- /package/lib/types/{runtime → packages/market-runtime/src/runtime}/core/mount-lifecycle.d.ts +0 -0
- /package/lib/types/{runtime → packages/market-runtime/src/runtime}/core/source-auto-update.d.ts +0 -0
- /package/lib/types/{runtime → packages/market-runtime/src/runtime}/core/timer-seat.d.ts +0 -0
- /package/lib/types/{runtime → packages/market-runtime/src/runtime}/host/failure-detail.d.ts +0 -0
- /package/lib/types/{runtime → packages/market-runtime/src/runtime}/host/shell-path.d.ts +0 -0
- /package/lib/types/{runtime → packages/market-runtime/src/runtime}/host/tool-registry-observer.d.ts +0 -0
- /package/lib/types/{runtime → packages/market-runtime/src/runtime}/surfaces/dynamic-context.d.ts +0 -0
|
@@ -0,0 +1,457 @@
|
|
|
1
|
+
import { isDeepStrictEqual } from 'node:util';
|
|
2
|
+
import { CommandMountRegistry } from '../surfaces/commands-mounts.js';
|
|
3
|
+
import { HooksMountRegistry } from '../surfaces/hooks-mounts.js';
|
|
4
|
+
import { projectExtensionSuites } from '../../application/extension-suite-selection.js';
|
|
5
|
+
import { captureExtensionSelection } from '../../../../market-contracts/src/contracts/extension-presets.js';
|
|
6
|
+
import { bindHostLocale } from '../host/host-locale.js';
|
|
7
|
+
export class RuntimeReconciler {
|
|
8
|
+
mcp;
|
|
9
|
+
commands;
|
|
10
|
+
hooks;
|
|
11
|
+
lspRegistry;
|
|
12
|
+
queues = new Map();
|
|
13
|
+
gates;
|
|
14
|
+
disposed = false;
|
|
15
|
+
agentScopedContributors = false;
|
|
16
|
+
authority;
|
|
17
|
+
authorityEpoch = 0;
|
|
18
|
+
globalSuites = [];
|
|
19
|
+
committed = new Map();
|
|
20
|
+
staged = new Map();
|
|
21
|
+
sharedQueue = Promise.resolve();
|
|
22
|
+
demandedMcp = new Map();
|
|
23
|
+
demandedLsp = new Set();
|
|
24
|
+
overridesProvider = async () => new Map();
|
|
25
|
+
disposal;
|
|
26
|
+
warn;
|
|
27
|
+
/**
|
|
28
|
+
* @param ctx - the context every mount registers through.
|
|
29
|
+
* @param dataRoot - the plugin data root the mount adapters store under.
|
|
30
|
+
* @param mounts - the transport adapters this coordinator drives. The
|
|
31
|
+
* composition root builds them, so no transport package is imported here.
|
|
32
|
+
* @param t - host translator for the command registry's own diagnostics.
|
|
33
|
+
*/
|
|
34
|
+
constructor(ctx, dataRoot, mounts, t = bindHostLocale(undefined)) {
|
|
35
|
+
this.mcp = mounts.mcp;
|
|
36
|
+
this.commands = new CommandMountRegistry(ctx, t, dataRoot);
|
|
37
|
+
this.hooks = new HooksMountRegistry(ctx);
|
|
38
|
+
this.lspRegistry = mounts.lsp;
|
|
39
|
+
this.lspRegistry.setPluginDataRoot(dataRoot);
|
|
40
|
+
this.lspRegistry.setDemandedProviderIdsProvider(() => this.demandedLsp);
|
|
41
|
+
this.warn = message => ctx.logger?.warn(message);
|
|
42
|
+
this.mcp.setOverridesProvider(async () => {
|
|
43
|
+
const overrides = new Map(await this.overridesProvider());
|
|
44
|
+
for (const [suiteId, keys] of this.demandedMcp) {
|
|
45
|
+
const rows = { ...overrides.get(suiteId) };
|
|
46
|
+
for (const key of keys)
|
|
47
|
+
rows[key] = { ...rows[key], enabled: true };
|
|
48
|
+
overrides.set(suiteId, rows);
|
|
49
|
+
}
|
|
50
|
+
return overrides;
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
/** Transfer commands and hooks to per-agent registries; call before the first reconcile. */
|
|
54
|
+
setAgentScopedContributors() {
|
|
55
|
+
this.agentScopedContributors = true;
|
|
56
|
+
}
|
|
57
|
+
/** Exact live MCP definitions and their owning extension resources. */
|
|
58
|
+
mcpToolOwnership() {
|
|
59
|
+
return this.mcp.toolOwnership();
|
|
60
|
+
}
|
|
61
|
+
/** The LSP mount registry, consumed by the LSP status surface. */
|
|
62
|
+
get lsp() {
|
|
63
|
+
return this.lspRegistry;
|
|
64
|
+
}
|
|
65
|
+
/** The suite commands the global layer currently holds, for the slash menu's row faces. */
|
|
66
|
+
commandRegistrations() {
|
|
67
|
+
return this.commands.registrations();
|
|
68
|
+
}
|
|
69
|
+
/** Install the per-workspace entry filter on the MCP mount registry. */
|
|
70
|
+
setMcpEntryFilter(filter) {
|
|
71
|
+
this.mcp.setEntryFilter(filter);
|
|
72
|
+
}
|
|
73
|
+
/** Install the per-workspace entry filter on the command mount registry. */
|
|
74
|
+
setCommandsEntryFilter(filter) {
|
|
75
|
+
this.commands.setEntryFilter(filter);
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Install the per-workspace surface gates, read on every pass.
|
|
79
|
+
*
|
|
80
|
+
* Set after construction because the toggle service is built later in
|
|
81
|
+
* composition; until then every surface mounts, which is the all-on default.
|
|
82
|
+
*/
|
|
83
|
+
setSurfaceGates(gates) {
|
|
84
|
+
this.gates = gates;
|
|
85
|
+
}
|
|
86
|
+
/** Install the per-suite MCP overrides provider used at mount time. */
|
|
87
|
+
setMcpOverridesProvider(provider) {
|
|
88
|
+
this.overridesProvider = provider;
|
|
89
|
+
}
|
|
90
|
+
/** Install the live tool-name provider used for foreign-namespace mount guards. */
|
|
91
|
+
setMcpToolNamesProvider(provider) {
|
|
92
|
+
this.mcp.setToolNamesProvider(provider);
|
|
93
|
+
}
|
|
94
|
+
/** Install the backend provider deciding which MCP client mounts each server. */
|
|
95
|
+
setMcpBackendProvider(provider) {
|
|
96
|
+
this.mcp.setBackendProvider(provider);
|
|
97
|
+
}
|
|
98
|
+
/** Whether the current MCP snapshot uses one credential reference. */
|
|
99
|
+
usesCredential(ref) {
|
|
100
|
+
return this.mcp.usesCredential(ref);
|
|
101
|
+
}
|
|
102
|
+
/** Flag one MCP mount for an explicit rebuild on the next reconcile. */
|
|
103
|
+
forceMcpRemount(suiteId, serverKey) {
|
|
104
|
+
this.mcp.forceRemount(suiteId, serverKey);
|
|
105
|
+
}
|
|
106
|
+
/** Flag every live MCP mount for a rebuild on the next reconcile. */
|
|
107
|
+
forceMcpRemountAll() {
|
|
108
|
+
this.mcp.forceRemountAll();
|
|
109
|
+
}
|
|
110
|
+
/** The mount key owning one derived serverName; undefined when not mounted here. */
|
|
111
|
+
mcpServerOwner(serverName) {
|
|
112
|
+
return this.mcp.serverOwner(serverName);
|
|
113
|
+
}
|
|
114
|
+
/** Publish fresh immutable authority without mounting or waiting behind network work. */
|
|
115
|
+
setCatalogAuthority(candidates, global) {
|
|
116
|
+
if (this.disposed)
|
|
117
|
+
return;
|
|
118
|
+
if (isDeepStrictEqual(this.authority, candidates) && isDeepStrictEqual(this.globalSuites, global))
|
|
119
|
+
return;
|
|
120
|
+
this.authorityEpoch++;
|
|
121
|
+
this.authority = structuredClone([...candidates]);
|
|
122
|
+
this.globalSuites = structuredClone([...global]);
|
|
123
|
+
}
|
|
124
|
+
/** Update full validated authority and the ordinary global base in one shared-service pass. */
|
|
125
|
+
refreshCatalog(candidates, global) {
|
|
126
|
+
return this.reconcileSnapshot(global, structuredClone([...candidates]));
|
|
127
|
+
}
|
|
128
|
+
/** Legacy enabled-only refresh never replaces full authority or session demand. */
|
|
129
|
+
reconcile(global) {
|
|
130
|
+
return this.reconcileSnapshot(global);
|
|
131
|
+
}
|
|
132
|
+
async reconcileSnapshot(global, authority) {
|
|
133
|
+
const diagnostics = emptyDiagnostics();
|
|
134
|
+
if (this.disposed)
|
|
135
|
+
return diagnostics;
|
|
136
|
+
const captured = structuredClone([...global]);
|
|
137
|
+
if (authority !== undefined)
|
|
138
|
+
this.setCatalogAuthority(authority, captured);
|
|
139
|
+
else if (!isDeepStrictEqual(this.globalSuites, captured)) {
|
|
140
|
+
this.authorityEpoch++;
|
|
141
|
+
this.globalSuites = captured;
|
|
142
|
+
}
|
|
143
|
+
const local = Promise.all([
|
|
144
|
+
this.surface('commands', diagnostics, () => this.commands.reconcile(this.agentScopedContributors || this.gates?.allows('commands') === false ? [] : captured)),
|
|
145
|
+
this.surface('hooks', diagnostics, () => this.hooks.reconcile(this.agentScopedContributors ? [] : captured))
|
|
146
|
+
]);
|
|
147
|
+
const shared = this.enqueue(async () => {
|
|
148
|
+
if (this.disposed)
|
|
149
|
+
return;
|
|
150
|
+
const result = await this.reconcileShared();
|
|
151
|
+
diagnostics.mcp = result.mcp;
|
|
152
|
+
diagnostics.lsp = result.lsp;
|
|
153
|
+
diagnostics.errors.push(...result.errors);
|
|
154
|
+
});
|
|
155
|
+
await Promise.all([local, shared]);
|
|
156
|
+
return diagnostics;
|
|
157
|
+
}
|
|
158
|
+
surface(key, diagnostics, work) {
|
|
159
|
+
const run = (this.queues.get(key) ?? Promise.resolve()).then(async () => {
|
|
160
|
+
if (this.disposed)
|
|
161
|
+
return;
|
|
162
|
+
try {
|
|
163
|
+
diagnostics[key] = await work();
|
|
164
|
+
}
|
|
165
|
+
catch (error) {
|
|
166
|
+
diagnostics.errors.push({ surface: key, reason: messageOf(error) });
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
this.queues.set(key, run);
|
|
170
|
+
return run;
|
|
171
|
+
}
|
|
172
|
+
enqueue(work) {
|
|
173
|
+
const run = this.sharedQueue.then(work);
|
|
174
|
+
this.sharedQueue = run.catch(() => undefined);
|
|
175
|
+
return run;
|
|
176
|
+
}
|
|
177
|
+
/** Stage only identities; configuration always comes from current validated authority. */
|
|
178
|
+
stageSessionDemand(owner, requested, directLspIds = []) {
|
|
179
|
+
const ids = demandIds(requested);
|
|
180
|
+
for (const id of directLspIds) {
|
|
181
|
+
if (!id.startsWith('direct/') || id.length === 7 || Array.from(id).some(character => character.charCodeAt(0) < 32 || character.charCodeAt(0) === 127))
|
|
182
|
+
return Promise.reject(new Error('extension-shared-invalid-direct-lsp'));
|
|
183
|
+
ids.add('lsp:' + id);
|
|
184
|
+
}
|
|
185
|
+
return (async () => {
|
|
186
|
+
if (this.disposed || this.authority === undefined)
|
|
187
|
+
throw new Error('extension-shared-not-ready');
|
|
188
|
+
if (this.staged.has(owner))
|
|
189
|
+
throw new Error('extension-shared-demand-busy');
|
|
190
|
+
const token = { ids, active: true, ready: false };
|
|
191
|
+
this.staged.set(owner, token);
|
|
192
|
+
let mounted = false;
|
|
193
|
+
const covered = new Set();
|
|
194
|
+
try {
|
|
195
|
+
const epoch = this.authorityEpoch;
|
|
196
|
+
const projected = this.project(ids);
|
|
197
|
+
const eligible = demandIds(projected);
|
|
198
|
+
for (const id of ids)
|
|
199
|
+
if (id.startsWith('lsp:direct/'))
|
|
200
|
+
eligible.add(id);
|
|
201
|
+
if ([...ids].some(id => !eligible.has(id)))
|
|
202
|
+
throw new Error('extension-shared-demand-unavailable');
|
|
203
|
+
const overrides = await this.overridesProvider();
|
|
204
|
+
const disabledLsp = await this.lspRegistry.globalDisabledProviderIds();
|
|
205
|
+
if (epoch !== this.authorityEpoch)
|
|
206
|
+
throw new Error('extension-shared-catalog-conflict');
|
|
207
|
+
const activation = projected.map(suite => {
|
|
208
|
+
const row = structuredClone(suite);
|
|
209
|
+
const key = suiteKey(suite);
|
|
210
|
+
const base = this.globalSuites.find(candidate => suiteKey(candidate) === key);
|
|
211
|
+
if (row.mcp)
|
|
212
|
+
row.mcp.servers = Object.fromEntries(Object.entries(row.mcp.servers).filter(([name]) => !(base?.enabled &&
|
|
213
|
+
base.activeSurfaces.mcp &&
|
|
214
|
+
this.gates?.allows('mcp') !== false &&
|
|
215
|
+
Object.hasOwn(base.mcp?.servers ?? {}, name) &&
|
|
216
|
+
overrides.get(key)?.[name]?.enabled !== false)));
|
|
217
|
+
if (row.lsp)
|
|
218
|
+
row.lsp.servers = Object.fromEntries(Object.entries(row.lsp.servers).filter(([, spec]) => !(base?.enabled &&
|
|
219
|
+
base.activeSurfaces.lsp &&
|
|
220
|
+
this.gates?.allows('lsp') !== false &&
|
|
221
|
+
Object.values(base.lsp?.servers ?? {}).some(candidate => candidate.key === spec.key) &&
|
|
222
|
+
!disabledLsp.has(key + '/' + spec.key))));
|
|
223
|
+
return row;
|
|
224
|
+
});
|
|
225
|
+
const activationIds = demandIds(activation);
|
|
226
|
+
for (const id of ids) {
|
|
227
|
+
if (id.startsWith('market:') || (!activationIds.has(id) && (!id.startsWith('lsp:direct/') || (!disabledLsp.has(id.slice(4)) && this.gates?.allows('lsp') !== false))))
|
|
228
|
+
covered.add(id);
|
|
229
|
+
}
|
|
230
|
+
const needsActivation = [...ids].some(id => !covered.has(id));
|
|
231
|
+
if (!token.active || this.disposed || this.staged.get(owner) !== token)
|
|
232
|
+
throw new Error('extension-shared-not-ready');
|
|
233
|
+
token.ready = true;
|
|
234
|
+
if (needsActivation)
|
|
235
|
+
await this.enqueue(async () => {
|
|
236
|
+
const current = demandIds(this.project(ids));
|
|
237
|
+
if ([...ids].some(id => !id.startsWith('lsp:direct/') && !current.has(id)))
|
|
238
|
+
throw new Error('extension-shared-demand-unavailable');
|
|
239
|
+
mounted = true;
|
|
240
|
+
const result = await this.reconcileShared();
|
|
241
|
+
if (this.disposed)
|
|
242
|
+
throw new Error('extension-shared-not-ready');
|
|
243
|
+
this.assertMounted(activation, result);
|
|
244
|
+
const owned = new Set(this.lspRegistry.providerOwnership().map(row => row.resourceId));
|
|
245
|
+
for (const id of ids)
|
|
246
|
+
if (id.startsWith('lsp:direct/') &&
|
|
247
|
+
(disabledLsp.has(id.slice(4)) || this.gates?.allows('lsp') === false) &&
|
|
248
|
+
(!owned.has(id) ||
|
|
249
|
+
result.errors.some(row => row.surface === 'lsp') ||
|
|
250
|
+
result.lsp.some(row => row.suiteId === 'direct' && (row.serverKey === id.slice(11) || row.serverKey === id.slice(4)))))
|
|
251
|
+
throw new Error('extension-shared-lsp-unavailable: ' + id);
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
catch (error) {
|
|
255
|
+
token.active = false;
|
|
256
|
+
this.staged.delete(owner);
|
|
257
|
+
try {
|
|
258
|
+
const cleanup = mounted ? await this.enqueue(() => this.reconcileShared()) : emptyDiagnostics();
|
|
259
|
+
if (cleanupFailed(cleanup))
|
|
260
|
+
this.warn('extension shared stage rollback failed; retained mounts remain execution-gated');
|
|
261
|
+
}
|
|
262
|
+
catch (cleanupError) {
|
|
263
|
+
this.warn('extension shared stage rollback failed: ' + messageOf(cleanupError));
|
|
264
|
+
}
|
|
265
|
+
throw error;
|
|
266
|
+
}
|
|
267
|
+
return {
|
|
268
|
+
commit: () => {
|
|
269
|
+
if (!token.active || this.disposed || this.staged.get(owner) !== token)
|
|
270
|
+
return;
|
|
271
|
+
const removed = [...(this.committed.get(owner) ?? [])].some(id => !token.ids.has(id) && !covered.has(id));
|
|
272
|
+
token.active = false;
|
|
273
|
+
this.committed.set(owner, token.ids);
|
|
274
|
+
this.staged.delete(owner);
|
|
275
|
+
if (removed)
|
|
276
|
+
void this.enqueue(() => this.reconcileShared())
|
|
277
|
+
.then(result => {
|
|
278
|
+
if (cleanupFailed(result))
|
|
279
|
+
this.warn('extension shared cleanup failed; retained mounts remain execution-gated');
|
|
280
|
+
})
|
|
281
|
+
.catch(error => {
|
|
282
|
+
this.warn('extension shared committed cleanup failed: ' + messageOf(error));
|
|
283
|
+
});
|
|
284
|
+
},
|
|
285
|
+
rollback: async () => {
|
|
286
|
+
if (!token.active || this.staged.get(owner) !== token)
|
|
287
|
+
return;
|
|
288
|
+
token.active = false;
|
|
289
|
+
this.staged.delete(owner);
|
|
290
|
+
if (mounted) {
|
|
291
|
+
const result = await this.enqueue(() => this.reconcileShared());
|
|
292
|
+
if (cleanupFailed(result))
|
|
293
|
+
throw new Error('extension-shared-rollback-failed');
|
|
294
|
+
}
|
|
295
|
+
else if (token.ready && token.ids.size > 0) {
|
|
296
|
+
void this.enqueue(() => this.reconcileShared()).catch(error => this.warn('extension shared rollback cleanup failed: ' + messageOf(error)));
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
};
|
|
300
|
+
})();
|
|
301
|
+
}
|
|
302
|
+
releaseSessionDemand(owner) {
|
|
303
|
+
return this.enqueue(async () => {
|
|
304
|
+
const token = this.staged.get(owner);
|
|
305
|
+
if (token)
|
|
306
|
+
token.active = false;
|
|
307
|
+
this.staged.delete(owner);
|
|
308
|
+
this.committed.delete(owner);
|
|
309
|
+
const result = await this.reconcileShared();
|
|
310
|
+
if (cleanupFailed(result))
|
|
311
|
+
throw new Error('extension-shared-release-failed');
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
project(ids) {
|
|
315
|
+
return projectExtensionSuites((this.authority ?? []).filter(row => row.suite.dimension === 'user'), captureExtensionSelection(null, [...ids])).map(row => row.suite);
|
|
316
|
+
}
|
|
317
|
+
async reconcileShared() {
|
|
318
|
+
const diagnostics = emptyDiagnostics();
|
|
319
|
+
if (this.disposed)
|
|
320
|
+
return diagnostics;
|
|
321
|
+
const epoch = this.authorityEpoch;
|
|
322
|
+
const ids = new Set([...this.committed.values(), ...[...this.staged.values()].filter(row => row.ready).map(row => row.ids)].flatMap(set => [...set]));
|
|
323
|
+
const projected = this.project(ids);
|
|
324
|
+
this.demandedMcp = new Map();
|
|
325
|
+
this.demandedLsp = new Set([...ids].filter(id => id.startsWith('lsp:direct/')).map(id => id.slice(4)));
|
|
326
|
+
for (const row of projected) {
|
|
327
|
+
const key = suiteKey(row);
|
|
328
|
+
const mcp = Object.keys(row.mcp?.servers ?? {});
|
|
329
|
+
if (mcp.length)
|
|
330
|
+
this.demandedMcp.set(key, new Set(mcp));
|
|
331
|
+
for (const spec of Object.values(row.lsp?.servers ?? {}))
|
|
332
|
+
this.demandedLsp.add(key + '/' + spec.key);
|
|
333
|
+
}
|
|
334
|
+
const forSurface = (face) => {
|
|
335
|
+
const global = this.gates?.allows(face) === false ? [] : this.globalSuites;
|
|
336
|
+
const rows = new Map();
|
|
337
|
+
for (const base of global) {
|
|
338
|
+
if (!base.activeSurfaces[face])
|
|
339
|
+
continue;
|
|
340
|
+
if (this.authority === undefined || base.dimension !== 'user') {
|
|
341
|
+
rows.set(suiteKey(base), structuredClone(base));
|
|
342
|
+
continue;
|
|
343
|
+
}
|
|
344
|
+
const current = this.authority.find(row => suiteKey(row.suite) === suiteKey(base));
|
|
345
|
+
if (!current || current.validSurfaces[face] !== true)
|
|
346
|
+
continue;
|
|
347
|
+
const row = structuredClone(current.suite);
|
|
348
|
+
row.enabled = true;
|
|
349
|
+
row.activeSurfaces[face] = true;
|
|
350
|
+
if (face === 'mcp' && row.mcp)
|
|
351
|
+
row.mcp.servers = Object.fromEntries(Object.entries(row.mcp.servers).filter(([key]) => Object.hasOwn(base.mcp?.servers ?? {}, key)));
|
|
352
|
+
if (face === 'lsp' && row.lsp) {
|
|
353
|
+
const keys = new Set(Object.values(base.lsp?.servers ?? {}).map(spec => spec.key));
|
|
354
|
+
row.lsp.servers = Object.fromEntries(Object.entries(row.lsp.servers).filter(([, spec]) => keys.has(spec.key)));
|
|
355
|
+
}
|
|
356
|
+
rows.set(suiteKey(base), row);
|
|
357
|
+
}
|
|
358
|
+
for (const demand of projected) {
|
|
359
|
+
if (!demand.activeSurfaces[face])
|
|
360
|
+
continue;
|
|
361
|
+
const key = suiteKey(demand);
|
|
362
|
+
const base = rows.get(key);
|
|
363
|
+
const latest = this.authority?.find(row => suiteKey(row.suite) === key)?.suite;
|
|
364
|
+
const merged = structuredClone(latest ?? demand);
|
|
365
|
+
merged.enabled = true;
|
|
366
|
+
merged.activeSurfaces[face] = true;
|
|
367
|
+
if (face === 'mcp')
|
|
368
|
+
merged.mcp = { ...demand.mcp, servers: { ...(base?.mcp?.servers ?? {}), ...demand.mcp.servers } };
|
|
369
|
+
else
|
|
370
|
+
merged.lsp = { servers: { ...(base?.lsp?.servers ?? {}), ...demand.lsp.servers } };
|
|
371
|
+
rows.set(key, merged);
|
|
372
|
+
}
|
|
373
|
+
return [...rows.values()];
|
|
374
|
+
};
|
|
375
|
+
await Promise.all([
|
|
376
|
+
this.surface('mcp', diagnostics, () => this.mcp.reconcile(forSurface('mcp'))),
|
|
377
|
+
this.surface('lsp', diagnostics, () => this.lspRegistry.reconcile(forSurface('lsp')))
|
|
378
|
+
]);
|
|
379
|
+
if (!this.disposed && epoch !== this.authorityEpoch) {
|
|
380
|
+
void this.enqueue(() => this.reconcileShared()).catch(error => this.warn('extension shared catalog refresh failed: ' + messageOf(error)));
|
|
381
|
+
}
|
|
382
|
+
return diagnostics;
|
|
383
|
+
}
|
|
384
|
+
assertMounted(suites, diagnostics) {
|
|
385
|
+
const mcpFailed = diagnostics.errors.some(row => row.surface === 'mcp');
|
|
386
|
+
const lspFailed = diagnostics.errors.some(row => row.surface === 'lsp');
|
|
387
|
+
const lsp = new Set(this.lspRegistry.providerOwnership().map(row => row.resourceId));
|
|
388
|
+
for (const suite of suites) {
|
|
389
|
+
const key = suiteKey(suite);
|
|
390
|
+
// Each suite proves its own surfaces in order: the MCP half needs this
|
|
391
|
+
// adapter's server-name derivation, so the adapter owns it.
|
|
392
|
+
this.mcp.assertMounted(suite, diagnostics.mcp, mcpFailed);
|
|
393
|
+
for (const spec of Object.values(suite.lsp?.servers ?? {})) {
|
|
394
|
+
if (!lsp.has('lsp:' + key + '/' + spec.key) ||
|
|
395
|
+
diagnostics.lsp.some(row => row.suiteId === key && (row.serverKey === spec.key || row.serverKey.split(',').includes(key + '/' + spec.key))) ||
|
|
396
|
+
lspFailed)
|
|
397
|
+
throw new Error('extension-shared-lsp-unavailable: ' + key + '/' + spec.key);
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
/** Stop receipt admission before draining shared and independently queued local work. */
|
|
402
|
+
dispose() {
|
|
403
|
+
if (this.disposal)
|
|
404
|
+
return this.disposal;
|
|
405
|
+
this.disposed = true;
|
|
406
|
+
for (const token of this.staged.values())
|
|
407
|
+
token.active = false;
|
|
408
|
+
this.staged.clear();
|
|
409
|
+
this.committed.clear();
|
|
410
|
+
this.disposal = (async () => {
|
|
411
|
+
await this.sharedQueue;
|
|
412
|
+
await Promise.all(this.queues.values());
|
|
413
|
+
const outcomes = await Promise.allSettled([
|
|
414
|
+
Promise.resolve().then(() => this.commands.disposeAll()),
|
|
415
|
+
Promise.resolve().then(() => this.mcp.disposeAll()),
|
|
416
|
+
Promise.resolve().then(() => this.hooks.disposeAll()),
|
|
417
|
+
Promise.resolve().then(() => this.lspRegistry.disposeAll())
|
|
418
|
+
]);
|
|
419
|
+
this.queues.clear();
|
|
420
|
+
const failures = outcomes.filter((result) => result.status === 'rejected').map(result => result.reason);
|
|
421
|
+
if (failures.length > 0)
|
|
422
|
+
throw new AggregateError(failures, 'runtime disposal failed: ' + failures.map(messageOf).join('; '));
|
|
423
|
+
})();
|
|
424
|
+
return this.disposal;
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
function cleanupFailed(result) {
|
|
428
|
+
return result.errors.length > 0 || [...result.mcp, ...result.lsp].some(row => row.code === 'unmount-failed');
|
|
429
|
+
}
|
|
430
|
+
function emptyDiagnostics() {
|
|
431
|
+
return { mcp: [], commands: [], hooks: [], lsp: [], errors: [] };
|
|
432
|
+
}
|
|
433
|
+
function suiteKey(suite) {
|
|
434
|
+
return suite.sourceId + '/' + suite.id;
|
|
435
|
+
}
|
|
436
|
+
function demandIds(suites) {
|
|
437
|
+
const ids = new Set();
|
|
438
|
+
for (const suite of suites) {
|
|
439
|
+
if (suite.dimension !== 'user')
|
|
440
|
+
continue;
|
|
441
|
+
const key = suiteKey(suite);
|
|
442
|
+
if (suite.activeSurfaces.mcp)
|
|
443
|
+
for (const name of Object.keys(suite.mcp?.servers ?? {})) {
|
|
444
|
+
ids.add('market:' + key);
|
|
445
|
+
ids.add('mcp:plugin:' + key + '/' + name);
|
|
446
|
+
}
|
|
447
|
+
if (suite.activeSurfaces.lsp)
|
|
448
|
+
for (const spec of Object.values(suite.lsp?.servers ?? {})) {
|
|
449
|
+
ids.add('market:' + key);
|
|
450
|
+
ids.add('lsp:' + key + '/' + spec.key);
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
return ids;
|
|
454
|
+
}
|
|
455
|
+
function messageOf(error) {
|
|
456
|
+
return error instanceof Error ? error.message : String(error);
|
|
457
|
+
}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unique call names for the commands this plugin registers.
|
|
3
|
+
*
|
|
4
|
+
* The host's command registry keys one name to one definition per layer:
|
|
5
|
+
* `NamedEntries.insert` throws `command "x" is already registered` when the
|
|
6
|
+
* name is taken, and the layer a registration lands in is chosen by the
|
|
7
|
+
* registry service's own context, never by the caller's. Two suites flattening
|
|
8
|
+
* to one call name, a host built-in such as `compact`, or a second mount
|
|
9
|
+
* registry feeding the same layer therefore collide — and a colliding
|
|
10
|
+
* definition is the one thing the slash menu drops, so the name has to be
|
|
11
|
+
* chosen before `register` is called. The layer's existing names cannot be
|
|
12
|
+
* enumerated from here, which leaves the refused registration as the only
|
|
13
|
+
* observable of a foreign occupant; {@link registerWithAllocatedName} retries
|
|
14
|
+
* with the next suffix.
|
|
15
|
+
*
|
|
16
|
+
* Allocation answers the preferred name while it is free and appends an
|
|
17
|
+
* increasing numeric suffix afterwards: the first conflict is `compact-1`,
|
|
18
|
+
* then `compact-2`. A name the host refused stays held as occupied, so the
|
|
19
|
+
* retry asks for the following suffix instead of repeating the name that just
|
|
20
|
+
* failed.
|
|
21
|
+
*
|
|
22
|
+
* @module runtime/command-name-allocator
|
|
23
|
+
*/
|
|
24
|
+
/** Suffixes one preferred name may spend before allocation gives up on it. */
|
|
25
|
+
export const MAX_COMMAND_NAME_ATTEMPTS = 50;
|
|
26
|
+
/** The host's duplicate-registration failure, as `CommandRuntime.register` renders it. */
|
|
27
|
+
const DUPLICATE_COMMAND_NAME = /^command "[^"]+" is already registered/;
|
|
28
|
+
/**
|
|
29
|
+
* Whether the host refused a registration because that exact name is taken.
|
|
30
|
+
*
|
|
31
|
+
* `CommandRuntime.register` renders one sentence for the global layer
|
|
32
|
+
* (`command "x" is already registered (for a per-agent variant, ...)`) and a
|
|
33
|
+
* shorter one for a scoped layer (`... in this scope`); both open with the
|
|
34
|
+
* same clause, and an error carrying any other text is a real failure rather
|
|
35
|
+
* than a name collision.
|
|
36
|
+
* @param error - the value thrown by `register`.
|
|
37
|
+
* @returns whether re-claiming under another name can succeed.
|
|
38
|
+
*/
|
|
39
|
+
export function isDuplicateCommandName(error) {
|
|
40
|
+
const message = error instanceof Error ? error.message : typeof error === 'string' ? error : '';
|
|
41
|
+
return DUPLICATE_COMMAND_NAME.test(message);
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Build a naming policy over `taken`.
|
|
45
|
+
*
|
|
46
|
+
* The allocator owns the names it hands out, which is what makes
|
|
47
|
+
* {@link CommandNameAllocator.release} meaningful; `taken` adds the names
|
|
48
|
+
* occupied outside it (another surface's registrations in the same layer, and
|
|
49
|
+
* the names the host has already refused).
|
|
50
|
+
* @param taken - every name currently unavailable to this allocator.
|
|
51
|
+
* @returns the allocator.
|
|
52
|
+
*/
|
|
53
|
+
export function createCommandNameAllocator(taken) {
|
|
54
|
+
const claimed = new Set();
|
|
55
|
+
return {
|
|
56
|
+
claim(preferred) {
|
|
57
|
+
const busy = new Set(taken());
|
|
58
|
+
for (const name of claimed)
|
|
59
|
+
busy.add(name);
|
|
60
|
+
if (!busy.has(preferred)) {
|
|
61
|
+
claimed.add(preferred);
|
|
62
|
+
return preferred;
|
|
63
|
+
}
|
|
64
|
+
for (let suffix = 1; suffix <= MAX_COMMAND_NAME_ATTEMPTS; suffix += 1) {
|
|
65
|
+
const candidate = `${preferred}-${suffix}`;
|
|
66
|
+
if (busy.has(candidate))
|
|
67
|
+
continue;
|
|
68
|
+
claimed.add(candidate);
|
|
69
|
+
return candidate;
|
|
70
|
+
}
|
|
71
|
+
throw new Error(`command name "${preferred}" has no free suffix within ${MAX_COMMAND_NAME_ATTEMPTS} attempts`);
|
|
72
|
+
},
|
|
73
|
+
release(name) {
|
|
74
|
+
claimed.delete(name);
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* The names one command layer holds for this plugin.
|
|
80
|
+
*
|
|
81
|
+
* A mount registry keeps one of these for the lifetime of its layer seat: it
|
|
82
|
+
* spans every reconcile pass, so a name stays reserved exactly as long as the
|
|
83
|
+
* registration carrying it is live, and it dies with the seat — a recomposed
|
|
84
|
+
* layer starts from the host's own occupancy alone. Names the host refused are
|
|
85
|
+
* held too, so a rename never retries a name this layer just rejected.
|
|
86
|
+
*
|
|
87
|
+
* Occupancy is per layer, not per process, because that is the unit the host
|
|
88
|
+
* checks: two agents' scoped layers each hold their own `review`, and neither
|
|
89
|
+
* registration sees the other. A process-wide ledger would rename the second
|
|
90
|
+
* one for a collision the host never reports.
|
|
91
|
+
*/
|
|
92
|
+
export class CommandNameRegistry {
|
|
93
|
+
/** Names held by this plugin in the layer, whether registered or refused. */
|
|
94
|
+
held = new Set();
|
|
95
|
+
allocator = createCommandNameAllocator(() => this.held);
|
|
96
|
+
/**
|
|
97
|
+
* Reserve the next free name for `preferred`.
|
|
98
|
+
* @param preferred - the name the command uses undisturbed.
|
|
99
|
+
* @returns the name to register under.
|
|
100
|
+
* @throws when every suffix within {@link MAX_COMMAND_NAME_ATTEMPTS} is taken.
|
|
101
|
+
*/
|
|
102
|
+
claim(preferred) {
|
|
103
|
+
const name = this.allocator.claim(preferred);
|
|
104
|
+
this.held.add(name);
|
|
105
|
+
return name;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Drop a name this plugin no longer registers, freeing it for a later claim.
|
|
109
|
+
* @param name - the name whose registration ended.
|
|
110
|
+
*/
|
|
111
|
+
forget(name) {
|
|
112
|
+
this.allocator.release(name);
|
|
113
|
+
this.held.delete(name);
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Hold a name the host refused, so it stays occupied without a registration.
|
|
117
|
+
* @param name - the refused call name.
|
|
118
|
+
*/
|
|
119
|
+
refuse(name) {
|
|
120
|
+
this.allocator.release(name);
|
|
121
|
+
this.held.add(name);
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Every name this layer holds for the plugin.
|
|
125
|
+
* @returns the allocated and refused names, as one read-only view.
|
|
126
|
+
*/
|
|
127
|
+
taken() {
|
|
128
|
+
return new Set(this.held);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Register under the first call name the layer accepts.
|
|
133
|
+
*
|
|
134
|
+
* The attempt loop is the only way past a foreign occupant: the layer's names
|
|
135
|
+
* are not enumerable, so a refusal is what moves allocation to the next
|
|
136
|
+
* suffix. A refusal is held on `names` before the retry, which is what makes
|
|
137
|
+
* the loop terminate — every iteration either registers or retires one
|
|
138
|
+
* candidate, and allocation itself fails once the suffix ceiling is reached.
|
|
139
|
+
* Any other failure ends the attempt immediately, because renaming around a
|
|
140
|
+
* malformed definition or an unavailable registry would report a rename
|
|
141
|
+
* instead of the bug that caused it.
|
|
142
|
+
* @param names - the layer's occupancy ledger.
|
|
143
|
+
* @param preferred - the name the command uses when nothing holds it.
|
|
144
|
+
* @param register - the host registration, called once per candidate name.
|
|
145
|
+
* @returns the accepted name and its registration, or the failure to diagnose.
|
|
146
|
+
*/
|
|
147
|
+
export function registerWithAllocatedName(names, preferred, register) {
|
|
148
|
+
for (;;) {
|
|
149
|
+
let name;
|
|
150
|
+
try {
|
|
151
|
+
name = names.claim(preferred);
|
|
152
|
+
}
|
|
153
|
+
catch (error) {
|
|
154
|
+
return { kind: 'failed', error };
|
|
155
|
+
}
|
|
156
|
+
try {
|
|
157
|
+
return { kind: 'registered', name, disposer: register(name) };
|
|
158
|
+
}
|
|
159
|
+
catch (error) {
|
|
160
|
+
if (!isDuplicateCommandName(error)) {
|
|
161
|
+
// The registration never landed, so the name is free again.
|
|
162
|
+
names.forget(name);
|
|
163
|
+
return { kind: 'failed', error };
|
|
164
|
+
}
|
|
165
|
+
names.refuse(name);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|