@bevel-software/platform-core-backend 0.25.2 → 0.27.0
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/agent-guide/access-control.md +251 -0
- package/agent-guide/conventions.md +35 -0
- package/agent-guide/directory-structure.md +145 -0
- package/agent-guide/finding-things.md +7 -0
- package/agent-guide/html-views.md +83 -0
- package/agent-guide/introduction.md +27 -0
- package/agent-guide/new-knowledge-base.md +24 -0
- package/agent-guide/skills.md +47 -0
- package/agent-guide/tool-manuals.md +227 -0
- package/agent-guide/where-a-new-file-goes.md +36 -0
- package/dist/assets.d.ts +26 -0
- package/dist/assets.d.ts.map +1 -1
- package/dist/assets.js +35 -2
- package/dist/assets.js.map +1 -1
- package/dist/core/catalog-revision.d.ts +19 -1
- package/dist/core/catalog-revision.d.ts.map +1 -1
- package/dist/core/catalog-revision.js +14 -3
- package/dist/core/catalog-revision.js.map +1 -1
- package/dist/core/core-ports.d.ts +11 -0
- package/dist/core/core-ports.d.ts.map +1 -1
- package/dist/core/core-ports.js.map +1 -1
- package/dist/core/create-core-server.d.ts +5 -0
- package/dist/core/create-core-server.d.ts.map +1 -1
- package/dist/core/create-core-server.js +65 -3
- package/dist/core/create-core-server.js.map +1 -1
- package/dist/core/create-core-services.d.ts +35 -0
- package/dist/core/create-core-services.d.ts.map +1 -1
- package/dist/core/create-core-services.js +114 -12
- package/dist/core/create-core-services.js.map +1 -1
- package/dist/core/lifecycle.d.ts +16 -1
- package/dist/core/lifecycle.d.ts.map +1 -1
- package/dist/core/lifecycle.js +18 -1
- package/dist/core/lifecycle.js.map +1 -1
- package/dist/core-config.d.ts +21 -0
- package/dist/core-config.d.ts.map +1 -1
- package/dist/core-config.js +22 -1
- package/dist/core-config.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/modules/access/access-control.interface.d.ts +17 -0
- package/dist/modules/access/access-control.interface.d.ts.map +1 -1
- package/dist/modules/access/access-control.service.d.ts +2 -0
- package/dist/modules/access/access-control.service.d.ts.map +1 -1
- package/dist/modules/access/access-control.service.js +27 -0
- package/dist/modules/access/access-control.service.js.map +1 -1
- package/dist/modules/access/directory-sync-bot.js +1 -1
- package/dist/modules/access/directory-sync-bot.js.map +1 -1
- package/dist/modules/agent-guide/agent-guide.d.ts +145 -0
- package/dist/modules/agent-guide/agent-guide.d.ts.map +1 -0
- package/dist/modules/agent-guide/agent-guide.js +199 -0
- package/dist/modules/agent-guide/agent-guide.js.map +1 -0
- package/dist/modules/agent-guide/agent-guide.tools.d.ts +24 -0
- package/dist/modules/agent-guide/agent-guide.tools.d.ts.map +1 -0
- package/dist/modules/agent-guide/agent-guide.tools.js +100 -0
- package/dist/modules/agent-guide/agent-guide.tools.js.map +1 -0
- package/dist/modules/agent-guide/index.d.ts +4 -0
- package/dist/modules/agent-guide/index.d.ts.map +1 -0
- package/dist/modules/agent-guide/index.js +4 -0
- package/dist/modules/agent-guide/index.js.map +1 -0
- package/dist/modules/agent-instructions/agent-instructions.routes.d.ts +3 -2
- package/dist/modules/agent-instructions/agent-instructions.routes.d.ts.map +1 -1
- package/dist/modules/agent-instructions/agent-instructions.routes.js +3 -2
- package/dist/modules/agent-instructions/agent-instructions.routes.js.map +1 -1
- package/dist/modules/agent-instructions/compose.d.ts +14 -6
- package/dist/modules/agent-instructions/compose.d.ts.map +1 -1
- package/dist/modules/agent-instructions/compose.js +28 -8
- package/dist/modules/agent-instructions/compose.js.map +1 -1
- package/dist/modules/agent-instructions/index.d.ts +1 -1
- package/dist/modules/agent-instructions/index.d.ts.map +1 -1
- package/dist/modules/agent-instructions/index.js +1 -1
- package/dist/modules/agent-instructions/index.js.map +1 -1
- package/dist/modules/agent-instructions/shared-file-rules.d.ts +10 -50
- package/dist/modules/agent-instructions/shared-file-rules.d.ts.map +1 -1
- package/dist/modules/agent-instructions/shared-file-rules.js +51 -104
- package/dist/modules/agent-instructions/shared-file-rules.js.map +1 -1
- package/dist/modules/audit/agent-audit.service.d.ts +21 -2
- package/dist/modules/audit/agent-audit.service.d.ts.map +1 -1
- package/dist/modules/audit/agent-audit.service.js +43 -2
- package/dist/modules/audit/agent-audit.service.js.map +1 -1
- package/dist/modules/audit/agent-connection.routes.d.ts +34 -0
- package/dist/modules/audit/agent-connection.routes.d.ts.map +1 -0
- package/dist/modules/audit/agent-connection.routes.js +38 -0
- package/dist/modules/audit/agent-connection.routes.js.map +1 -0
- package/dist/modules/audit/audit.contract.d.ts +24 -0
- package/dist/modules/audit/audit.contract.d.ts.map +1 -1
- package/dist/modules/audit/audit.contract.js.map +1 -1
- package/dist/modules/audit/index.d.ts +1 -0
- package/dist/modules/audit/index.d.ts.map +1 -1
- package/dist/modules/audit/index.js +1 -0
- package/dist/modules/audit/index.js.map +1 -1
- package/dist/modules/auth/account.routes.d.ts.map +1 -1
- package/dist/modules/auth/account.routes.js +10 -3
- package/dist/modules/auth/account.routes.js.map +1 -1
- package/dist/modules/auth/auth.middleware.d.ts +7 -0
- package/dist/modules/auth/auth.middleware.d.ts.map +1 -1
- package/dist/modules/auth/auth.middleware.js +1 -1
- package/dist/modules/auth/auth.middleware.js.map +1 -1
- package/dist/modules/code-mode/code-mode.tool.d.ts.map +1 -1
- package/dist/modules/code-mode/code-mode.tool.js +11 -3
- package/dist/modules/code-mode/code-mode.tool.js.map +1 -1
- package/dist/modules/database/core-schema.d.ts +96 -0
- package/dist/modules/database/core-schema.d.ts.map +1 -1
- package/dist/modules/database/core-schema.js +32 -3
- package/dist/modules/database/core-schema.js.map +1 -1
- package/dist/modules/embed/account-link.service.d.ts +42 -0
- package/dist/modules/embed/account-link.service.d.ts.map +1 -0
- package/dist/modules/embed/account-link.service.js +50 -0
- package/dist/modules/embed/account-link.service.js.map +1 -0
- package/dist/modules/embed/embed-link.d.ts +58 -0
- package/dist/modules/embed/embed-link.d.ts.map +1 -0
- package/dist/modules/embed/embed-link.js +160 -0
- package/dist/modules/embed/embed-link.js.map +1 -0
- package/dist/modules/embed/embed.errors.d.ts +30 -0
- package/dist/modules/embed/embed.errors.d.ts.map +1 -0
- package/dist/modules/embed/embed.errors.js +42 -0
- package/dist/modules/embed/embed.errors.js.map +1 -0
- package/dist/modules/embed/embed.interface.d.ts +204 -0
- package/dist/modules/embed/embed.interface.d.ts.map +1 -0
- package/dist/modules/embed/embed.interface.js +2 -0
- package/dist/modules/embed/embed.interface.js.map +1 -0
- package/dist/modules/embed/embed.routes.d.ts +59 -0
- package/dist/modules/embed/embed.routes.d.ts.map +1 -0
- package/dist/modules/embed/embed.routes.js +343 -0
- package/dist/modules/embed/embed.routes.js.map +1 -0
- package/dist/modules/embed/embed.service.d.ts +169 -0
- package/dist/modules/embed/embed.service.d.ts.map +1 -0
- package/dist/modules/embed/embed.service.js +627 -0
- package/dist/modules/embed/embed.service.js.map +1 -0
- package/dist/modules/embed/embed.tools.d.ts +51 -0
- package/dist/modules/embed/embed.tools.d.ts.map +1 -0
- package/dist/modules/embed/embed.tools.js +170 -0
- package/dist/modules/embed/embed.tools.js.map +1 -0
- package/dist/modules/embed/mcp-app.d.ts +64 -0
- package/dist/modules/embed/mcp-app.d.ts.map +1 -0
- package/dist/modules/embed/mcp-app.js +147 -0
- package/dist/modules/embed/mcp-app.js.map +1 -0
- package/dist/modules/embed/mcp-app.routes.d.ts +21 -0
- package/dist/modules/embed/mcp-app.routes.d.ts.map +1 -0
- package/dist/modules/embed/mcp-app.routes.js +36 -0
- package/dist/modules/embed/mcp-app.routes.js.map +1 -0
- package/dist/modules/github-app/github-app.connection.d.ts +15 -0
- package/dist/modules/github-app/github-app.connection.d.ts.map +1 -1
- package/dist/modules/github-app/github-app.connection.js +34 -3
- package/dist/modules/github-app/github-app.connection.js.map +1 -1
- package/dist/modules/kb-fs/locking-filesystem.d.ts +65 -0
- package/dist/modules/kb-fs/locking-filesystem.d.ts.map +1 -1
- package/dist/modules/kb-fs/locking-filesystem.js +300 -0
- package/dist/modules/kb-fs/locking-filesystem.js.map +1 -1
- package/dist/modules/kb-sync/kb-sync.interface.d.ts +5 -0
- package/dist/modules/kb-sync/kb-sync.interface.d.ts.map +1 -1
- package/dist/modules/kb-sync/kb-sync.service.d.ts.map +1 -1
- package/dist/modules/kb-sync/kb-sync.service.js +6 -0
- package/dist/modules/kb-sync/kb-sync.service.js.map +1 -1
- package/dist/modules/mcp/mcp-auth.middleware.d.ts.map +1 -1
- package/dist/modules/mcp/mcp-auth.middleware.js +2 -1
- package/dist/modules/mcp/mcp-auth.middleware.js.map +1 -1
- package/dist/modules/mcp/mcp.service.d.ts +57 -3
- package/dist/modules/mcp/mcp.service.d.ts.map +1 -1
- package/dist/modules/mcp/mcp.service.js +177 -24
- package/dist/modules/mcp/mcp.service.js.map +1 -1
- package/dist/modules/mcp/oauth/bevel-oauth-provider.d.ts +24 -0
- package/dist/modules/mcp/oauth/bevel-oauth-provider.d.ts.map +1 -1
- package/dist/modules/mcp/oauth/bevel-oauth-provider.js +32 -4
- package/dist/modules/mcp/oauth/bevel-oauth-provider.js.map +1 -1
- package/dist/modules/mcp/tool-schema-guard.d.ts +105 -0
- package/dist/modules/mcp/tool-schema-guard.d.ts.map +1 -0
- package/dist/modules/mcp/tool-schema-guard.js +171 -0
- package/dist/modules/mcp/tool-schema-guard.js.map +1 -0
- package/dist/modules/onboarding/onboarding.contract.d.ts +80 -0
- package/dist/modules/onboarding/onboarding.contract.d.ts.map +1 -0
- package/dist/modules/onboarding/onboarding.contract.js +7 -0
- package/dist/modules/onboarding/onboarding.contract.js.map +1 -0
- package/dist/modules/onboarding/onboarding.routes.d.ts +18 -0
- package/dist/modules/onboarding/onboarding.routes.d.ts.map +1 -0
- package/dist/modules/onboarding/onboarding.routes.js +81 -0
- package/dist/modules/onboarding/onboarding.routes.js.map +1 -0
- package/dist/modules/onboarding/starter-pack.service.d.ts +213 -0
- package/dist/modules/onboarding/starter-pack.service.d.ts.map +1 -0
- package/dist/modules/onboarding/starter-pack.service.js +492 -0
- package/dist/modules/onboarding/starter-pack.service.js.map +1 -0
- package/dist/modules/onboarding/starter-packs.d.ts +78 -0
- package/dist/modules/onboarding/starter-packs.d.ts.map +1 -0
- package/dist/modules/onboarding/starter-packs.js +156 -0
- package/dist/modules/onboarding/starter-packs.js.map +1 -0
- package/dist/modules/plugins/index.d.ts +1 -1
- package/dist/modules/plugins/index.d.ts.map +1 -1
- package/dist/modules/plugins/index.js +1 -1
- package/dist/modules/plugins/index.js.map +1 -1
- package/dist/modules/plugins/plugin-provision.service.d.ts +19 -0
- package/dist/modules/plugins/plugin-provision.service.d.ts.map +1 -1
- package/dist/modules/plugins/plugin-provision.service.js +18 -1
- package/dist/modules/plugins/plugin-provision.service.js.map +1 -1
- package/dist/modules/plugins/plugins.routes.d.ts +0 -36
- package/dist/modules/plugins/plugins.routes.d.ts.map +1 -1
- package/dist/modules/plugins/plugins.routes.js +31 -0
- package/dist/modules/plugins/plugins.routes.js.map +1 -1
- package/dist/modules/plugins/plugins.tools.d.ts +36 -2
- package/dist/modules/plugins/plugins.tools.d.ts.map +1 -1
- package/dist/modules/plugins/plugins.tools.js +71 -14
- package/dist/modules/plugins/plugins.tools.js.map +1 -1
- package/dist/modules/settings/deployment-settings.service.d.ts +34 -7
- package/dist/modules/settings/deployment-settings.service.d.ts.map +1 -1
- package/dist/modules/settings/deployment-settings.service.js +148 -54
- package/dist/modules/settings/deployment-settings.service.js.map +1 -1
- package/dist/modules/settings/repository-source.d.ts +1 -0
- package/dist/modules/settings/repository-source.d.ts.map +1 -1
- package/dist/modules/settings/repository-source.js +3 -3
- package/dist/modules/settings/repository-source.js.map +1 -1
- package/dist/modules/settings/setup.routes.d.ts.map +1 -1
- package/dist/modules/settings/setup.routes.js +3 -6
- package/dist/modules/settings/setup.routes.js.map +1 -1
- package/dist/modules/skills/skills.tools.d.ts.map +1 -1
- package/dist/modules/skills/skills.tools.js +103 -43
- package/dist/modules/skills/skills.tools.js.map +1 -1
- package/dist/modules/tool-auth/connection-key-rejection.d.ts +10 -1
- package/dist/modules/tool-auth/connection-key-rejection.d.ts.map +1 -1
- package/dist/modules/tool-auth/connection-key-rejection.js +11 -3
- package/dist/modules/tool-auth/connection-key-rejection.js.map +1 -1
- package/dist/modules/tool-auth/external-api-key.interface.d.ts +8 -0
- package/dist/modules/tool-auth/external-api-key.interface.d.ts.map +1 -1
- package/dist/modules/tool-auth/external-api-key.service.d.ts +24 -2
- package/dist/modules/tool-auth/external-api-key.service.d.ts.map +1 -1
- package/dist/modules/tool-auth/external-api-key.service.js +59 -2
- package/dist/modules/tool-auth/external-api-key.service.js.map +1 -1
- package/dist/modules/tool-auth/tool-auth.middleware.d.ts.map +1 -1
- package/dist/modules/tool-auth/tool-auth.middleware.js +9 -4
- package/dist/modules/tool-auth/tool-auth.middleware.js.map +1 -1
- package/dist/modules/tool-helpers/index.d.ts +28 -1
- package/dist/modules/tool-helpers/index.d.ts.map +1 -1
- package/dist/modules/tool-helpers/index.js +28 -1
- package/dist/modules/tool-helpers/index.js.map +1 -1
- package/dist/modules/tool-helpers/route-argument-check.d.ts +10 -0
- package/dist/modules/tool-helpers/route-argument-check.d.ts.map +1 -0
- package/dist/modules/tool-helpers/route-argument-check.js +132 -0
- package/dist/modules/tool-helpers/route-argument-check.js.map +1 -0
- package/dist/modules/tool-helpers/route-tool-schemas.d.ts +89 -0
- package/dist/modules/tool-helpers/route-tool-schemas.d.ts.map +1 -0
- package/dist/modules/tool-helpers/route-tool-schemas.js +113 -0
- package/dist/modules/tool-helpers/route-tool-schemas.js.map +1 -0
- package/dist/modules/tool-helpers/tool-def.d.ts +71 -0
- package/dist/modules/tool-helpers/tool-def.d.ts.map +1 -1
- package/dist/modules/tool-helpers/tool-def.js +70 -6
- package/dist/modules/tool-helpers/tool-def.js.map +1 -1
- package/dist/modules/tool-helpers/tool-handler.d.ts +46 -6
- package/dist/modules/tool-helpers/tool-handler.d.ts.map +1 -1
- package/dist/modules/tool-helpers/tool-handler.js +157 -8
- package/dist/modules/tool-helpers/tool-handler.js.map +1 -1
- package/dist/modules/tool-helpers/tool.contract.d.ts +9 -0
- package/dist/modules/tool-helpers/tool.contract.d.ts.map +1 -1
- package/dist/modules/tool-helpers/tool.contract.js.map +1 -1
- package/dist/modules/tool-manuals/tool-manuals.contract.d.ts +23 -4
- package/dist/modules/tool-manuals/tool-manuals.contract.d.ts.map +1 -1
- package/dist/modules/tool-manuals/tool-manuals.contract.js.map +1 -1
- package/dist/modules/tool-manuals/tool-manuals.service.d.ts +4 -0
- package/dist/modules/tool-manuals/tool-manuals.service.d.ts.map +1 -1
- package/dist/modules/tool-manuals/tool-manuals.service.js +14 -0
- package/dist/modules/tool-manuals/tool-manuals.service.js.map +1 -1
- package/dist/modules/tool-manuals/tool-manuals.tools.d.ts +7 -0
- package/dist/modules/tool-manuals/tool-manuals.tools.d.ts.map +1 -1
- package/dist/modules/tool-manuals/tool-manuals.tools.js +77 -38
- package/dist/modules/tool-manuals/tool-manuals.tools.js.map +1 -1
- package/dist/modules/tool-registry/description-length.d.ts +20 -16
- package/dist/modules/tool-registry/description-length.d.ts.map +1 -1
- package/dist/modules/tool-registry/description-length.js +50 -30
- package/dist/modules/tool-registry/description-length.js.map +1 -1
- package/dist/modules/tool-registry/guide-first.d.ts +27 -0
- package/dist/modules/tool-registry/guide-first.d.ts.map +1 -0
- package/dist/modules/tool-registry/guide-first.js +40 -0
- package/dist/modules/tool-registry/guide-first.js.map +1 -0
- package/dist/modules/tool-registry/tool-registry.d.ts +6 -0
- package/dist/modules/tool-registry/tool-registry.d.ts.map +1 -1
- package/dist/modules/tool-registry/tool-registry.js +9 -2
- package/dist/modules/tool-registry/tool-registry.js.map +1 -1
- package/dist/modules/workflow/agent-tools/change-request-read-shape.d.ts +449 -0
- package/dist/modules/workflow/agent-tools/change-request-read-shape.d.ts.map +1 -0
- package/dist/modules/workflow/agent-tools/change-request-read-shape.js +481 -0
- package/dist/modules/workflow/agent-tools/change-request-read-shape.js.map +1 -0
- package/dist/modules/workflow/agent-tools/change-request-read.tools.d.ts +126 -0
- package/dist/modules/workflow/agent-tools/change-request-read.tools.d.ts.map +1 -0
- package/dist/modules/workflow/agent-tools/change-request-read.tools.js +611 -0
- package/dist/modules/workflow/agent-tools/change-request-read.tools.js.map +1 -0
- package/dist/modules/workflow/agent-tools/change-request-summary.d.ts +12 -1
- package/dist/modules/workflow/agent-tools/change-request-summary.d.ts.map +1 -1
- package/dist/modules/workflow/agent-tools/change-request-summary.js +5 -1
- package/dist/modules/workflow/agent-tools/change-request-summary.js.map +1 -1
- package/dist/modules/workflow/agent-tools/workflow.tools.d.ts +8 -1
- package/dist/modules/workflow/agent-tools/workflow.tools.d.ts.map +1 -1
- package/dist/modules/workflow/agent-tools/workflow.tools.js +133 -37
- package/dist/modules/workflow/agent-tools/workflow.tools.js.map +1 -1
- package/dist/modules/workflow/file-lock.service.d.ts +29 -5
- package/dist/modules/workflow/file-lock.service.d.ts.map +1 -1
- package/dist/modules/workflow/file-lock.service.js +62 -5
- package/dist/modules/workflow/file-lock.service.js.map +1 -1
- package/dist/modules/workflow/git/git.service.d.ts +282 -14
- package/dist/modules/workflow/git/git.service.d.ts.map +1 -1
- package/dist/modules/workflow/git/git.service.js +627 -126
- package/dist/modules/workflow/git/git.service.js.map +1 -1
- package/dist/modules/workflow/git/merge-commit.d.ts +73 -0
- package/dist/modules/workflow/git/merge-commit.d.ts.map +1 -0
- package/dist/modules/workflow/git/merge-commit.js +89 -0
- package/dist/modules/workflow/git/merge-commit.js.map +1 -0
- package/dist/modules/workflow/git/node-git-runner.d.ts +15 -0
- package/dist/modules/workflow/git/node-git-runner.d.ts.map +1 -1
- package/dist/modules/workflow/git/node-git-runner.js +78 -6
- package/dist/modules/workflow/git/node-git-runner.js.map +1 -1
- package/dist/modules/workflow/git/pull-request.service.d.ts +94 -1
- package/dist/modules/workflow/git/pull-request.service.d.ts.map +1 -1
- package/dist/modules/workflow/git/pull-request.service.js +332 -37
- package/dist/modules/workflow/git/pull-request.service.js.map +1 -1
- package/dist/modules/workflow/pending-commits.service.d.ts +15 -0
- package/dist/modules/workflow/pending-commits.service.d.ts.map +1 -1
- package/dist/modules/workflow/pending-commits.service.js +25 -1
- package/dist/modules/workflow/pending-commits.service.js.map +1 -1
- package/dist/modules/workflow/pending-commits.worker.d.ts +6 -1
- package/dist/modules/workflow/pending-commits.worker.d.ts.map +1 -1
- package/dist/modules/workflow/pending-commits.worker.js +23 -6
- package/dist/modules/workflow/pending-commits.worker.js.map +1 -1
- package/dist/modules/workflow/recovery-bot.js +1 -1
- package/dist/modules/workflow/recovery-bot.js.map +1 -1
- package/dist/modules/workflow/review-workflow/review-workflow.service.d.ts +35 -0
- package/dist/modules/workflow/review-workflow/review-workflow.service.d.ts.map +1 -1
- package/dist/modules/workflow/review-workflow/review-workflow.service.js +180 -13
- package/dist/modules/workflow/review-workflow/review-workflow.service.js.map +1 -1
- package/dist/modules/workflow/sanitize-error.d.ts +16 -0
- package/dist/modules/workflow/sanitize-error.d.ts.map +1 -1
- package/dist/modules/workflow/sanitize-error.js +45 -0
- package/dist/modules/workflow/sanitize-error.js.map +1 -1
- package/dist/modules/workflow/workflow.routes.d.ts +6 -2
- package/dist/modules/workflow/workflow.routes.d.ts.map +1 -1
- package/dist/modules/workflow/workflow.routes.js +7 -2
- package/dist/modules/workflow/workflow.routes.js.map +1 -1
- package/dist/modules/workflow/workflow.service.d.ts +187 -15
- package/dist/modules/workflow/workflow.service.d.ts.map +1 -1
- package/dist/modules/workflow/workflow.service.js +808 -106
- package/dist/modules/workflow/workflow.service.js.map +1 -1
- package/dist/modules/workspace/agent-download.builder.d.ts +105 -0
- package/dist/modules/workspace/agent-download.builder.d.ts.map +1 -0
- package/dist/modules/workspace/agent-download.builder.js +238 -0
- package/dist/modules/workspace/agent-download.builder.js.map +1 -0
- package/dist/modules/workspace/agent-download.routes.d.ts +77 -0
- package/dist/modules/workspace/agent-download.routes.d.ts.map +1 -0
- package/dist/modules/workspace/agent-download.routes.js +156 -0
- package/dist/modules/workspace/agent-download.routes.js.map +1 -0
- package/dist/modules/workspace/agent-download.store.d.ts +225 -0
- package/dist/modules/workspace/agent-download.store.d.ts.map +1 -0
- package/dist/modules/workspace/agent-download.store.js +423 -0
- package/dist/modules/workspace/agent-download.store.js.map +1 -0
- package/dist/modules/workspace/agent-upload.store.d.ts +10 -1
- package/dist/modules/workspace/agent-upload.store.d.ts.map +1 -1
- package/dist/modules/workspace/agent-upload.store.js +16 -6
- package/dist/modules/workspace/agent-upload.store.js.map +1 -1
- package/dist/modules/workspace/file-readers/raw-mime.d.ts +6 -0
- package/dist/modules/workspace/file-readers/raw-mime.d.ts.map +1 -0
- package/dist/modules/workspace/file-readers/raw-mime.js +38 -0
- package/dist/modules/workspace/file-readers/raw-mime.js.map +1 -0
- package/dist/modules/workspace/file-readers/text-reader.d.ts +5 -5
- package/dist/modules/workspace/file-readers/text-reader.d.ts.map +1 -1
- package/dist/modules/workspace/file-readers/text-reader.js +5 -8
- package/dist/modules/workspace/file-readers/text-reader.js.map +1 -1
- package/dist/modules/workspace/first-run.d.ts +111 -0
- package/dist/modules/workspace/first-run.d.ts.map +1 -0
- package/dist/modules/workspace/first-run.js +181 -0
- package/dist/modules/workspace/first-run.js.map +1 -0
- package/dist/modules/workspace/move-links.d.ts +92 -0
- package/dist/modules/workspace/move-links.d.ts.map +1 -0
- package/dist/modules/workspace/move-links.js +173 -0
- package/dist/modules/workspace/move-links.js.map +1 -0
- package/dist/modules/workspace/startup/steps/seed-tree.d.ts.map +1 -1
- package/dist/modules/workspace/startup/steps/seed-tree.js +24 -39
- package/dist/modules/workspace/startup/steps/seed-tree.js.map +1 -1
- package/dist/modules/workspace/startup/steps/template-files.step.d.ts +58 -52
- package/dist/modules/workspace/startup/steps/template-files.step.d.ts.map +1 -1
- package/dist/modules/workspace/startup/steps/template-files.step.js +209 -223
- package/dist/modules/workspace/startup/steps/template-files.step.js.map +1 -1
- package/dist/modules/workspace/startup/steps/template-source.d.ts +5 -3
- package/dist/modules/workspace/startup/steps/template-source.d.ts.map +1 -1
- package/dist/modules/workspace/startup/steps/template-source.js +5 -3
- package/dist/modules/workspace/startup/steps/template-source.js.map +1 -1
- package/dist/modules/workspace/workspace.routes.d.ts.map +1 -1
- package/dist/modules/workspace/workspace.routes.js +63 -22
- package/dist/modules/workspace/workspace.routes.js.map +1 -1
- package/dist/modules/workspace/workspace.service.d.ts +75 -2
- package/dist/modules/workspace/workspace.service.d.ts.map +1 -1
- package/dist/modules/workspace/workspace.service.js +197 -24
- package/dist/modules/workspace/workspace.service.js.map +1 -1
- package/dist/modules/workspace/workspace.tools.d.ts +68 -1
- package/dist/modules/workspace/workspace.tools.d.ts.map +1 -1
- package/dist/modules/workspace/workspace.tools.js +642 -71
- package/dist/modules/workspace/workspace.tools.js.map +1 -1
- package/dist/modules/write-access/write-access.d.ts.map +1 -1
- package/dist/modules/write-access/write-access.js +9 -0
- package/dist/modules/write-access/write-access.js.map +1 -1
- package/dist/shared/domain-errors.d.ts +84 -1
- package/dist/shared/domain-errors.d.ts.map +1 -1
- package/dist/shared/domain-errors.js +100 -12
- package/dist/shared/domain-errors.js.map +1 -1
- package/dist/shared/git.contract.d.ts +10 -1
- package/dist/shared/git.contract.d.ts.map +1 -1
- package/dist/shared/git.contract.js.map +1 -1
- package/dist/shared/hidden-tools.d.ts +44 -0
- package/dist/shared/hidden-tools.d.ts.map +1 -0
- package/dist/shared/hidden-tools.js +13 -0
- package/dist/shared/hidden-tools.js.map +1 -0
- package/dist/shared/utf8-text.d.ts +15 -0
- package/dist/shared/utf8-text.d.ts.map +1 -0
- package/dist/shared/utf8-text.js +20 -0
- package/dist/shared/utf8-text.js.map +1 -0
- package/dist/tenancy/static-tenant-source.d.ts +2 -1
- package/dist/tenancy/static-tenant-source.d.ts.map +1 -1
- package/dist/tenancy/static-tenant-source.js +9 -2
- package/dist/tenancy/static-tenant-source.js.map +1 -1
- package/kb-template/.bevelignore +0 -5
- package/mcp-app/page.html +349 -0
- package/migrations/0017_atlassian_account_links.sql +37 -0
- package/migrations/meta/0017_snapshot.json +2396 -0
- package/migrations/meta/_journal.json +8 -1
- package/package.json +6 -3
- package/src/__tests__/kb-layout-config.test.ts +10 -100
- package/src/__tests__/packaged-assets-ship.test.ts +66 -0
- package/src/assets.ts +38 -2
- package/src/core/__tests__/catalog-revision.test.ts +40 -0
- package/src/core/__tests__/gated-boot.test.ts +1 -0
- package/src/core/__tests__/lifecycle.test.ts +14 -0
- package/src/core/catalog-revision.ts +15 -2
- package/src/core/core-ports.ts +11 -0
- package/src/core/create-core-server.ts +78 -3
- package/src/core/create-core-services.ts +168 -10
- package/src/core/lifecycle.ts +28 -2
- package/src/core-config.ts +24 -1
- package/src/index.ts +2 -2
- package/src/modules/access/__tests__/access-control.atref-batch.test.ts +58 -0
- package/src/modules/access/__tests__/access-control.platform-restore.test.ts +8 -7
- package/src/modules/access/__tests__/access-control.service.test.ts +19 -0
- package/src/modules/access/__tests__/access-personal-plugin.test.ts +1 -18
- package/src/modules/access/access-control.interface.ts +28 -0
- package/src/modules/access/access-control.service.ts +37 -0
- package/src/modules/access/directory-sync-bot.ts +1 -1
- package/src/modules/agent-guide/__tests__/agent-guide.test.ts +386 -0
- package/src/modules/agent-guide/__tests__/agent-guide.tools.test.ts +207 -0
- package/src/modules/agent-guide/agent-guide.tools.ts +122 -0
- package/src/modules/agent-guide/agent-guide.ts +300 -0
- package/src/modules/agent-guide/index.ts +22 -0
- package/src/modules/agent-instructions/__tests__/shared-file-rules.test.ts +39 -118
- package/src/modules/agent-instructions/agent-instructions.routes.ts +3 -2
- package/src/modules/agent-instructions/compose.ts +26 -8
- package/src/modules/agent-instructions/index.ts +0 -3
- package/src/modules/agent-instructions/shared-file-rules.ts +50 -112
- package/src/modules/audit/__tests__/agent-audit.service.test.ts +64 -4
- package/src/modules/audit/__tests__/agent-connection.routes.test.ts +102 -0
- package/src/modules/audit/agent-audit.service.ts +58 -3
- package/src/modules/audit/agent-connection.routes.ts +56 -0
- package/src/modules/audit/audit.contract.ts +26 -0
- package/src/modules/audit/index.ts +1 -0
- package/src/modules/auth/__tests__/account.routes.test.ts +5 -3
- package/src/modules/auth/account.routes.ts +10 -3
- package/src/modules/auth/auth.middleware.ts +1 -1
- package/src/modules/code-mode/__tests__/code-mode.tool.test.ts +18 -2
- package/src/modules/code-mode/code-mode.tool.ts +13 -2
- package/src/modules/database/core-schema.ts +33 -3
- package/src/modules/embed/__tests__/account-links.migration.test.ts +98 -0
- package/src/modules/embed/__tests__/embed-link.test.ts +122 -0
- package/src/modules/embed/__tests__/embed.routes.test.ts +362 -0
- package/src/modules/embed/__tests__/embed.service.lock.test.ts +193 -0
- package/src/modules/embed/__tests__/embed.service.test.ts +805 -0
- package/src/modules/embed/__tests__/embed.tools.test.ts +304 -0
- package/src/modules/embed/__tests__/mcp-app.test.ts +207 -0
- package/src/modules/embed/account-link.service.ts +76 -0
- package/src/modules/embed/embed-link.ts +180 -0
- package/src/modules/embed/embed.errors.ts +43 -0
- package/src/modules/embed/embed.interface.ts +203 -0
- package/src/modules/embed/embed.routes.ts +363 -0
- package/src/modules/embed/embed.service.ts +705 -0
- package/src/modules/embed/embed.tools.ts +206 -0
- package/src/modules/embed/mcp-app.routes.ts +41 -0
- package/src/modules/embed/mcp-app.ts +173 -0
- package/src/modules/github-app/__tests__/github-app.test.ts +76 -0
- package/src/modules/github-app/github-app.connection.ts +38 -4
- package/src/modules/kb-fs/__tests__/move-with-edits.test.ts +304 -0
- package/src/modules/kb-fs/locking-filesystem.ts +287 -0
- package/src/modules/kb-sync/__tests__/kb-sync.service.test.ts +35 -0
- package/src/modules/kb-sync/kb-sync.interface.ts +2 -0
- package/src/modules/kb-sync/kb-sync.service.ts +6 -0
- package/src/modules/mcp/__tests__/bevel-oauth-provider.test.ts +68 -11
- package/src/modules/mcp/__tests__/fake-downstream-mcp-server.ts +14 -3
- package/src/modules/mcp/__tests__/mcp-proxy-helpers.test.ts +37 -2
- package/src/modules/mcp/__tests__/mcp.app.e2e.test.ts +200 -0
- package/src/modules/mcp/__tests__/mcp.e2e.test.ts +252 -0
- package/src/modules/mcp/__tests__/mcp.service.test.ts +42 -24
- package/src/modules/mcp/__tests__/tool-call-interface.e2e.test.ts +499 -0
- package/src/modules/mcp/__tests__/tool-schema-guard.test.ts +266 -0
- package/src/modules/mcp/mcp-auth.middleware.ts +2 -1
- package/src/modules/mcp/mcp.service.ts +218 -31
- package/src/modules/mcp/oauth/bevel-oauth-provider.ts +42 -4
- package/src/modules/mcp/tool-schema-guard.ts +196 -0
- package/src/modules/onboarding/__tests__/onboarding.routes.test.ts +163 -0
- package/src/modules/onboarding/__tests__/starter-pack.service.test.ts +635 -0
- package/src/modules/onboarding/__tests__/starter-packs.test.ts +169 -0
- package/src/modules/onboarding/onboarding.contract.ts +85 -0
- package/src/modules/onboarding/onboarding.routes.ts +85 -0
- package/src/modules/onboarding/starter-pack.service.ts +580 -0
- package/src/modules/onboarding/starter-packs.ts +182 -0
- package/src/modules/plugins/__tests__/plugins.tools.test.ts +177 -4
- package/src/modules/plugins/index.ts +1 -0
- package/src/modules/plugins/plugin-provision.service.ts +22 -1
- package/src/modules/plugins/plugins.routes.ts +29 -0
- package/src/modules/plugins/plugins.tools.ts +75 -15
- package/src/modules/settings/__tests__/deployment-settings.service.test.ts +176 -56
- package/src/modules/settings/__tests__/repository-source.test.ts +9 -0
- package/src/modules/settings/deployment-settings.service.ts +144 -55
- package/src/modules/settings/repository-source.ts +4 -4
- package/src/modules/settings/setup.routes.ts +3 -6
- package/src/modules/skills/__tests__/skills.tools.description.test.ts +95 -0
- package/src/modules/skills/skills.tools.ts +112 -46
- package/src/modules/tool-auth/__tests__/connection-key-rejection.test.ts +32 -0
- package/src/modules/tool-auth/__tests__/external-api-key.service.test.ts +65 -0
- package/src/modules/tool-auth/connection-key-rejection.ts +13 -3
- package/src/modules/tool-auth/external-api-key.interface.ts +9 -0
- package/src/modules/tool-auth/external-api-key.service.ts +61 -4
- package/src/modules/tool-auth/tool-auth.middleware.ts +13 -4
- package/src/modules/tool-helpers/__tests__/branch-declaration.test.ts +502 -0
- package/src/modules/tool-helpers/__tests__/route-argument-check.test.ts +337 -0
- package/src/modules/tool-helpers/index.ts +34 -1
- package/src/modules/tool-helpers/route-argument-check.ts +149 -0
- package/src/modules/tool-helpers/route-tool-schemas.ts +171 -0
- package/src/modules/tool-helpers/tool-def.ts +132 -7
- package/src/modules/tool-helpers/tool-handler.ts +196 -8
- package/src/modules/tool-helpers/tool.contract.ts +9 -0
- package/src/modules/tool-manuals/__tests__/tool-manuals.detail.route.test.ts +57 -0
- package/src/modules/tool-manuals/__tests__/tool-manuals.tools.test.ts +73 -4
- package/src/modules/tool-manuals/tool-manuals.contract.ts +24 -4
- package/src/modules/tool-manuals/tool-manuals.service.ts +17 -0
- package/src/modules/tool-manuals/tool-manuals.tools.ts +86 -38
- package/src/modules/tool-registry/__tests__/own-tool-schemas.test.ts +173 -0
- package/src/modules/tool-registry/__tests__/tool-description-length.test.ts +81 -66
- package/src/modules/tool-registry/description-length.ts +57 -32
- package/src/modules/tool-registry/guide-first.ts +41 -0
- package/src/modules/tool-registry/tool-registry.ts +9 -2
- package/src/modules/workflow/__tests__/apply-failure.test.ts +6 -1
- package/src/modules/workflow/__tests__/file-lock.service.deletion-gate.test.ts +104 -0
- package/src/modules/workflow/__tests__/pending-commits.repository-replaced.test.ts +66 -0
- package/src/modules/workflow/__tests__/pending-commits.worker.test.ts +31 -2
- package/src/modules/workflow/__tests__/preserve-roles-yaml.test.ts +110 -6
- package/src/modules/workflow/__tests__/sanitize-error.test.ts +89 -1
- package/src/modules/workflow/__tests__/workflow.routes.push-refused.test.ts +202 -0
- package/src/modules/workflow/__tests__/workflow.service.branch-in-use.test.ts +6 -6
- package/src/modules/workflow/__tests__/workflow.service.delete-branch.test.ts +1026 -0
- package/src/modules/workflow/__tests__/workflow.service.facade.test.ts +468 -10
- package/src/modules/workflow/__tests__/workflow.service.folder-proposals.test.ts +4 -0
- package/src/modules/workflow/__tests__/workflow.service.releaseLock.test.ts +5 -4
- package/src/modules/workflow/__tests__/workflow.service.update-from-target.test.ts +54 -2
- package/src/modules/workflow/agent-tools/__tests__/change-request-read-shape.test.ts +705 -0
- package/src/modules/workflow/agent-tools/__tests__/change-request-read.tools.test.ts +1554 -0
- package/src/modules/workflow/agent-tools/__tests__/workflow.tools.test.ts +150 -4
- package/src/modules/workflow/agent-tools/change-request-read-shape.ts +712 -0
- package/src/modules/workflow/agent-tools/change-request-read.tools.ts +759 -0
- package/src/modules/workflow/agent-tools/change-request-summary.ts +5 -1
- package/src/modules/workflow/agent-tools/workflow.tools.ts +137 -35
- package/src/modules/workflow/file-lock.service.ts +67 -5
- package/src/modules/workflow/git/__tests__/git.service.appliedChange.test.ts +285 -0
- package/src/modules/workflow/git/__tests__/git.service.changedFilesForPr.test.ts +124 -0
- package/src/modules/workflow/git/__tests__/git.service.deleteBranch.test.ts +164 -0
- package/src/modules/workflow/git/__tests__/git.service.mergeChangeRequest.test.ts +334 -0
- package/src/modules/workflow/git/__tests__/git.service.pull.test.ts +48 -1
- package/src/modules/workflow/git/__tests__/node-git-runner.test.ts +231 -2
- package/src/modules/workflow/git/__tests__/pull-request.service.list-fetch.test.ts +72 -2
- package/src/modules/workflow/git/__tests__/pull-request.service.placeholder.test.ts +24 -2
- package/src/modules/workflow/git/__tests__/pull-request.service.test.ts +620 -1
- package/src/modules/workflow/git/git.service.ts +714 -133
- package/src/modules/workflow/git/merge-commit.ts +88 -0
- package/src/modules/workflow/git/node-git-runner.ts +82 -7
- package/src/modules/workflow/git/pull-request.service.ts +380 -54
- package/src/modules/workflow/pending-commits.service.ts +29 -1
- package/src/modules/workflow/pending-commits.worker.ts +24 -6
- package/src/modules/workflow/recovery-bot.ts +1 -1
- package/src/modules/workflow/review-workflow/__tests__/approval-states.test.ts +7 -1
- package/src/modules/workflow/review-workflow/__tests__/merge-records-own-commit.test.ts +407 -0
- package/src/modules/workflow/review-workflow/review-workflow.service.ts +191 -12
- package/src/modules/workflow/sanitize-error.ts +50 -0
- package/src/modules/workflow/workflow.routes.ts +7 -2
- package/src/modules/workflow/workflow.service.ts +886 -112
- package/src/modules/workspace/__tests__/agent-downloads.test.ts +823 -0
- package/src/modules/workspace/__tests__/escape-sequences.routes.test.ts +4 -3
- package/src/modules/workspace/__tests__/first-run.test.ts +234 -0
- package/src/modules/workspace/__tests__/git-internals.security.test.ts +5 -2
- package/src/modules/workspace/__tests__/md-links.test.ts +353 -0
- package/src/modules/workspace/__tests__/move-links.test.ts +261 -0
- package/src/modules/workspace/__tests__/rest-tool-arguments.test.ts +219 -0
- package/src/modules/workspace/__tests__/workspace-paths-inside-the-repo.test.ts +3 -0
- package/src/modules/workspace/__tests__/workspace.routes.delete.test.ts +102 -0
- package/src/modules/workspace/__tests__/workspace.routes.download.test.ts +52 -5
- package/src/modules/workspace/__tests__/workspace.routes.folder-zip-access.test.ts +190 -0
- package/src/modules/workspace/__tests__/workspace.routes.move-platform-files.test.ts +21 -10
- package/src/modules/workspace/__tests__/workspace.service.forget-clone-races.test.ts +8 -4
- package/src/modules/workspace/__tests__/workspace.service.test.ts +50 -8
- package/src/modules/workspace/__tests__/workspace.tools.agents-file.test.ts +33 -55
- package/src/modules/workspace/__tests__/workspace.tools.branch-errors.test.ts +44 -1
- package/src/modules/workspace/__tests__/workspace.tools.test.ts +664 -34
- package/src/modules/workspace/agent-download.builder.ts +308 -0
- package/src/modules/workspace/agent-download.routes.ts +183 -0
- package/src/modules/workspace/agent-download.store.ts +533 -0
- package/src/modules/workspace/agent-upload.store.ts +23 -7
- package/src/modules/workspace/file-readers/raw-mime.ts +40 -0
- package/src/modules/workspace/file-readers/text-reader.ts +5 -8
- package/src/modules/workspace/first-run.ts +222 -0
- package/src/modules/workspace/move-links.ts +237 -0
- package/src/modules/workspace/startup/steps/__tests__/steps.test.ts +191 -489
- package/src/modules/workspace/startup/steps/seed-tree.ts +23 -38
- package/src/modules/workspace/startup/steps/template-files.step.ts +217 -249
- package/src/modules/workspace/startup/steps/template-source.ts +5 -3
- package/src/modules/workspace/workspace.routes.ts +64 -22
- package/src/modules/workspace/workspace.service.ts +202 -25
- package/src/modules/workspace/workspace.tools.ts +707 -68
- package/src/modules/write-access/__tests__/write-access.test.ts +13 -0
- package/src/modules/write-access/write-access.ts +9 -0
- package/src/shared/domain-errors.ts +123 -11
- package/src/shared/git.contract.ts +8 -1
- package/src/shared/hidden-tools.ts +45 -0
- package/src/shared/utf8-text.ts +21 -0
- package/src/tenancy/__tests__/static-tenant-source.test.ts +1 -0
- package/src/tenancy/static-tenant-source.ts +10 -2
- package/starter-packs/README.md +103 -0
- package/starter-packs/engineering/KnowledgeBase/About us.md +9 -0
- package/starter-packs/engineering/KnowledgeBase/Architecture.md +9 -0
- package/starter-packs/engineering/KnowledgeBase/Glossary.md +9 -0
- package/starter-packs/engineering/KnowledgeBase/How we ship.md +9 -0
- package/starter-packs/engineering/Plugins/engineering-starter/LICENSE +21 -0
- package/starter-packs/engineering/Plugins/engineering-starter/SOURCE.md +20 -0
- package/starter-packs/engineering/Plugins/engineering-starter/access.md +19 -0
- package/starter-packs/engineering/Plugins/engineering-starter/plugin.json +10 -0
- package/starter-packs/engineering/Plugins/engineering-starter/skills/office-hours/SKILL.md +171 -0
- package/starter-packs/engineering/Plugins/engineering-starter/skills/office-hours/sections/phase-2a-startup-diagnostic.md +157 -0
- package/starter-packs/engineering/Plugins/engineering-starter/skills/office-hours/sections/phase-2b-builder-brainstorm.md +39 -0
- package/starter-packs/engineering/Plugins/engineering-starter/skills/plan-ceo-review/SKILL.md +144 -0
- package/starter-packs/engineering/Plugins/engineering-starter/skills/plan-eng-review/SKILL.md +144 -0
- package/starter-packs/engineering/Plugins/engineering-starter/skills/review/SKILL.md +80 -0
- package/starter-packs/engineering/Plugins/engineering-starter/skills/review/checklist.md +184 -0
- package/starter-packs/engineering/pack.yaml +11 -0
- package/starter-packs/general/KnowledgeBase/About us.md +9 -0
- package/starter-packs/general/KnowledgeBase/Glossary.md +9 -0
- package/starter-packs/general/KnowledgeBase/How we work.md +9 -0
- package/starter-packs/general/Plugins/general-starter/LICENSE +202 -0
- package/starter-packs/general/Plugins/general-starter/SOURCE.md +10 -0
- package/starter-packs/general/Plugins/general-starter/access.md +19 -0
- package/starter-packs/general/Plugins/general-starter/plugin.json +10 -0
- package/starter-packs/general/Plugins/general-starter/skills/memory-management/SKILL.md +332 -0
- package/starter-packs/general/Plugins/general-starter/skills/productivity-start/SKILL.md +163 -0
- package/starter-packs/general/Plugins/general-starter/skills/productivity-update/SKILL.md +167 -0
- package/starter-packs/general/Plugins/general-starter/skills/task-management/SKILL.md +83 -0
- package/starter-packs/general/pack.yaml +10 -0
- package/starter-packs/operations/KnowledgeBase/Glossary.md +9 -0
- package/starter-packs/operations/KnowledgeBase/How we work.md +9 -0
- package/starter-packs/operations/KnowledgeBase/Processes.md +9 -0
- package/starter-packs/operations/KnowledgeBase/Tools we use.md +9 -0
- package/starter-packs/operations/KnowledgeBase/Vendors.md +9 -0
- package/starter-packs/operations/Plugins/operations-starter/LICENSE +202 -0
- package/starter-packs/operations/Plugins/operations-starter/SOURCE.md +10 -0
- package/starter-packs/operations/Plugins/operations-starter/access.md +19 -0
- package/starter-packs/operations/Plugins/operations-starter/plugin.json +10 -0
- package/starter-packs/operations/Plugins/operations-starter/skills/capacity-plan/SKILL.md +111 -0
- package/starter-packs/operations/Plugins/operations-starter/skills/change-request/SKILL.md +119 -0
- package/starter-packs/operations/Plugins/operations-starter/skills/compliance-tracking/SKILL.md +44 -0
- package/starter-packs/operations/Plugins/operations-starter/skills/process-doc/SKILL.md +80 -0
- package/starter-packs/operations/Plugins/operations-starter/skills/process-optimization/SKILL.md +39 -0
- package/starter-packs/operations/Plugins/operations-starter/skills/risk-assessment/SKILL.md +40 -0
- package/starter-packs/operations/Plugins/operations-starter/skills/runbook/SKILL.md +85 -0
- package/starter-packs/operations/Plugins/operations-starter/skills/status-report/SKILL.md +75 -0
- package/starter-packs/operations/Plugins/operations-starter/skills/vendor-review/SKILL.md +102 -0
- package/starter-packs/operations/pack.yaml +12 -0
- package/starter-packs/sales/KnowledgeBase/About us.md +9 -0
- package/starter-packs/sales/KnowledgeBase/Customers.md +9 -0
- package/starter-packs/sales/KnowledgeBase/Glossary.md +9 -0
- package/starter-packs/sales/KnowledgeBase/How we sell.md +9 -0
- package/starter-packs/sales/KnowledgeBase/Objections.md +9 -0
- package/starter-packs/sales/KnowledgeBase/Pricing.md +9 -0
- package/starter-packs/sales/Plugins/sales-starter/LICENSE +202 -0
- package/starter-packs/sales/Plugins/sales-starter/SOURCE.md +10 -0
- package/starter-packs/sales/Plugins/sales-starter/access.md +19 -0
- package/starter-packs/sales/Plugins/sales-starter/plugin.json +10 -0
- package/starter-packs/sales/Plugins/sales-starter/skills/account-context/SKILL.md +94 -0
- package/starter-packs/sales/Plugins/sales-starter/skills/account-plan/SKILL.md +95 -0
- package/starter-packs/sales/Plugins/sales-starter/skills/account-research/SKILL.md +99 -0
- package/starter-packs/sales/Plugins/sales-starter/skills/account-tiering/SKILL.md +101 -0
- package/starter-packs/sales/Plugins/sales-starter/skills/call-prep/SKILL.md +111 -0
- package/starter-packs/sales/Plugins/sales-starter/skills/call-summary/SKILL.md +111 -0
- package/starter-packs/sales/Plugins/sales-starter/skills/close-plan/SKILL.md +106 -0
- package/starter-packs/sales/Plugins/sales-starter/skills/competitive-intelligence/SKILL.md +102 -0
- package/starter-packs/sales/Plugins/sales-starter/skills/create-an-asset/SKILL.md +105 -0
- package/starter-packs/sales/Plugins/sales-starter/skills/crm-hygiene-check/SKILL.md +103 -0
- package/starter-packs/sales/Plugins/sales-starter/skills/customer-health/SKILL.md +108 -0
- package/starter-packs/sales/Plugins/sales-starter/skills/customer-voice/SKILL.md +94 -0
- package/starter-packs/sales/Plugins/sales-starter/skills/daily-briefing/SKILL.md +61 -0
- package/starter-packs/sales/Plugins/sales-starter/skills/deal-advance-gap/SKILL.md +102 -0
- package/starter-packs/sales/Plugins/sales-starter/skills/deal-review/SKILL.md +105 -0
- package/starter-packs/sales/Plugins/sales-starter/skills/deal-signals/SKILL.md +96 -0
- package/starter-packs/sales/Plugins/sales-starter/skills/deal-slip-scenario/SKILL.md +104 -0
- package/starter-packs/sales/Plugins/sales-starter/skills/draft-outreach/SKILL.md +116 -0
- package/starter-packs/sales/Plugins/sales-starter/skills/end-of-day/SKILL.md +114 -0
- package/starter-packs/sales/Plugins/sales-starter/skills/expansion-whitespace/SKILL.md +97 -0
- package/starter-packs/sales/Plugins/sales-starter/skills/forecast/SKILL.md +100 -0
- package/starter-packs/sales/Plugins/sales-starter/skills/handle-objection/SKILL.md +93 -0
- package/starter-packs/sales/Plugins/sales-starter/skills/inbox-sweep/SKILL.md +114 -0
- package/starter-packs/sales/Plugins/sales-starter/skills/lead-triage/SKILL.md +106 -0
- package/starter-packs/sales/Plugins/sales-starter/skills/log-activity/SKILL.md +111 -0
- package/starter-packs/sales/Plugins/sales-starter/skills/pipeline-review/SKILL.md +97 -0
- package/starter-packs/sales/Plugins/sales-starter/skills/renewal-radar/SKILL.md +95 -0
- package/starter-packs/sales/Plugins/sales-starter/skills/rep-context/SKILL.md +90 -0
- package/starter-packs/sales/Plugins/sales-starter/skills/route-lead/SKILL.md +111 -0
- package/starter-packs/sales/Plugins/sales-starter/skills/sales-setup/SKILL.md +200 -0
- package/starter-packs/sales/Plugins/sales-starter/skills/schedule-meeting/SKILL.md +99 -0
- package/starter-packs/sales/Plugins/sales-starter/skills/stakeholder-map/SKILL.md +107 -0
- package/starter-packs/sales/Plugins/sales-starter/skills/team-pipeline/SKILL.md +105 -0
- package/starter-packs/sales/Plugins/sales-starter/skills/update-opportunity/SKILL.md +112 -0
- package/starter-packs/sales/Plugins/sales-starter/skills/weekly-wrap/SKILL.md +90 -0
- package/starter-packs/sales/Plugins/sales-starter/skills/win-loss-review/SKILL.md +88 -0
- package/starter-packs/sales/pack.yaml +13 -0
- package/starter-packs/support/KnowledgeBase/Escalations.md +9 -0
- package/starter-packs/support/KnowledgeBase/Glossary.md +9 -0
- package/starter-packs/support/KnowledgeBase/Known issues.md +9 -0
- package/starter-packs/support/KnowledgeBase/Products.md +9 -0
- package/starter-packs/support/KnowledgeBase/Tone of voice.md +9 -0
- package/starter-packs/support/Plugins/support-starter/LICENSE +202 -0
- package/starter-packs/support/Plugins/support-starter/SOURCE.md +10 -0
- package/starter-packs/support/Plugins/support-starter/access.md +19 -0
- package/starter-packs/support/Plugins/support-starter/plugin.json +10 -0
- package/starter-packs/support/Plugins/support-starter/skills/customer-escalation/SKILL.md +246 -0
- package/starter-packs/support/Plugins/support-starter/skills/customer-research/SKILL.md +250 -0
- package/starter-packs/support/Plugins/support-starter/skills/draft-response/SKILL.md +416 -0
- package/starter-packs/support/Plugins/support-starter/skills/kb-article/SKILL.md +350 -0
- package/starter-packs/support/Plugins/support-starter/skills/ticket-triage/SKILL.md +273 -0
- package/starter-packs/support/pack.yaml +12 -0
- package/kb-template/AGENTS.md +0 -730
|
@@ -8,6 +8,8 @@ import {
|
|
|
8
8
|
ListToolsRequestSchema,
|
|
9
9
|
ListPromptsRequestSchema,
|
|
10
10
|
GetPromptRequestSchema,
|
|
11
|
+
ListResourcesRequestSchema,
|
|
12
|
+
ReadResourceRequestSchema,
|
|
11
13
|
McpError,
|
|
12
14
|
ErrorCode,
|
|
13
15
|
isInitializeRequest,
|
|
@@ -39,6 +41,9 @@ import {
|
|
|
39
41
|
retiredToolMessage,
|
|
40
42
|
needsAuthorizationResult,
|
|
41
43
|
skillPromptText,
|
|
44
|
+
toListedResource,
|
|
45
|
+
toReadResourceResult,
|
|
46
|
+
type McpAppManifest,
|
|
42
47
|
type ProxiedTool,
|
|
43
48
|
type SkillSummary,
|
|
44
49
|
type LoadedSkill,
|
|
@@ -53,6 +58,7 @@ import {
|
|
|
53
58
|
import { EXTERNAL_KB_MANUAL_NAME } from '../tool-manuals/tool-manuals.contract.js';
|
|
54
59
|
import type { IToolManualService } from '../tool-manuals/tool-manuals.contract.js';
|
|
55
60
|
import type { SpillStore } from '../workspace/spill-store.js';
|
|
61
|
+
import type { HiddenToolSource } from '../../shared/hidden-tools.js';
|
|
56
62
|
import { seedBevelHostedManualVars } from '../../shared/utcp-namespace.js';
|
|
57
63
|
import type { InternalTokenService } from '../tool-auth/internal-token.service.js';
|
|
58
64
|
import type { IAgentEventRecorder } from '../audit/audit.contract.js';
|
|
@@ -60,16 +66,17 @@ import { RequestAudit } from '../audit/request-audit.js';
|
|
|
60
66
|
import { ManualFailureMemo } from './manual-failure-memo.js';
|
|
61
67
|
import { DownstreamPool, POOL_KEY_SEPARATOR, type DownstreamPoolOptions, type Lease } from './downstream-pool.js';
|
|
62
68
|
import { SurfaceLogThrottle } from './surface-log-throttle.js';
|
|
69
|
+
import { ToolSchemaGuard, type ScreenedHiddenTool } from './tool-schema-guard.js';
|
|
63
70
|
import { DownstreamRefreshGuard, isDownstreamTokenRejection } from './downstream-token-refresh.js';
|
|
64
71
|
import { printable } from '../../shared/printable.js';
|
|
65
72
|
import {
|
|
66
73
|
composeAgentInstructions,
|
|
67
74
|
prefixToolDescription,
|
|
68
75
|
PREFIXED_TOOLS,
|
|
69
|
-
sharedRulesPointer,
|
|
70
76
|
type AgentPreambleReader,
|
|
71
77
|
type ComposedAgentInstructions,
|
|
72
78
|
} from '../agent-instructions/index.js';
|
|
79
|
+
import { guideFirstDescription } from '../tool-registry/guide-first.js';
|
|
73
80
|
|
|
74
81
|
/**
|
|
75
82
|
* Configuration for the loopback proxy. `loopbackBaseUrl` is the backend's own
|
|
@@ -95,8 +102,8 @@ export interface McpProxyOptions {
|
|
|
95
102
|
readAgentPreamble?: AgentPreambleReader;
|
|
96
103
|
/**
|
|
97
104
|
* The layout in effect, read per request: the shared file rules name the
|
|
98
|
-
*
|
|
99
|
-
*
|
|
105
|
+
* guide by the name a deployment saved for it, and the setup save applies
|
|
106
|
+
* a layout without a restart. A GETTER, so nothing snapshots the
|
|
100
107
|
* pre-setup default. Absent, the rules name `AGENTS.md`.
|
|
101
108
|
*/
|
|
102
109
|
kbLayout?: () => KbLayout;
|
|
@@ -166,6 +173,14 @@ interface RequestSurface {
|
|
|
166
173
|
* They differ only when the name holds a non-word character (`my-server`).
|
|
167
174
|
*/
|
|
168
175
|
catalogNames: ReadonlyMap<string, string>;
|
|
176
|
+
/**
|
|
177
|
+
* The tools this request's load took OFF the surface for an invalid schema,
|
|
178
|
+
* by the name an agent would have called them by. Carried on the surface
|
|
179
|
+
* rather than read back out of the guard: it is this caller's own load, so a
|
|
180
|
+
* call answered from it cannot answer about a schema some other caller's
|
|
181
|
+
* connection was shown.
|
|
182
|
+
*/
|
|
183
|
+
hidden: ReadonlyMap<string, ScreenedHiddenTool>;
|
|
169
184
|
}
|
|
170
185
|
|
|
171
186
|
/** A manual off the surface for want of a sign-in — see {@link RequestSurface.unavailable}. */
|
|
@@ -273,6 +288,15 @@ export class McpService {
|
|
|
273
288
|
*/
|
|
274
289
|
private readonly knownDownstreamTools = new Map<string, { definition: string; tools: UtcpTool[] }>();
|
|
275
290
|
|
|
291
|
+
/**
|
|
292
|
+
* The JSON Schema check on connected tools, and the memory of what it found.
|
|
293
|
+
* Process-wide rather than per request, because a schema's validity is a
|
|
294
|
+
* property of the server and not of the caller — and because the point of
|
|
295
|
+
* remembering is that the check runs when a server's tools are loaded, not
|
|
296
|
+
* once per request and never on a tool call. See {@link ToolSchemaGuard}.
|
|
297
|
+
*/
|
|
298
|
+
private readonly toolSchemas = new ToolSchemaGuard();
|
|
299
|
+
|
|
276
300
|
// The downstream connection pool for `mcp` manuals — see the class doc.
|
|
277
301
|
private readonly downstream: DownstreamPool<PooledDownstream>;
|
|
278
302
|
|
|
@@ -296,6 +320,18 @@ export class McpService {
|
|
|
296
320
|
// of a request that arrived with a key or an agent connection goes
|
|
297
321
|
// through it. Optional like the others; without it nothing is recorded.
|
|
298
322
|
private readonly auditRecorder?: IAgentEventRecorder,
|
|
323
|
+
/**
|
|
324
|
+
* The MCP Apps this deployment serves — the views a tool's `_meta` names
|
|
325
|
+
* and `resources/list` / `resources/read` answer for.
|
|
326
|
+
*
|
|
327
|
+
* Optional, and absence is a real state rather than a test convenience:
|
|
328
|
+
* with no manifest the endpoint declares no `resources` capability and
|
|
329
|
+
* every tool is listed exactly as before, which is also what a
|
|
330
|
+
* deployment whose packaged view could not be read must look like. A
|
|
331
|
+
* `resourceUri` advertised without a resource behind it would have a
|
|
332
|
+
* host preload a failure and show an empty frame.
|
|
333
|
+
*/
|
|
334
|
+
private readonly mcpApps?: { manifest(): Promise<McpAppManifest> },
|
|
299
335
|
) {
|
|
300
336
|
this.downstream = new DownstreamPool<PooledDownstream>({
|
|
301
337
|
...opts.downstreamPool,
|
|
@@ -402,10 +438,24 @@ export class McpService {
|
|
|
402
438
|
}));
|
|
403
439
|
|
|
404
440
|
const initializing = (Array.isArray(messages) ? messages : [messages]).some((m) => isInitializeRequest(m));
|
|
441
|
+
// The deployment's MCP Apps, read once per request. Declaring the
|
|
442
|
+
// `resources` capability is what permits the two handlers below, and a
|
|
443
|
+
// deployment with no view must not declare it — a client would then list
|
|
444
|
+
// resources and be told the method does not exist.
|
|
445
|
+
const apps = this.mcpApps ? await this.mcpApps.manifest().catch(() => null) : null;
|
|
446
|
+
const servesApps = (apps?.resources.length ?? 0) > 0;
|
|
405
447
|
const server = new Server(
|
|
406
448
|
{ name: 'bevel-mcp', version: '0.1.0' },
|
|
407
449
|
{
|
|
408
|
-
capabilities: {
|
|
450
|
+
capabilities: {
|
|
451
|
+
tools: {},
|
|
452
|
+
prompts: {},
|
|
453
|
+
// Resources exist here for ONE purpose: serving the MCP App views
|
|
454
|
+
// the tools carry. The knowledge base's own files are not
|
|
455
|
+
// resources — they are what the file TOOLS read, under the access
|
|
456
|
+
// rules, which a resource listing has no way to express.
|
|
457
|
+
...(servesApps ? { resources: {} } : {}),
|
|
458
|
+
},
|
|
409
459
|
// `instructions` rides the initialize result; clients that honour it
|
|
410
460
|
// place the text in the model's system prompt without the model acting.
|
|
411
461
|
...(initializing ? { instructions: (await agentInstructions()).instructions } : {}),
|
|
@@ -445,7 +495,12 @@ export class McpService {
|
|
|
445
495
|
const direct: McpTool[] = [];
|
|
446
496
|
const examplePool: ProxiedTool[] = [];
|
|
447
497
|
for (const t of listed) {
|
|
448
|
-
|
|
498
|
+
// The MCP App view this tool's result renders in, by tool name. Not
|
|
499
|
+
// part of the UTCP manual the tool was discovered from (UTCP has no
|
|
500
|
+
// place for it), so it is joined on here — the one point where a
|
|
501
|
+
// discovered tool becomes a listing entry.
|
|
502
|
+
const ui = apps && Object.hasOwn(apps.tools, t.mcpName) ? apps.tools[t.mcpName] : undefined;
|
|
503
|
+
const entry = toListedTool(ui ? { ...t, ui } : t); // logs its own reason on a name/schema drop
|
|
449
504
|
if (!entry) {
|
|
450
505
|
dropped.push(t.mcpName);
|
|
451
506
|
continue;
|
|
@@ -486,14 +541,17 @@ export class McpService {
|
|
|
486
541
|
// different name, and one fixed example is necessarily wrong on one of the
|
|
487
542
|
// two surfaces.
|
|
488
543
|
//
|
|
489
|
-
//
|
|
490
|
-
//
|
|
491
|
-
//
|
|
492
|
-
// `
|
|
493
|
-
//
|
|
544
|
+
// What a chain does with a failure, a large result or an image is
|
|
545
|
+
// stated once, in the shared rules — in the guide and in the handshake
|
|
546
|
+
// instructions — and not on the chain itself (an EMPTY pointer is how
|
|
547
|
+
// `mcp-core` is told the rules are served elsewhere). Like every tool of
|
|
548
|
+
// the platform's own, each meta-tool opens with the one sentence saying
|
|
549
|
+
// what to do before any of them, which is where those rules are. The
|
|
550
|
+
// registry puts the sentence on the tools it lists; the meta-tools are
|
|
551
|
+
// built here, so here it is.
|
|
494
552
|
const metaTools = codeModeMetaTools(EXTERNAL_KB_MANUAL_NAME, examplePool, {
|
|
495
|
-
sharedRulesPointer:
|
|
496
|
-
});
|
|
553
|
+
sharedRulesPointer: '',
|
|
554
|
+
}).map((tool) => ({ ...tool, description: guideFirstDescription(tool.description) }));
|
|
497
555
|
// Log only when a tool was dropped (name/schema/duplicate) — that's the
|
|
498
556
|
// anomaly worth surfacing, since a downstream client would otherwise hide
|
|
499
557
|
// it by rejecting the whole response.
|
|
@@ -509,8 +567,27 @@ export class McpService {
|
|
|
509
567
|
};
|
|
510
568
|
});
|
|
511
569
|
|
|
570
|
+
// The MCP App views. Registered only when this deployment serves one, so
|
|
571
|
+
// the handlers and the declared capability agree.
|
|
572
|
+
if (servesApps && apps) {
|
|
573
|
+
server.setRequestHandler(ListResourcesRequestSchema, async () => ({
|
|
574
|
+
resources: apps.resources.map((r) => toListedResource(r)),
|
|
575
|
+
}));
|
|
576
|
+
server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
|
|
577
|
+
const resource = apps.resources.find((r) => r.uri === request.params.uri);
|
|
578
|
+
if (!resource) {
|
|
579
|
+
throw new McpError(
|
|
580
|
+
ErrorCode.InvalidParams,
|
|
581
|
+
`No resource at ${request.params.uri}. This endpoint serves the MCP App views its tools ` +
|
|
582
|
+
`name and nothing else: ${apps.resources.map((r) => r.uri).join(', ')}.`,
|
|
583
|
+
);
|
|
584
|
+
}
|
|
585
|
+
return toReadResourceResult(resource);
|
|
586
|
+
});
|
|
587
|
+
}
|
|
588
|
+
|
|
512
589
|
server.setRequestHandler(CallToolRequestSchema, async (request, extra) => {
|
|
513
|
-
const { client, tools, unavailable, catalogNames } = await requestSurface();
|
|
590
|
+
const { client, tools, unavailable, catalogNames, hidden: hiddenTools } = await requestSurface();
|
|
514
591
|
const toolName = request.params.name;
|
|
515
592
|
const args = request.params.arguments ?? {};
|
|
516
593
|
if (META_TOOL_NAMES.has(toolName)) {
|
|
@@ -551,6 +628,24 @@ export class McpService {
|
|
|
551
628
|
};
|
|
552
629
|
const proxied = tools.find((t) => t.mcpName === toolName);
|
|
553
630
|
if (!proxied) {
|
|
631
|
+
// A tool this process hid for an invalid schema: say that, rather than
|
|
632
|
+
// "Unknown tool" about a tool the agent has every reason to think
|
|
633
|
+
// exists. The place and the reason are deliberately NOT here — they are
|
|
634
|
+
// for the people who manage the server, who are the only ones who can
|
|
635
|
+
// act on them.
|
|
636
|
+
const hidden = hiddenTools.get(toolName);
|
|
637
|
+
if (hidden) {
|
|
638
|
+
// The UTCP name, as every other audit path records a tool: the
|
|
639
|
+
// flattened agent name loses the server segment of a multi-segment
|
|
640
|
+
// `<manual>.<server>.<tool>`, and an audit trail that names a
|
|
641
|
+
// different tool than the rest of the trail is worse than none.
|
|
642
|
+
if (audit) await audit.denied(hidden.utcpName, args);
|
|
643
|
+
return toolError(
|
|
644
|
+
`The "${toolName}" tool is hidden from agents because its schema is invalid, so it cannot be ` +
|
|
645
|
+
`called. The people who manage its server can see the place in the schema and the reason, on ` +
|
|
646
|
+
`the tool's page in Hexis and through \`list_tool_setup\`.`,
|
|
647
|
+
);
|
|
648
|
+
}
|
|
554
649
|
// Not on the surface — but if the name belongs to a manual that is off
|
|
555
650
|
// it only because this caller's sign-in is gone (and nothing in this
|
|
556
651
|
// process has seen its tools yet), the honest answer is the sign-in
|
|
@@ -570,7 +665,10 @@ export class McpService {
|
|
|
570
665
|
if (audit) await audit.denied(proxied.utcpName, args);
|
|
571
666
|
return needsAuth;
|
|
572
667
|
}
|
|
573
|
-
|
|
668
|
+
// A tool with an MCP App view answers structured content too — the
|
|
669
|
+
// view reads its fields from there.
|
|
670
|
+
const structured = apps !== null && Object.hasOwn(apps.tools, proxied.mcpName);
|
|
671
|
+
const run = () => this.dispatch(client, proxied, request, extra, structured);
|
|
574
672
|
return audit ? audit.call(proxied.utcpName, args, run, isErrorResult) : run();
|
|
575
673
|
});
|
|
576
674
|
|
|
@@ -626,7 +724,7 @@ export class McpService {
|
|
|
626
724
|
const manuals = await this.fetchManualTemplates(loopbackBearer);
|
|
627
725
|
const catalogMs = performance.now() - started;
|
|
628
726
|
const client = await this.buildClient(loopbackBearer, userId, manuals);
|
|
629
|
-
const { tools, unavailable, catalogNames } = await this.discoverTools(client, manuals, userId);
|
|
727
|
+
const { tools, unavailable, catalogNames, hidden } = await this.discoverTools(client, manuals, userId);
|
|
630
728
|
const totalMs = performance.now() - started;
|
|
631
729
|
// Per user: on a shape change or once per interval, never per request —
|
|
632
730
|
// see SurfaceLogThrottle for why both halves matter.
|
|
@@ -641,7 +739,7 @@ export class McpService {
|
|
|
641
739
|
(decision.suppressed > 0 ? ` [+${decision.suppressed} identical rebuild(s) since last line]` : ''),
|
|
642
740
|
);
|
|
643
741
|
}
|
|
644
|
-
return { client, tools, unavailable, catalogNames };
|
|
742
|
+
return { client, tools, unavailable, catalogNames, hidden };
|
|
645
743
|
}
|
|
646
744
|
|
|
647
745
|
/**
|
|
@@ -798,13 +896,37 @@ export class McpService {
|
|
|
798
896
|
client: CodeModeUtcpClient,
|
|
799
897
|
manuals: CallTemplate[],
|
|
800
898
|
userId: string,
|
|
801
|
-
): Promise<{
|
|
899
|
+
): Promise<{
|
|
900
|
+
tools: ProxiedTool[];
|
|
901
|
+
unavailable: UnavailableManual[];
|
|
902
|
+
catalogNames: Map<string, string>;
|
|
903
|
+
hidden: Map<string, ScreenedHiddenTool>;
|
|
904
|
+
}> {
|
|
802
905
|
const routes = new Map<string, DownstreamRoute>();
|
|
803
906
|
const unavailable: UnavailableManual[] = [];
|
|
907
|
+
// Taken BEFORE a single manual is registered, so it ranks this load by the
|
|
908
|
+
// freshness of what it is about to read — see ToolSchemaGuard.beginLoad.
|
|
909
|
+
const loadId = this.toolSchemas.beginLoad();
|
|
804
910
|
const catalogNames = new Map<string, string>();
|
|
805
911
|
for (const m of manuals) {
|
|
806
912
|
if (m.call_template_type === 'mcp') catalogNames.set(utcpManualName(m), String(m.name));
|
|
807
913
|
}
|
|
914
|
+
// Every manual's catalog name, which is how the owner-facing surfaces know
|
|
915
|
+
// it. `catalogNames` above is the credential catalog's map and covers `mcp`
|
|
916
|
+
// manuals only; the schema check is about the tools of every connected
|
|
917
|
+
// server, so it needs the whole list. Taken HERE, before registration:
|
|
918
|
+
// registering a manual renames the template in place, so `m.name` read
|
|
919
|
+
// afterwards is the rewritten identifier and `my-server` would be recorded
|
|
920
|
+
// as `my_server` — a name no tool page ever looks up.
|
|
921
|
+
// Keyed by the rewritten name, which two manuals can share (the collision
|
|
922
|
+
// handled below): the KB manual's entry is the one that stays, since it is
|
|
923
|
+
// the one that is registered when a `.tool` collides with it.
|
|
924
|
+
const manualCatalogNames = new Map<string, string>();
|
|
925
|
+
for (const m of manuals) {
|
|
926
|
+
const rewritten = utcpManualName(m);
|
|
927
|
+
if (manualCatalogNames.get(rewritten) === EXTERNAL_KB_MANUAL_NAME) continue;
|
|
928
|
+
manualCatalogNames.set(rewritten, String(m.name));
|
|
929
|
+
}
|
|
808
930
|
// The shared layer rewrites every manual name (`[^\w]` → `_`) and tools
|
|
809
931
|
// route by the rewritten prefix, so two manuals whose names rewrite to one
|
|
810
932
|
// identifier would silently share it. Sequential registration used to
|
|
@@ -884,11 +1006,65 @@ export class McpService {
|
|
|
884
1006
|
if (kbFailure && !kbFailure.ok) throw new Error(`Bevel tool discovery failed: ${kbFailure.error}`);
|
|
885
1007
|
if (routes.size > 0) routeToDownstream(client, routes);
|
|
886
1008
|
const utcpTools = await client.getTools();
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
1009
|
+
const flattened = utcpTools.map((tool: UtcpTool) => flattenManualTool(tool, EXTERNAL_KB_MANUAL_NAME));
|
|
1010
|
+
const { tools, hidden } = await this.hideInvalidSchemas(client, flattened, manualCatalogNames, userId, loadId);
|
|
1011
|
+
return { tools, unavailable, catalogNames, hidden };
|
|
1012
|
+
}
|
|
1013
|
+
|
|
1014
|
+
/**
|
|
1015
|
+
* Check the input schema of every tool the servers just advertised, and take
|
|
1016
|
+
* the invalid ones OFF the client's tool repository.
|
|
1017
|
+
*
|
|
1018
|
+
* The repository is the single place `tools/list`, `list_tools`/`tools_info`
|
|
1019
|
+
* and the TypeScript interfaces `call_tool_chain` generates are all built
|
|
1020
|
+
* from, so removing a tool here removes it from all three — which is what
|
|
1021
|
+
* "not offered to agents" has to mean. Its siblings are untouched: the check
|
|
1022
|
+
* is per tool, so one bad schema costs that tool and nothing else of the
|
|
1023
|
+
* server.
|
|
1024
|
+
*
|
|
1025
|
+
* A client would otherwise drop such a tool itself, silently, and the agent
|
|
1026
|
+
* would be left without it and without a reason. Hidden here, the reason
|
|
1027
|
+
* reaches the people who manage the server (see {@link ToolSchemaGuard}).
|
|
1028
|
+
*/
|
|
1029
|
+
private async hideInvalidSchemas(
|
|
1030
|
+
client: CodeModeUtcpClient,
|
|
1031
|
+
tools: ProxiedTool[],
|
|
1032
|
+
catalogNames: ReadonlyMap<string, string>,
|
|
1033
|
+
userId: string,
|
|
1034
|
+
loadId: number,
|
|
1035
|
+
): Promise<{ tools: ProxiedTool[]; hidden: Map<string, ScreenedHiddenTool> }> {
|
|
1036
|
+
const byManual = new Map<string, ProxiedTool[]>();
|
|
1037
|
+
// EVERY manual of this surface is screened, including the ones that
|
|
1038
|
+
// advertised nothing. A server that removed its last invalid tool, and one
|
|
1039
|
+
// whose tools never loaded at all (a sign-in that has gone), both come
|
|
1040
|
+
// through here with an empty group — and an empty group is what clears the
|
|
1041
|
+
// marker. Screening only the groups that have tools would leave the tool
|
|
1042
|
+
// page, `list_tool_setup` and the hidden-tool answer on a call all
|
|
1043
|
+
// reporting a defect this process can no longer see.
|
|
1044
|
+
for (const manual of catalogNames.values()) byManual.set(manual, []);
|
|
1045
|
+
for (const tool of tools) {
|
|
1046
|
+
const manual = catalogNames.get(tool.manualName) ?? tool.manualName;
|
|
1047
|
+
byManual.set(manual, [...(byManual.get(manual) ?? []), tool]);
|
|
1048
|
+
}
|
|
1049
|
+
const found = this.toolSchemas.screen(userId, loadId, byManual);
|
|
1050
|
+
const hidden = new Map<string, ScreenedHiddenTool>();
|
|
1051
|
+
for (const tool of found.values()) hidden.set(tool.name, tool);
|
|
1052
|
+
if (found.size === 0) return { tools, hidden };
|
|
1053
|
+
for (const utcpName of found.keys()) {
|
|
1054
|
+
await client.config.tool_repository.removeTool(utcpName);
|
|
1055
|
+
}
|
|
1056
|
+
// Logged every time rather than throttled: a hidden tool is the one thing
|
|
1057
|
+
// about this surface that a person has to act on, and it is rare.
|
|
1058
|
+
log.warn(
|
|
1059
|
+
`hiding ${found.size} connected tool(s) whose input schema is not valid JSON Schema: ` +
|
|
1060
|
+
`${[...found.values()].map((t) => `${t.name} (${t.path}: ${t.reason})`).join(', ')}`,
|
|
1061
|
+
);
|
|
1062
|
+
return { tools: tools.filter((tool) => !found.has(tool.utcpName)), hidden };
|
|
1063
|
+
}
|
|
1064
|
+
|
|
1065
|
+
/** The schema findings the owner-facing surfaces report — see {@link ToolSchemaGuard}. */
|
|
1066
|
+
get hiddenTools(): HiddenToolSource {
|
|
1067
|
+
return this.toolSchemas;
|
|
892
1068
|
}
|
|
893
1069
|
|
|
894
1070
|
/**
|
|
@@ -1244,17 +1420,23 @@ export class McpService {
|
|
|
1244
1420
|
// payload without a `progressToken` is accepted — same approach the prior
|
|
1245
1421
|
// handler used; the strict ServerNotification type requires the token.
|
|
1246
1422
|
extra: { sendNotification: (n: any) => Promise<void> },
|
|
1423
|
+
structured = false,
|
|
1247
1424
|
): Promise<CallToolResult> {
|
|
1248
1425
|
const progressToken = request.params._meta?.progressToken;
|
|
1249
|
-
return dispatchToolCall(
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1426
|
+
return dispatchToolCall(
|
|
1427
|
+
client,
|
|
1428
|
+
tool,
|
|
1429
|
+
request.params.arguments ?? {},
|
|
1430
|
+
(progress, message) =>
|
|
1431
|
+
extra.sendNotification({
|
|
1432
|
+
method: 'notifications/progress',
|
|
1433
|
+
params: {
|
|
1434
|
+
...(progressToken !== undefined ? { progressToken } : {}),
|
|
1435
|
+
progress,
|
|
1436
|
+
message,
|
|
1437
|
+
},
|
|
1438
|
+
}),
|
|
1439
|
+
{ structured },
|
|
1258
1440
|
);
|
|
1259
1441
|
}
|
|
1260
1442
|
|
|
@@ -1328,6 +1510,11 @@ function templateFingerprint(template: CallTemplate): string {
|
|
|
1328
1510
|
* until the consumer finishes or abandons it (`for await` returns the
|
|
1329
1511
|
* generator, which runs the `finally`).
|
|
1330
1512
|
*
|
|
1513
|
+
* No guard is re-installed over this wrapper, and none is needed: a routed call
|
|
1514
|
+
* is made on the POOLED client, which had the guards installed on it when its
|
|
1515
|
+
* own manual was registered (`registerManual`). Nothing in this module checks a
|
|
1516
|
+
* call or shapes its failure — it forwards the call and returns the answer.
|
|
1517
|
+
*
|
|
1331
1518
|
* A call the downstream refuses for its token (401 / `invalid_token`) goes to
|
|
1332
1519
|
* the route's `afterFailure`, which may refresh the token and ask for ONE retry
|
|
1333
1520
|
* on a fresh connection. Retrying is safe for the same reason session recovery
|
|
@@ -20,6 +20,7 @@ import type {
|
|
|
20
20
|
OAuthTokenRevocationRequest,
|
|
21
21
|
OAuthTokens,
|
|
22
22
|
} from '@modelcontextprotocol/sdk/shared/auth.js';
|
|
23
|
+
import type { AgentConnectedEvent } from '@bevel-software/platform-shared';
|
|
23
24
|
import type { Database } from '../../database/connection.js';
|
|
24
25
|
import { agentConnections, oauthAuthCodes, oauthClients, oauthTokens, users } from '../../database/schema.js';
|
|
25
26
|
import type { TokenCrypto } from '../../../shared/token-crypto.js';
|
|
@@ -57,6 +58,12 @@ export interface BevelOAuthProviderDeps {
|
|
|
57
58
|
publicFrontendUrl: string;
|
|
58
59
|
/** Access-token plaintext prefix, e.g. `bevel-mcp_`. */
|
|
59
60
|
tokenPrefix: string;
|
|
61
|
+
/**
|
|
62
|
+
* Where the FIRST use of an agent connection is announced to its owner
|
|
63
|
+
* (`agent-connected`, see {@link BevelOAuthProvider.noteConnectionUse}).
|
|
64
|
+
* Optional: without it the stamp is written and nobody is told.
|
|
65
|
+
*/
|
|
66
|
+
events?: { emit(event: AgentConnectedEvent): void };
|
|
60
67
|
}
|
|
61
68
|
|
|
62
69
|
/**
|
|
@@ -511,11 +518,42 @@ export class BevelOAuthProvider implements OAuthServerProvider {
|
|
|
511
518
|
const last = this.connectionTouchedAt.get(connectionId);
|
|
512
519
|
if (last !== undefined && now - last < CONNECTION_TOUCH_INTERVAL_MS) return;
|
|
513
520
|
this.connectionTouchedAt.set(connectionId, now);
|
|
514
|
-
this.
|
|
521
|
+
this.stampConnectionUse(connectionId, new Date(now)).catch((err) =>
|
|
522
|
+
log.warn('touch connection lastUsedAt failed:', { err }),
|
|
523
|
+
);
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
/**
|
|
527
|
+
* The stamp itself, and the one thing it tells: a connection stamped for
|
|
528
|
+
* the FIRST time is an agent that has just reached the platform — the
|
|
529
|
+
* `initialize` every client sends on connecting — which is what the
|
|
530
|
+
* onboarding waits for, so its owner is told (`agent-connected`) for
|
|
531
|
+
* exactly that stamp and never again.
|
|
532
|
+
*
|
|
533
|
+
* The first stamp is CLAIMED in one statement (`… where last_used_at is
|
|
534
|
+
* null … returning`): of two requests racing it — a parallel
|
|
535
|
+
* `initialize` and `tools/list`, or two replicas — the database hands the
|
|
536
|
+
* row to exactly one, and only that one announces. The loser, and every
|
|
537
|
+
* later use, stamps the ordinary way. Both sit behind the throttle above,
|
|
538
|
+
* so the hot path pays nothing for them.
|
|
539
|
+
*/
|
|
540
|
+
private async stampConnectionUse(connectionId: string, at: Date): Promise<void> {
|
|
541
|
+
const [first] = await this.deps.db
|
|
515
542
|
.update(agentConnections)
|
|
516
|
-
.set({ lastUsedAt:
|
|
517
|
-
.where(eq(agentConnections.id, connectionId))
|
|
518
|
-
.
|
|
543
|
+
.set({ lastUsedAt: at })
|
|
544
|
+
.where(and(eq(agentConnections.id, connectionId), isNull(agentConnections.lastUsedAt)))
|
|
545
|
+
.returning({ userId: agentConnections.userId, client: agentConnections.clientName });
|
|
546
|
+
if (first) {
|
|
547
|
+
this.deps.events?.emit({
|
|
548
|
+
kind: 'agent-connected',
|
|
549
|
+
forUserId: first.userId,
|
|
550
|
+
client: first.client ?? 'Unnamed agent',
|
|
551
|
+
agentKind: 'agent',
|
|
552
|
+
at: at.toISOString(),
|
|
553
|
+
});
|
|
554
|
+
return;
|
|
555
|
+
}
|
|
556
|
+
await this.deps.db.update(agentConnections).set({ lastUsedAt: at }).where(eq(agentConnections.id, connectionId));
|
|
519
557
|
}
|
|
520
558
|
|
|
521
559
|
/**
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The schema check for connected tools, and the memory of what it found.
|
|
3
|
+
*
|
|
4
|
+
* An AI client that is handed a tool whose input schema is not valid JSON
|
|
5
|
+
* Schema drops that tool and says nothing: it is simply missing for the agent,
|
|
6
|
+
* with nothing in Hexis to look at. So Hexis runs the same check itself, when a
|
|
7
|
+
* server's tools are LOADED, and:
|
|
8
|
+
*
|
|
9
|
+
* - keeps such a tool off every agent surface, so the agent's picture of what
|
|
10
|
+
* it can do matches what it can actually call;
|
|
11
|
+
* - remembers the finding for the people who manage that server, who are the
|
|
12
|
+
* only ones who can get it fixed (the tool page, `list_tool_setup`).
|
|
13
|
+
*
|
|
14
|
+
* WHEN it runs is the point. The verdict is remembered per DISTINCT SCHEMA, so
|
|
15
|
+
* a server whose tools are unchanged costs one hash and one map lookup per
|
|
16
|
+
* tool: the JSON Schema check happens when a server's tools are first loaded
|
|
17
|
+
* and when a refresh brings a schema this process has not seen, and never on a
|
|
18
|
+
* tool call — which re-derives the surface from those same unchanged schemas.
|
|
19
|
+
*
|
|
20
|
+
* It never REPAIRS anything. The proxy passes a connected server's schema
|
|
21
|
+
* through as sent; an invalid one is reported, and the server's owner decides.
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
import { createHash } from 'node:crypto';
|
|
25
|
+
import { inputSchemaDefect, schemaDefectMarker, type SchemaDefect } from '@bevel-software/platform-mcp-core';
|
|
26
|
+
import type { HiddenTool, HiddenToolSource } from '../../shared/hidden-tools.js';
|
|
27
|
+
|
|
28
|
+
/** What {@link ToolSchemaGuard.screen} needs of a freshly loaded tool. */
|
|
29
|
+
export interface ScreenedTool {
|
|
30
|
+
/** The UTCP name (`<manual>.<server>.<tool>`) — how the tool repository knows it. */
|
|
31
|
+
utcpName: string;
|
|
32
|
+
/** The flattened name an agent addresses it by. */
|
|
33
|
+
mcpName: string;
|
|
34
|
+
/** The input schema exactly as the connected server sent it. */
|
|
35
|
+
inputSchema: unknown;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* A finding as the LOADING side needs it. The owner-facing `HiddenTool` is
|
|
40
|
+
* about a tool by the name an agent would have called it; the proxy also has to
|
|
41
|
+
* take the tool out of its repository and record it in the audit trail, and
|
|
42
|
+
* both of those know a tool by its UTCP name. Kept off `HiddenTool` so the
|
|
43
|
+
* owner-facing payload stays exactly what its surfaces declare.
|
|
44
|
+
*/
|
|
45
|
+
export interface ScreenedHiddenTool extends HiddenTool {
|
|
46
|
+
/** The UTCP name (`<manual>.<server>.<tool>`) the tool repository knows it by. */
|
|
47
|
+
utcpName: string;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* How many schema verdicts to remember. Each is a hash and a verdict, so the
|
|
52
|
+
* cap is about a deployment that edits servers all day rather than about size;
|
|
53
|
+
* past it the whole table is cleared instead of evicted entry by entry, since
|
|
54
|
+
* the next load simply re-checks.
|
|
55
|
+
*/
|
|
56
|
+
const MAX_REMEMBERED_SCHEMAS = 5000;
|
|
57
|
+
|
|
58
|
+
/** How many callers' pictures to hold at once — see `screen` for what happens past it. Exported for the tests that fill it. */
|
|
59
|
+
export const MAX_REMEMBERED_CALLERS = 2000;
|
|
60
|
+
|
|
61
|
+
export class ToolSchemaGuard implements HiddenToolSource {
|
|
62
|
+
/** Verdict per distinct schema: `null` means valid, so `undefined` means unchecked. */
|
|
63
|
+
private readonly verdicts = new Map<string, SchemaDefect | null>();
|
|
64
|
+
/**
|
|
65
|
+
* The findings, per CALLER and then per manual by catalog name.
|
|
66
|
+
*
|
|
67
|
+
* Keyed by caller because that is what a load is: discovery runs on the
|
|
68
|
+
* requesting user's own connection to the server, and two callers can be
|
|
69
|
+
* shown different tools by the same server. A single table keyed by manual
|
|
70
|
+
* would let one caller's load erase another's finding — the owner page would
|
|
71
|
+
* then show a defect from whichever request happened to be last, or none at
|
|
72
|
+
* all. Keyed by caller, a load replaces only what that caller can see, and
|
|
73
|
+
* `hiddenFor` reports the union, since the finding is about the server.
|
|
74
|
+
*/
|
|
75
|
+
private readonly hidden = new Map<string, Map<string, ScreenedHiddenTool[]>>();
|
|
76
|
+
/** The newest load whose picture has been applied, per caller — see {@link beginLoad}. */
|
|
77
|
+
private readonly applied = new Map<string, number>();
|
|
78
|
+
/** Hands out {@link beginLoad} tickets; monotonic for the life of the process. */
|
|
79
|
+
private loads = 0;
|
|
80
|
+
|
|
81
|
+
/** `check` is injected only by tests, to observe how often the check runs. */
|
|
82
|
+
constructor(private readonly check: (schema: unknown) => SchemaDefect | null = inputSchemaDefect) {}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* A ticket for a load that is ABOUT TO READ a server's tools, to be handed
|
|
86
|
+
* back to {@link screen} with what it found.
|
|
87
|
+
*
|
|
88
|
+
* Requests overlap: a caller's surface is rebuilt on every one of them, and
|
|
89
|
+
* two can be dialling the same server at once. Without an order, a load that
|
|
90
|
+
* started while a schema was still broken could land after the load that saw
|
|
91
|
+
* it corrected, and put the marker back on a tool that is fine — until some
|
|
92
|
+
* later request happened to clear it again. The ticket is taken BEFORE the
|
|
93
|
+
* read, so it ranks loads by the freshness of what they saw, and `screen`
|
|
94
|
+
* ignores a picture older than the one already applied.
|
|
95
|
+
*/
|
|
96
|
+
beginLoad(): number {
|
|
97
|
+
this.loads += 1;
|
|
98
|
+
return this.loads;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Screen everything one caller's request just loaded — every manual on their
|
|
103
|
+
* surface, with the tools that manual advertised — and replace that caller's
|
|
104
|
+
* whole picture. Returns the tools to keep off the agent surfaces, keyed by
|
|
105
|
+
* UTCP name.
|
|
106
|
+
*
|
|
107
|
+
* WHOLE is the point, and why this takes every manual rather than one. A
|
|
108
|
+
* manual whose group is EMPTY has nothing hidden: its server dropped the
|
|
109
|
+
* offending tool, or it failed to attach at all and its tools are not loaded.
|
|
110
|
+
* A manual absent from `groups` is no longer on this caller's surface. Either
|
|
111
|
+
* way the marker goes, with nothing to clear by hand — and nothing claims a
|
|
112
|
+
* tool is hidden for a schema this process can no longer see.
|
|
113
|
+
*
|
|
114
|
+
* `loadId` comes from {@link beginLoad}, taken before the tools were read. A
|
|
115
|
+
* load that is already out of date still gets its own answer — the request
|
|
116
|
+
* that ran it must not offer a tool it has just judged invalid — but it does
|
|
117
|
+
* not write that answer into what everyone else reads.
|
|
118
|
+
*/
|
|
119
|
+
screen(
|
|
120
|
+
userId: string,
|
|
121
|
+
loadId: number,
|
|
122
|
+
groups: ReadonlyMap<string, readonly ScreenedTool[]>,
|
|
123
|
+
): Map<string, ScreenedHiddenTool> {
|
|
124
|
+
const found = new Map<string, ScreenedHiddenTool>();
|
|
125
|
+
const picture = new Map<string, ScreenedHiddenTool[]>();
|
|
126
|
+
for (const [manual, tools] of groups) {
|
|
127
|
+
const ofManual: ScreenedHiddenTool[] = [];
|
|
128
|
+
for (const tool of tools) {
|
|
129
|
+
const defect = this.verdict(tool.inputSchema);
|
|
130
|
+
if (!defect) continue;
|
|
131
|
+
const hidden: ScreenedHiddenTool = {
|
|
132
|
+
manual,
|
|
133
|
+
name: tool.mcpName,
|
|
134
|
+
utcpName: tool.utcpName,
|
|
135
|
+
path: defect.path,
|
|
136
|
+
reason: defect.reason,
|
|
137
|
+
marker: schemaDefectMarker(defect),
|
|
138
|
+
};
|
|
139
|
+
found.set(tool.utcpName, hidden);
|
|
140
|
+
ofManual.push(hidden);
|
|
141
|
+
}
|
|
142
|
+
if (ofManual.length > 0) picture.set(manual, ofManual);
|
|
143
|
+
}
|
|
144
|
+
// Stale: a load that read the server earlier than one already applied for
|
|
145
|
+
// THIS caller. Its own answer stands, the shared picture does not move.
|
|
146
|
+
//
|
|
147
|
+
// Per caller, and nothing wider. An evicted caller's watermark goes with
|
|
148
|
+
// their picture, and that loses nothing: once nothing of theirs is held,
|
|
149
|
+
// whichever of their loads lands next is the newest picture this process
|
|
150
|
+
// has of them, and it restores the watermark that rejects any older one
|
|
151
|
+
// landing after it. A floor shared across callers would instead reject
|
|
152
|
+
// some OTHER caller's newest load for having begun before an unrelated
|
|
153
|
+
// eviction, and the owner's page would miss that caller's finding.
|
|
154
|
+
if (loadId < (this.applied.get(userId) ?? 0)) return found;
|
|
155
|
+
// Not about size — each entry is a handful of strings — but about a
|
|
156
|
+
// deployment with many callers never growing these without bound. Evicted
|
|
157
|
+
// one caller at a time, the longest unseen first, so every other caller's
|
|
158
|
+
// findings stay on the owner's page; the next load of the evicted surface
|
|
159
|
+
// puts its own back. (Re-inserted on every load, so a Map's insertion
|
|
160
|
+
// order is the order of last sight.)
|
|
161
|
+
while (this.applied.size >= MAX_REMEMBERED_CALLERS && !this.applied.has(userId)) {
|
|
162
|
+
const oldest = this.applied.keys().next().value as string;
|
|
163
|
+
this.applied.delete(oldest);
|
|
164
|
+
this.hidden.delete(oldest);
|
|
165
|
+
}
|
|
166
|
+
this.applied.delete(userId);
|
|
167
|
+
this.applied.set(userId, loadId);
|
|
168
|
+
if (picture.size > 0) this.hidden.set(userId, picture);
|
|
169
|
+
else this.hidden.delete(userId);
|
|
170
|
+
return found;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
hiddenFor(manual: string): HiddenTool[] {
|
|
174
|
+
const union = new Map<string, HiddenTool>();
|
|
175
|
+
for (const picture of this.hidden.values()) {
|
|
176
|
+
for (const { manual: of, name, path, reason, marker } of picture.get(manual) ?? []) {
|
|
177
|
+
// One entry per distinct defect: two callers shown the same broken tool
|
|
178
|
+
// have found one thing, and its owner should read it once. Projected to
|
|
179
|
+
// the owner-facing shape, so nothing of the loading side rides along.
|
|
180
|
+
union.set(`${name}\u0000${path}\u0000${reason}`, { manual: of, name, path, reason, marker });
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
return [...union.values()];
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/** The check itself, once per distinct schema. */
|
|
187
|
+
private verdict(schema: unknown): SchemaDefect | null {
|
|
188
|
+
const key = createHash('sha1').update(JSON.stringify(schema) ?? 'undefined').digest('hex');
|
|
189
|
+
const remembered = this.verdicts.get(key);
|
|
190
|
+
if (remembered !== undefined) return remembered;
|
|
191
|
+
const defect = this.check(schema);
|
|
192
|
+
if (this.verdicts.size >= MAX_REMEMBERED_SCHEMAS) this.verdicts.clear();
|
|
193
|
+
this.verdicts.set(key, defect);
|
|
194
|
+
return defect;
|
|
195
|
+
}
|
|
196
|
+
}
|