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,211 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* User command mounting: every enabled entry of the user commands panel
|
|
3
|
+
* registers as a dsh slash command, so user-authored quick replies behave
|
|
4
|
+
* exactly like suite commands — the body with `$ARGUMENTS` substituted rides
|
|
5
|
+
* one follow-up message on the receiving agent. A nested entry registers
|
|
6
|
+
* under its flattened call name (`git/commit` → `git-commit`) while the panel
|
|
7
|
+
* keeps addressing it by path; when two entries flatten to one call name the
|
|
8
|
+
* later one takes a numeric suffix (`git-commit-1`) and is reported, because a
|
|
9
|
+
* second registration of one name is what makes the host's slash menu drop it.
|
|
10
|
+
* Reconciled on every catalog change, keyed by the entry path.
|
|
11
|
+
* @module runtime/user-commands
|
|
12
|
+
*/
|
|
13
|
+
import { createUserMessage } from '@deepseek-ai/dsh-llm';
|
|
14
|
+
import { commandCallName } from '../../../../market-contracts/src/model/command-names.js';
|
|
15
|
+
import { USER_ENTRY_PATH, parseFrontmatterRecord } from '../../application/panels/user-store.js';
|
|
16
|
+
import { pluginMarketSource } from '../../../../market-contracts/src/host/plugin-message-source.js';
|
|
17
|
+
import { CommandNameRegistry, registerWithAllocatedName } from '../host/command-name-allocator.js';
|
|
18
|
+
/** Render a thrown value for a diagnostic, without trusting its string coercion. */
|
|
19
|
+
function messageOf(error) {
|
|
20
|
+
return error instanceof Error ? error.message : String(error);
|
|
21
|
+
}
|
|
22
|
+
/** Register/unregister user-panel commands to match the panel's enabled entries. */
|
|
23
|
+
export class UserCommandMountRegistry {
|
|
24
|
+
ctx;
|
|
25
|
+
store;
|
|
26
|
+
t;
|
|
27
|
+
fingerprints = new Map();
|
|
28
|
+
live = new Map();
|
|
29
|
+
/**
|
|
30
|
+
* The call names this seat holds, and the entry each one was registered for.
|
|
31
|
+
*
|
|
32
|
+
* Occupancy is per layer, which is the unit the host checks: this registry
|
|
33
|
+
* registers into the global layer, so its names must be unique among
|
|
34
|
+
* themselves and against every other registration in that layer.
|
|
35
|
+
*/
|
|
36
|
+
names = new CommandNameRegistry();
|
|
37
|
+
registeredName = new Map();
|
|
38
|
+
/** The menu row each live registration produces, with the panel id it translates as. */
|
|
39
|
+
registered = new Map();
|
|
40
|
+
/** Per-workspace entry filter; an absent provider registers everything wanted. */
|
|
41
|
+
entryFilter;
|
|
42
|
+
selectionPolicy;
|
|
43
|
+
registrationPolicy;
|
|
44
|
+
allowDisabled = false;
|
|
45
|
+
constructor(ctx, store, t) {
|
|
46
|
+
this.ctx = ctx;
|
|
47
|
+
this.store = store;
|
|
48
|
+
this.t = t;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Install the per-workspace entry filter read at wanted-row time, keyed by
|
|
52
|
+
* the panel path name the resource window lists (`commands:${entry.name}`).
|
|
53
|
+
*/
|
|
54
|
+
setEntryFilter(filter) {
|
|
55
|
+
this.entryFilter = filter;
|
|
56
|
+
}
|
|
57
|
+
/** Gate reconcile and execution by the original panel path name; unset allows all. */
|
|
58
|
+
setSelectionPolicy(callback, registration = callback, options = {}) {
|
|
59
|
+
this.selectionPolicy = callback;
|
|
60
|
+
this.registrationPolicy = registration;
|
|
61
|
+
this.allowDisabled = options.allowDisabled === true;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Sync the live registrations with the panel's enabled entries.
|
|
65
|
+
*
|
|
66
|
+
* A switched-off commands surface reconciles against no entries at all,
|
|
67
|
+
* which unregisters whatever is live — skipping the pass would leave the
|
|
68
|
+
* previous registrations mounted after the switch went off.
|
|
69
|
+
* @param allow - whether the workspace's commands switch is on.
|
|
70
|
+
*/
|
|
71
|
+
async reconcile(allow = true) {
|
|
72
|
+
const diagnostics = [];
|
|
73
|
+
const entries = allow ? await this.store.list() : [];
|
|
74
|
+
const wanted = new Map();
|
|
75
|
+
// Keyed by the entry path, not the call name: two entries that flatten to
|
|
76
|
+
// one call name are two commands, and the second gets a suffixed call name
|
|
77
|
+
// rather than replacing the first in the wanted map.
|
|
78
|
+
for (const entry of entries) {
|
|
79
|
+
if (entry.metadata['validationError'] !== undefined)
|
|
80
|
+
continue;
|
|
81
|
+
try {
|
|
82
|
+
parseFrontmatterRecord(entry.rawText);
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
if (entry.disabled && !(this.allowDisabled && this.registrationPolicy?.(entry.name) === true))
|
|
88
|
+
continue;
|
|
89
|
+
if (this.entryFilter?.().allows('commands', `commands:${entry.name}`) === false)
|
|
90
|
+
continue;
|
|
91
|
+
if (this.registrationPolicy?.(entry.name) === false)
|
|
92
|
+
continue;
|
|
93
|
+
if (!USER_ENTRY_PATH.test(entry.name))
|
|
94
|
+
continue;
|
|
95
|
+
wanted.set(entry.name, {
|
|
96
|
+
name: commandCallName(entry.name),
|
|
97
|
+
description: entry.description === '' ? `[${this.t('userCommandSourceLabel')}] ${commandCallName(entry.name)}` : `[${this.t('userCommandSourceLabel')}] ${entry.description}`,
|
|
98
|
+
...(typeof entry.metadata['argument-hint'] === 'string' && entry.metadata['argument-hint'] !== '' ? { hint: entry.metadata['argument-hint'] } : {}),
|
|
99
|
+
body: entry.content
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
for (const [key, disposer] of [...this.live]) {
|
|
103
|
+
if (!wanted.has(key)) {
|
|
104
|
+
disposer();
|
|
105
|
+
this.live.delete(key);
|
|
106
|
+
this.fingerprints.delete(key);
|
|
107
|
+
this.releaseName(key);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
const host = this.ctx;
|
|
111
|
+
const commands = host.commands;
|
|
112
|
+
if (typeof commands?.register !== 'function') {
|
|
113
|
+
if (wanted.size > 0)
|
|
114
|
+
diagnostics.push('ctx.commands is not available in this profile; user commands stay unregistered');
|
|
115
|
+
return diagnostics;
|
|
116
|
+
}
|
|
117
|
+
for (const [key, spec] of wanted) {
|
|
118
|
+
const fingerprint = JSON.stringify(spec);
|
|
119
|
+
if (this.live.has(key) && this.fingerprints.get(key) === fingerprint)
|
|
120
|
+
continue;
|
|
121
|
+
this.live.get(key)?.();
|
|
122
|
+
this.live.delete(key);
|
|
123
|
+
this.fingerprints.delete(key);
|
|
124
|
+
this.releaseName(key);
|
|
125
|
+
const attempt = registerWithAllocatedName(this.names, spec.name, name => commands.register({
|
|
126
|
+
name,
|
|
127
|
+
description: spec.description,
|
|
128
|
+
...(spec.hint === undefined ? {} : { input: { hint: spec.hint } }),
|
|
129
|
+
handler: invocation => {
|
|
130
|
+
const agent = invocation.agent;
|
|
131
|
+
const send = (body) => {
|
|
132
|
+
if (this.selectionPolicy?.(key) === false)
|
|
133
|
+
return { kind: 'error', text: this.t('commandNotSelected', { command: name }) };
|
|
134
|
+
agent.followup(createUserMessage({
|
|
135
|
+
content: [{ type: 'text', text: body.replaceAll('$ARGUMENTS', invocation.rawInput.trim()) }],
|
|
136
|
+
source: pluginMarketSource()
|
|
137
|
+
}));
|
|
138
|
+
return { kind: 'success', text: this.t('commandAcknowledged', { command: name }) };
|
|
139
|
+
};
|
|
140
|
+
if (!this.selectionPolicy)
|
|
141
|
+
return send(spec.body);
|
|
142
|
+
return (async () => {
|
|
143
|
+
const denied = () => ({ kind: 'error', text: this.t('commandNotSelected', { command: name }) });
|
|
144
|
+
if (this.selectionPolicy?.(key) !== true)
|
|
145
|
+
return denied();
|
|
146
|
+
try {
|
|
147
|
+
const entry = await this.store.get(key);
|
|
148
|
+
if (!entry || entry.metadata['validationError'] !== undefined || (entry.disabled && !this.allowDisabled))
|
|
149
|
+
return denied();
|
|
150
|
+
parseFrontmatterRecord(entry.rawText);
|
|
151
|
+
if (this.selectionPolicy?.(key) !== true)
|
|
152
|
+
return denied();
|
|
153
|
+
return send(entry.content);
|
|
154
|
+
}
|
|
155
|
+
catch {
|
|
156
|
+
return denied();
|
|
157
|
+
}
|
|
158
|
+
})();
|
|
159
|
+
}
|
|
160
|
+
}));
|
|
161
|
+
if (attempt.kind === 'failed') {
|
|
162
|
+
diagnostics.push(`command "${spec.name}": ${messageOf(attempt.error)}`);
|
|
163
|
+
continue;
|
|
164
|
+
}
|
|
165
|
+
this.live.set(key, attempt.disposer);
|
|
166
|
+
this.fingerprints.set(key, fingerprint);
|
|
167
|
+
this.registeredName.set(key, attempt.name);
|
|
168
|
+
// The wanted map is keyed by the entry name the panel lists, which is also
|
|
169
|
+
// the id the panel translated that entry under — one spelling, one cache
|
|
170
|
+
// entry, so the menu shows the text the panel already paid for.
|
|
171
|
+
this.registered.set(key, { name: attempt.name, id: key });
|
|
172
|
+
// The panel addresses the entry by path, so a renamed registration is
|
|
173
|
+
// reported where the entry is listed rather than left to be discovered
|
|
174
|
+
// from the slash menu.
|
|
175
|
+
if (attempt.name !== spec.name) {
|
|
176
|
+
diagnostics.push(`command "${spec.name}": registered as "${attempt.name}" because the call name is already taken`);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
return diagnostics;
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Every command this seat currently holds: the call name the menu row carries
|
|
183
|
+
* and the panel identity that owns its translation.
|
|
184
|
+
*
|
|
185
|
+
* The registry is the only place that knows a name allocation suffixed, and a
|
|
186
|
+
* user entry's panel identity is the entry name the panel lists.
|
|
187
|
+
* @returns one row per live registration, in registration-key order.
|
|
188
|
+
*/
|
|
189
|
+
registrations() {
|
|
190
|
+
return [...this.registered.values()];
|
|
191
|
+
}
|
|
192
|
+
/** Dispose every registration (plugin teardown). */
|
|
193
|
+
disposeAll() {
|
|
194
|
+
for (const disposer of [...this.live.values()])
|
|
195
|
+
disposer();
|
|
196
|
+
for (const key of [...this.registeredName.keys()])
|
|
197
|
+
this.releaseName(key);
|
|
198
|
+
this.registered.clear();
|
|
199
|
+
this.live.clear();
|
|
200
|
+
this.fingerprints.clear();
|
|
201
|
+
}
|
|
202
|
+
/** Free the call name one unmounted entry held, so a later claim can reuse it. */
|
|
203
|
+
releaseName(key) {
|
|
204
|
+
const name = this.registeredName.get(key);
|
|
205
|
+
if (name === undefined)
|
|
206
|
+
return;
|
|
207
|
+
this.names.forget(name);
|
|
208
|
+
this.registeredName.delete(key);
|
|
209
|
+
this.registered.delete(key);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
* @module runtime/user-panels
|
|
31
31
|
*/
|
|
32
32
|
import { dirname } from 'node:path';
|
|
33
|
-
import { skillEntryRejection } from '
|
|
33
|
+
import { skillEntryRejection } from '../../../../market-catalog/src/index.js';
|
|
34
34
|
import { deleteEntryDocument, entryExists, listEntryDocuments, listEntryFiles, readEntryDocument, resolveEntryDocument, SKILL_ENTRY_SHAPES, USER_ENTRY_NAME, USER_ENTRY_PATH, userEntryDir, writeEntryDocument, writeEntryFile } from '../../application/panels/user-store.js';
|
|
35
35
|
/** The skill-source label user-panel entries carry into the skill registry. */
|
|
36
36
|
export const USER_PANEL_SKILL_SOURCE = 'user-panel';
|
|
@@ -43,9 +43,8 @@ export const USER_PANEL_SKILL_SOURCE = 'user-panel';
|
|
|
43
43
|
* (450), so a skill the user wrote by hand wins over one an installed suite
|
|
44
44
|
* ships under the same name.
|
|
45
45
|
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
* file honors.
|
|
46
|
+
* Global panel switches write the invocation pair into the document. A scoped
|
|
47
|
+
* selection policy overrides only that session and never writes the document.
|
|
49
48
|
*/
|
|
50
49
|
const USER_PANEL_RANK = 440;
|
|
51
50
|
/** Throwing CRUD over one panel directory, shared by the three panels. */
|
|
@@ -205,15 +204,33 @@ export function isUserSkillEntryName(name) {
|
|
|
205
204
|
*/
|
|
206
205
|
export class UserPanelSkillProvider {
|
|
207
206
|
skills;
|
|
207
|
+
options;
|
|
208
208
|
name = 'user-panel';
|
|
209
|
-
constructor(skills) {
|
|
209
|
+
constructor(skills, options = {}) {
|
|
210
210
|
this.skills = skills;
|
|
211
|
+
this.options = options;
|
|
212
|
+
}
|
|
213
|
+
invocation(entry) {
|
|
214
|
+
if (!isUserSkillEntryName(entry.name) || entry.metadata['validationError'] !== undefined)
|
|
215
|
+
return undefined;
|
|
216
|
+
if (!this.options.enabled && entry.disabled)
|
|
217
|
+
return undefined;
|
|
218
|
+
const authored = {
|
|
219
|
+
modelInvocable: entry.metadata['disable-model-invocation'] !== true,
|
|
220
|
+
userInvocable: entry.metadata['user-invocable'] !== false
|
|
221
|
+
};
|
|
222
|
+
if (!this.options.enabled)
|
|
223
|
+
return authored;
|
|
224
|
+
if (!this.options.enabled(entry))
|
|
225
|
+
return { modelInvocable: false, userInvocable: false };
|
|
226
|
+
return !authored.modelInvocable && !authored.userInvocable ? { modelInvocable: true, userInvocable: true } : authored;
|
|
211
227
|
}
|
|
212
228
|
async list(_options) {
|
|
213
229
|
const candidates = [];
|
|
214
230
|
const skills = await this.skills.list();
|
|
215
231
|
for (const entry of skills) {
|
|
216
|
-
|
|
232
|
+
const invocation = this.invocation(entry);
|
|
233
|
+
if (!invocation)
|
|
217
234
|
continue;
|
|
218
235
|
candidates.push({
|
|
219
236
|
// The entry's name is the one its document declares, which is also the
|
|
@@ -224,10 +241,7 @@ export class UserPanelSkillProvider {
|
|
|
224
241
|
// catalog a suite skill does.
|
|
225
242
|
description: entry.description === '' ? entry.name : entry.description,
|
|
226
243
|
...(typeof entry.metadata['whenToUse'] === 'string' && entry.metadata['whenToUse'] !== '' ? { whenToUse: entry.metadata['whenToUse'] } : {}),
|
|
227
|
-
invocation
|
|
228
|
-
modelInvocable: entry.metadata['disable-model-invocation'] !== true,
|
|
229
|
-
userInvocable: entry.metadata['user-invocable'] !== false
|
|
230
|
-
},
|
|
244
|
+
invocation,
|
|
231
245
|
source: USER_PANEL_SKILL_SOURCE,
|
|
232
246
|
provider: this.name,
|
|
233
247
|
rank: USER_PANEL_RANK,
|
|
@@ -240,15 +254,21 @@ export class UserPanelSkillProvider {
|
|
|
240
254
|
}
|
|
241
255
|
async get(candidate, _options) {
|
|
242
256
|
const locator = candidate.locator;
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
if (
|
|
257
|
+
if (typeof locator?.name !== 'string' || !isUserSkillEntryName(locator.name))
|
|
258
|
+
return undefined;
|
|
259
|
+
if (this.options.enabled && (candidate.provider !== this.name || candidate.source !== USER_PANEL_SKILL_SOURCE || candidate.name !== locator.name))
|
|
260
|
+
return undefined;
|
|
261
|
+
const entry = await this.skills.get(locator.name);
|
|
262
|
+
if (entry === undefined || (this.options.enabled && (entry.name !== candidate.name || entry.path !== candidate.path)))
|
|
263
|
+
return undefined;
|
|
264
|
+
const invocation = this.invocation(entry);
|
|
265
|
+
if (!invocation || (!invocation.modelInvocable && !invocation.userInvocable))
|
|
246
266
|
return undefined;
|
|
247
267
|
return {
|
|
248
268
|
name: candidate.name,
|
|
249
269
|
description: candidate.description,
|
|
250
270
|
...(typeof entry.metadata['whenToUse'] === 'string' && entry.metadata['whenToUse'] !== '' ? { whenToUse: entry.metadata['whenToUse'] } : {}),
|
|
251
|
-
invocation: candidate.invocation,
|
|
271
|
+
invocation: this.options.enabled ? invocation : candidate.invocation,
|
|
252
272
|
source: candidate.source,
|
|
253
273
|
provider: this.name,
|
|
254
274
|
resourceBase: { kind: 'directory', path: this.resourceDirectory(entry) },
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
import { createUserMessage } from '@deepseek-ai/dsh-llm';
|
|
2
|
+
import { qualifiedSuiteId, suiteDataDir } from '../../../../market-catalog/src/index.js';
|
|
3
|
+
import { expandPluginPaths, pluginRootOf } from '../../../../market-catalog/src/index.js';
|
|
4
|
+
import { defaultMarkdownResources, resourceText } from '../../../../market-catalog/src/index.js';
|
|
5
|
+
import { parseCommandResource, readCommands } from '../../application/command-resources.js';
|
|
6
|
+
export { readCommands } from '../../application/command-resources.js';
|
|
7
|
+
import { bindHostLocale } from '../host/host-locale.js';
|
|
8
|
+
import { injectDynamicContext, shellSeamOf } from './dynamic-context.js';
|
|
9
|
+
import { pluginMarketSource } from '../../../../market-contracts/src/host/plugin-message-source.js';
|
|
10
|
+
import { CommandNameRegistry, registerWithAllocatedName } from '../host/command-name-allocator.js';
|
|
11
|
+
import { pluginResourceId } from '../../application/panel-resources.js';
|
|
12
|
+
/** Render a thrown value for a diagnostic, without trusting its string coercion. */
|
|
13
|
+
function messageOf(error) {
|
|
14
|
+
return error instanceof Error ? error.message : String(error);
|
|
15
|
+
}
|
|
16
|
+
export class CommandMountRegistry {
|
|
17
|
+
ctx;
|
|
18
|
+
t;
|
|
19
|
+
dataRoot;
|
|
20
|
+
fingerprints = new Map();
|
|
21
|
+
live = new Map();
|
|
22
|
+
/**
|
|
23
|
+
* The call names this seat holds, and the keys they were registered under.
|
|
24
|
+
*
|
|
25
|
+
* Occupancy is per layer, which is the unit the host checks: this registry
|
|
26
|
+
* instance registers into one layer (an agent's scope on the project path,
|
|
27
|
+
* the global layer on the user path), and a sibling registry in another
|
|
28
|
+
* layer neither sees nor is seen by these names.
|
|
29
|
+
*/
|
|
30
|
+
names = new CommandNameRegistry();
|
|
31
|
+
registeredName = new Map();
|
|
32
|
+
/** The menu row each live registration produces, with the panel id it translates as. */
|
|
33
|
+
registered = new Map();
|
|
34
|
+
/** Per-workspace entry filter; an absent provider registers everything wanted. */
|
|
35
|
+
entryFilter;
|
|
36
|
+
selectionPolicy;
|
|
37
|
+
registrationPolicy;
|
|
38
|
+
allowDisabled = false;
|
|
39
|
+
constructor(ctx, t = bindHostLocale(undefined), dataRoot) {
|
|
40
|
+
this.ctx = ctx;
|
|
41
|
+
this.t = t;
|
|
42
|
+
this.dataRoot = dataRoot;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Install the per-workspace entry filter read at wanted-row time. A filtered
|
|
46
|
+
* command never becomes wanted, which unregisters it through the ordinary
|
|
47
|
+
* reconcile pass — the same path a removed command file takes.
|
|
48
|
+
*/
|
|
49
|
+
setEntryFilter(filter) {
|
|
50
|
+
this.entryFilter = filter;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Gate reconcile and execution by owning suite and authored resource name,
|
|
54
|
+
* before call-name flattening or collision allocation. Unset allows all.
|
|
55
|
+
*/
|
|
56
|
+
setSelectionPolicy(callback, registration = callback, options = {}) {
|
|
57
|
+
this.selectionPolicy = callback;
|
|
58
|
+
this.registrationPolicy = registration;
|
|
59
|
+
this.allowDisabled = options.allowDisabled === true;
|
|
60
|
+
}
|
|
61
|
+
/** The live shell seam, when the profile has one; dynamic context stays literal without it. */
|
|
62
|
+
shell() {
|
|
63
|
+
return shellSeamOf(this.ctx);
|
|
64
|
+
}
|
|
65
|
+
/** Register/unregister suite commands to match the enabled suites exactly. */
|
|
66
|
+
async reconcile(enabledSuites) {
|
|
67
|
+
const diagnostics = [];
|
|
68
|
+
const wanted = new Map();
|
|
69
|
+
/** How many specs already claimed one suite-qualified call name this pass. */
|
|
70
|
+
const occurrences = new Map();
|
|
71
|
+
for (const suite of enabledSuites) {
|
|
72
|
+
const specs = [];
|
|
73
|
+
const resources = suite.activeSurfaces.commands === false ? [] : (suite.resources?.commands ?? (await defaultMarkdownResources(suite.root, 'commands')));
|
|
74
|
+
for (const resource of resources) {
|
|
75
|
+
const includeDisabled = this.allowDisabled && this.registrationPolicy?.(suite, resource.name) === true;
|
|
76
|
+
for (const spec of await readCommands(suite.root, [resource], { includeDisabled }))
|
|
77
|
+
specs.push({ ...spec, resource });
|
|
78
|
+
}
|
|
79
|
+
const suiteRoot = pluginRootOf(suite);
|
|
80
|
+
const suiteData = suiteRoot === undefined || this.dataRoot === undefined ? undefined : suiteDataDir(this.dataRoot, suite.sourceId, suite.id);
|
|
81
|
+
for (const spec of specs) {
|
|
82
|
+
// The registry key is source-qualified: bare suite ids are unique per
|
|
83
|
+
// source only, so two sources' same-named suites would collide.
|
|
84
|
+
const suiteKey = qualifiedSuiteId(suite.sourceId, suite.id);
|
|
85
|
+
// Two files of one suite flatten to one call name (`git/commit` and
|
|
86
|
+
// `git-commit`) and are both real commands, so the key counts them
|
|
87
|
+
// apart and allocation gives the second one a suffix instead of
|
|
88
|
+
// dropping it. The count is per pass, so re-reading the same suite
|
|
89
|
+
// reproduces the same keys.
|
|
90
|
+
const qualified = `${suiteKey}/${spec.name}`;
|
|
91
|
+
const occurrence = occurrences.get(qualified) ?? 0;
|
|
92
|
+
occurrences.set(qualified, occurrence + 1);
|
|
93
|
+
const key = occurrence === 0 ? qualified : `${qualified}#${occurrence}`;
|
|
94
|
+
// The per-workspace resource filter answers by the call name the model
|
|
95
|
+
// types, so the window and the registry agree on what one row names.
|
|
96
|
+
if (this.entryFilter?.().allows('commands', `commands:${spec.name}`) === false)
|
|
97
|
+
continue;
|
|
98
|
+
if (this.registrationPolicy?.(suite, spec.resourceName) === false)
|
|
99
|
+
continue;
|
|
100
|
+
wanted.set(key, {
|
|
101
|
+
...spec,
|
|
102
|
+
suite,
|
|
103
|
+
suiteId: suiteKey,
|
|
104
|
+
suiteName: suite.manifest.name,
|
|
105
|
+
// Kept apart from the qualified `suiteId` above: the panel id is built
|
|
106
|
+
// from the two raw halves, exactly as the panel builds it.
|
|
107
|
+
sourceId: suite.sourceId,
|
|
108
|
+
rawSuiteId: suite.id,
|
|
109
|
+
...(suiteRoot === undefined ? {} : { suiteRoot }),
|
|
110
|
+
...(suiteData === undefined ? {} : { suiteData })
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
for (const [key, disposer] of [...this.live]) {
|
|
115
|
+
if (!wanted.has(key)) {
|
|
116
|
+
disposer();
|
|
117
|
+
this.live.delete(key);
|
|
118
|
+
this.fingerprints.delete(key);
|
|
119
|
+
this.releaseName(key);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
const host = this.ctx;
|
|
123
|
+
const commands = host.commands;
|
|
124
|
+
if (typeof commands?.register !== 'function') {
|
|
125
|
+
if (wanted.size > 0)
|
|
126
|
+
diagnostics.push({ suiteId: '', command: '', reason: 'ctx.commands is not available in this profile' });
|
|
127
|
+
return diagnostics;
|
|
128
|
+
}
|
|
129
|
+
for (const [key, { suite, ...spec }] of wanted) {
|
|
130
|
+
const fingerprint = JSON.stringify(spec);
|
|
131
|
+
if (this.live.has(key) && this.fingerprints.get(key) === fingerprint)
|
|
132
|
+
continue;
|
|
133
|
+
this.live.get(key)?.();
|
|
134
|
+
this.live.delete(key);
|
|
135
|
+
this.fingerprints.delete(key);
|
|
136
|
+
this.releaseName(key);
|
|
137
|
+
// A name the layer already holds — a sibling suite flattening to the
|
|
138
|
+
// same call name, a host built-in such as /compact, or a leftover
|
|
139
|
+
// registration — is the one case the host refuses outright, and a
|
|
140
|
+
// refused definition is what the slash menu drops. Allocating the name
|
|
141
|
+
// first turns that collision into a suffix instead of a disappearance.
|
|
142
|
+
const attempt = registerWithAllocatedName(this.names, spec.name, name => commands.register({
|
|
143
|
+
name,
|
|
144
|
+
description: `[${spec.suiteName}] ${spec.description}`,
|
|
145
|
+
...(spec.hint === undefined ? {} : { input: { hint: spec.hint } }),
|
|
146
|
+
handler: async (invocation) => {
|
|
147
|
+
const agent = invocation.agent;
|
|
148
|
+
const workdir = agent.session?.header?.cwd;
|
|
149
|
+
// The template rides the agent verbatim apart from the placeholders
|
|
150
|
+
// its author wrote: a decorator line naming this plugin or the
|
|
151
|
+
// suite would be text the command author never wrote, and the
|
|
152
|
+
// follow-up's `source` already records provenance.
|
|
153
|
+
let authoredBody = spec.body;
|
|
154
|
+
if (this.selectionPolicy) {
|
|
155
|
+
if (this.selectionPolicy(suite, spec.resourceName) !== true)
|
|
156
|
+
return { kind: 'error', text: this.t('commandNotSelected', { command: name }) };
|
|
157
|
+
try {
|
|
158
|
+
const resource = !this.allowDisabled || spec.resource.file === suite.manifest.path ? spec.resource : { name: spec.resource.name, file: spec.resource.file };
|
|
159
|
+
const fresh = parseCommandResource(resource, await resourceText(resource), { includeDisabled: this.allowDisabled });
|
|
160
|
+
if (!fresh || this.selectionPolicy(suite, spec.resourceName) !== true)
|
|
161
|
+
return { kind: 'error', text: this.t('commandNotSelected', { command: name }) };
|
|
162
|
+
authoredBody = fresh.body;
|
|
163
|
+
}
|
|
164
|
+
catch {
|
|
165
|
+
return { kind: 'error', text: this.t('commandNotSelected', { command: name }) };
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
const body = expandPluginPaths(authoredBody, {
|
|
169
|
+
...(spec.suiteRoot === undefined ? {} : { root: spec.suiteRoot }),
|
|
170
|
+
...(spec.suiteData === undefined ? {} : { data: spec.suiteData }),
|
|
171
|
+
...(workdir === undefined ? {} : { projectDir: workdir })
|
|
172
|
+
}).replaceAll('$ARGUMENTS', invocation.rawInput.trim());
|
|
173
|
+
if (this.selectionPolicy?.(suite, spec.resourceName) === false) {
|
|
174
|
+
return { kind: 'error', text: this.t('commandNotSelected', { command: name }) };
|
|
175
|
+
}
|
|
176
|
+
const shell = this.shell();
|
|
177
|
+
if (shell === undefined) {
|
|
178
|
+
agent.followup(createUserMessage({
|
|
179
|
+
content: [{ type: 'text', text: body }],
|
|
180
|
+
source: pluginMarketSource()
|
|
181
|
+
}));
|
|
182
|
+
return { kind: 'success', text: this.t('commandAcknowledged', { command: name }) };
|
|
183
|
+
}
|
|
184
|
+
let text;
|
|
185
|
+
try {
|
|
186
|
+
text = await injectDynamicContext(body, { shell, ...(workdir === undefined ? {} : { workdir }) });
|
|
187
|
+
}
|
|
188
|
+
catch (error) {
|
|
189
|
+
return { kind: 'error', text: error instanceof Error ? error.message : String(error) };
|
|
190
|
+
}
|
|
191
|
+
if (this.selectionPolicy?.(suite, spec.resourceName) === false) {
|
|
192
|
+
return { kind: 'error', text: this.t('commandNotSelected', { command: name }) };
|
|
193
|
+
}
|
|
194
|
+
agent.followup(createUserMessage({
|
|
195
|
+
content: [{ type: 'text', text }],
|
|
196
|
+
source: pluginMarketSource()
|
|
197
|
+
}));
|
|
198
|
+
return { kind: 'success', text: this.t('commandAcknowledged', { command: name }) };
|
|
199
|
+
}
|
|
200
|
+
}));
|
|
201
|
+
if (attempt.kind === 'failed') {
|
|
202
|
+
diagnostics.push({ suiteId: spec.suiteId, command: spec.name, reason: messageOf(attempt.error) });
|
|
203
|
+
continue;
|
|
204
|
+
}
|
|
205
|
+
this.live.set(key, attempt.disposer);
|
|
206
|
+
this.fingerprints.set(key, fingerprint);
|
|
207
|
+
this.registeredName.set(key, attempt.name);
|
|
208
|
+
// The panel addresses this document by the resource name it read plus the
|
|
209
|
+
// suite it belongs to, so the id is built exactly as the panel builds it —
|
|
210
|
+
// same inputs, same string, one shared cache entry.
|
|
211
|
+
this.registered.set(key, { name: attempt.name, id: pluginResourceId(spec.sourceId, spec.rawSuiteId, 'commands', spec.resourceName ?? spec.name) });
|
|
212
|
+
// A renamed command still works, so this is not a failure: it is the
|
|
213
|
+
// one record that the name a user types is not the name the file
|
|
214
|
+
// carries, which nothing else in the status surfaces would show.
|
|
215
|
+
if (attempt.name !== spec.name) {
|
|
216
|
+
diagnostics.push({
|
|
217
|
+
suiteId: spec.suiteId,
|
|
218
|
+
command: attempt.name,
|
|
219
|
+
reason: `registered as "${attempt.name}" because "${spec.name}" is already taken in this command layer`
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
return diagnostics;
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Every command this layer currently holds: the call name the menu row
|
|
227
|
+
* carries and the panel identity that owns its translation.
|
|
228
|
+
*
|
|
229
|
+
* Two files of one suite can flatten to the same call name, so the
|
|
230
|
+
* registration key (not the name) is what tells those rows apart; each one
|
|
231
|
+
* keeps its own resource name and therefore its own translation id.
|
|
232
|
+
* @returns one row per live registration, in registration-key order.
|
|
233
|
+
*/
|
|
234
|
+
registrations() {
|
|
235
|
+
return [...this.registered.values()];
|
|
236
|
+
}
|
|
237
|
+
/** Dispose every registered command; used at plugin teardown. */
|
|
238
|
+
disposeAll() {
|
|
239
|
+
for (const disposer of [...this.live.values()])
|
|
240
|
+
disposer();
|
|
241
|
+
for (const key of [...this.registeredName.keys()])
|
|
242
|
+
this.releaseName(key);
|
|
243
|
+
this.registered.clear();
|
|
244
|
+
this.live.clear();
|
|
245
|
+
this.fingerprints.clear();
|
|
246
|
+
}
|
|
247
|
+
/** Free the call name one unmounted key held, so a later claim can reuse it. */
|
|
248
|
+
releaseName(key) {
|
|
249
|
+
const name = this.registeredName.get(key);
|
|
250
|
+
if (name === undefined)
|
|
251
|
+
return;
|
|
252
|
+
this.names.forget(name);
|
|
253
|
+
this.registeredName.delete(key);
|
|
254
|
+
this.registered.delete(key);
|
|
255
|
+
}
|
|
256
|
+
}
|