@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
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import type { Router, RequestHandler } from 'express';
|
|
2
|
+
import type { IToolRegistry } from '../tool-registry/tool.contract.js';
|
|
3
|
+
import { ToolError } from '../tool-helpers/tool.contract.js';
|
|
4
|
+
import { toolDef } from '../tool-helpers/tool-def.js';
|
|
5
|
+
import type { ToolHandlerFactory } from '../tool-helpers/tool-handler.js';
|
|
6
|
+
import type { ToolContext } from '../tool-helpers/tool.contract.js';
|
|
7
|
+
import type { KbContext } from '../../shared/kb-context.js';
|
|
8
|
+
import type { ReadForTool } from '../workspace/workspace.tools.js';
|
|
9
|
+
import type { IEmbedService } from './embed.interface.js';
|
|
10
|
+
import { requireExternalSource } from '../tool-auth/tool-auth.middleware.js';
|
|
11
|
+
import { SESSION_ID_INPUT, type ToolDescriptionNotes } from '../workspace/agent-access.gate.js';
|
|
12
|
+
import { sessionIdInputOf } from '../workspace/workspace.tools.js';
|
|
13
|
+
|
|
14
|
+
/** The tool name, in one place: the app manifest keys its view by it. */
|
|
15
|
+
export const OPEN_PAGE_TOOL = 'open_page';
|
|
16
|
+
|
|
17
|
+
/** What `open_page` answers when the deployment cannot be framed. */
|
|
18
|
+
export const HTTP_DEPLOYMENT_NOTE =
|
|
19
|
+
'This deployment is reached over plain http, so no chat host can show the page inline — ' +
|
|
20
|
+
'an embedded view needs an https deployment. The page is above, and its address in the app ' +
|
|
21
|
+
'opens the whole thing.';
|
|
22
|
+
|
|
23
|
+
/** What a path outside the knowledge base is told. */
|
|
24
|
+
export const OUTSIDE_REPO = (kbDirName: string): string =>
|
|
25
|
+
`open_page shows a knowledge-base page, so \`path\` has to name a file under \`${kbDirName}/\`.`;
|
|
26
|
+
|
|
27
|
+
export interface EmbedToolsDeps {
|
|
28
|
+
embedService: IEmbedService;
|
|
29
|
+
kb: KbContext;
|
|
30
|
+
/** `read_file`'s own read — see {@link ReadForTool}. */
|
|
31
|
+
readForTool: ReadForTool;
|
|
32
|
+
/** Whether a chat host's sandbox can load from this deployment's public address at all (https). */
|
|
33
|
+
canBeReached: () => boolean;
|
|
34
|
+
/** The file's address in the app, for the answer and for the view's fallback link. */
|
|
35
|
+
appUrlFor: (repoRelative: string, slug?: string) => string;
|
|
36
|
+
/** The notes a deployment registers for the gated tools — `read_file`'s, and so this tool's. */
|
|
37
|
+
notes: ToolDescriptionNotes;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* `open_page`: the knowledge-base page, in the chat.
|
|
42
|
+
*
|
|
43
|
+
* The tool answers the file's TEXT exactly as `read_file` does — the same
|
|
44
|
+
* read hook, the same access gate, the same refusals — and adds the address
|
|
45
|
+
* of an embedded view that renders the page with the app's own renderer, so a
|
|
46
|
+
* host that supports MCP Apps shows it inline and lets the reader edit it or
|
|
47
|
+
* propose a change. A host that does not support them shows the text and the
|
|
48
|
+
* app address, and nothing errors: the answer stands on its own.
|
|
49
|
+
*
|
|
50
|
+
* `read_file` is deliberately untouched (Decision 2). Carrying a view on it
|
|
51
|
+
* would mint a token and render an iframe on every read an agent makes, for
|
|
52
|
+
* every file it reads while thinking.
|
|
53
|
+
*
|
|
54
|
+
* No `branch` argument, by decision: the embedded view is editable, and an
|
|
55
|
+
* editable embed targets the default branch only. The branch it rendered
|
|
56
|
+
* comes back in the answer so nothing is implied.
|
|
57
|
+
*/
|
|
58
|
+
export function registerEmbedTools(
|
|
59
|
+
registry: IToolRegistry,
|
|
60
|
+
router: Router,
|
|
61
|
+
toolAuth: RequestHandler,
|
|
62
|
+
toolHandler: ToolHandlerFactory,
|
|
63
|
+
deps: EmbedToolsDeps,
|
|
64
|
+
): void {
|
|
65
|
+
const { kbDirName } = deps.kb;
|
|
66
|
+
const DESCRIPTION =
|
|
67
|
+
'Show a knowledge-base page to the person you are talking to, rendered inside this chat. ' +
|
|
68
|
+
'Returns the same `{ path, content }` `read_file` returns — the page as text, for you to read — ' +
|
|
69
|
+
'plus `embedUrl` (the view the chat renders), `appUrl` (the page in the app), and `branch` ' +
|
|
70
|
+
"(always the default branch). The rendered view uses the app's own renderer for the file's type, " +
|
|
71
|
+
'and offers the reader Edit when they may write the page and Propose changes when they may not, ' +
|
|
72
|
+
'as that same person — not as you. Use it when somebody wants to SEE or FIX a page; use `read_file` ' +
|
|
73
|
+
'when you only need to read one yourself. A chat host that cannot render a view shows the text, ' +
|
|
74
|
+
'so calling this is never worse than reading.';
|
|
75
|
+
const def = toolDef({
|
|
76
|
+
name: OPEN_PAGE_TOOL,
|
|
77
|
+
description: DESCRIPTION + deps.notes.gatedToolNote(),
|
|
78
|
+
path: `/api/agent/tools/${OPEN_PAGE_TOOL}`,
|
|
79
|
+
inputs: {
|
|
80
|
+
type: 'object',
|
|
81
|
+
properties: {
|
|
82
|
+
path: {
|
|
83
|
+
type: 'string',
|
|
84
|
+
minLength: 1,
|
|
85
|
+
description:
|
|
86
|
+
`Path of the page to show, under \`${kbDirName}/\` (e.g. \`${kbDirName}/KnowledgeBase/Foo.md\`), ` +
|
|
87
|
+
'with or without a leading slash — a path without that prefix is placed under ' +
|
|
88
|
+
`\`${kbDirName}/\`. The page is always shown from the default branch.`,
|
|
89
|
+
},
|
|
90
|
+
heading: {
|
|
91
|
+
type: 'string',
|
|
92
|
+
description:
|
|
93
|
+
'Optional: the anchor slug of one heading (e.g. `problem-statement`) the view should open at. ' +
|
|
94
|
+
'The whole page is shown either way — this only says where to start reading.',
|
|
95
|
+
},
|
|
96
|
+
// As `read_file` takes it: the read is `read_file`'s own, and a
|
|
97
|
+
// deployment whose read hook wants the session must be able to get it.
|
|
98
|
+
sessionId: SESSION_ID_INPUT,
|
|
99
|
+
},
|
|
100
|
+
required: ['path'],
|
|
101
|
+
additionalProperties: false,
|
|
102
|
+
},
|
|
103
|
+
outputs: {
|
|
104
|
+
type: 'object',
|
|
105
|
+
properties: {
|
|
106
|
+
path: { type: 'string', description: 'The path that was shown (echoes the input).' },
|
|
107
|
+
content: { type: 'string', description: "The page's text, exactly as `read_file` answers it." },
|
|
108
|
+
embedUrl: {
|
|
109
|
+
type: 'string',
|
|
110
|
+
description:
|
|
111
|
+
'The address of the view the chat renders. Absent when this deployment cannot be framed — ' +
|
|
112
|
+
'see `note`.',
|
|
113
|
+
},
|
|
114
|
+
appUrl: { type: 'string', description: "The page's address in the app." },
|
|
115
|
+
branch: { type: 'string', description: 'The branch the page was rendered from — the default branch.' },
|
|
116
|
+
note: {
|
|
117
|
+
type: 'string',
|
|
118
|
+
description: 'Present only when there is no `embedUrl`: why there is no embedded view.',
|
|
119
|
+
},
|
|
120
|
+
},
|
|
121
|
+
required: ['path', 'content', 'appUrl', 'branch'],
|
|
122
|
+
},
|
|
123
|
+
tags: ['workspace'],
|
|
124
|
+
});
|
|
125
|
+
// EXTERNAL only. The view exists for a chat somewhere else; the in-app
|
|
126
|
+
// agent's reader is already looking at the app, where every page is a
|
|
127
|
+
// click away — handing it an iframe of the page it is standing on would be
|
|
128
|
+
// a tool that cannot help.
|
|
129
|
+
registry.registerExternalTool(def);
|
|
130
|
+
// The read is `read_file`'s own, so what the agent reads about it is too:
|
|
131
|
+
// the note a deployment registers for the gated tools, and the `sessionId`
|
|
132
|
+
// description with its note — applied now and on every later registration,
|
|
133
|
+
// exactly as the file tools apply them (`sessionIdInputOf` is theirs).
|
|
134
|
+
const redescribe = (): void => {
|
|
135
|
+
def.description = DESCRIPTION + deps.notes.gatedToolNote();
|
|
136
|
+
const sessionId = sessionIdInputOf(def);
|
|
137
|
+
if (sessionId) sessionId.description = deps.notes.sessionIdDescription();
|
|
138
|
+
};
|
|
139
|
+
redescribe();
|
|
140
|
+
deps.notes.onChange(redescribe);
|
|
141
|
+
|
|
142
|
+
router.post(
|
|
143
|
+
`/agent/tools/${OPEN_PAGE_TOOL}`,
|
|
144
|
+
toolAuth,
|
|
145
|
+
// Registered external-only above; the route holds the same line, so an
|
|
146
|
+
// in-process agent that guessed the endpoint is refused here too.
|
|
147
|
+
requireExternalSource,
|
|
148
|
+
toolHandler(async (args, ctx: ToolContext) => {
|
|
149
|
+
const raw = typeof args.path === 'string' ? args.path.trim() : '';
|
|
150
|
+
if (!raw) throw new ToolError('`path` is required.', 400);
|
|
151
|
+
const heading = typeof args.heading === 'string' && args.heading.trim() ? args.heading.trim() : undefined;
|
|
152
|
+
const repoRelative = toRepoRelative(raw, kbDirName);
|
|
153
|
+
if (repoRelative === null) throw new ToolError(OUTSIDE_REPO(kbDirName), 400);
|
|
154
|
+
const branch = deps.kb.defaultBranch;
|
|
155
|
+
const wsPath = `${kbDirName}/${repoRelative}`;
|
|
156
|
+
|
|
157
|
+
// The read comes FIRST, and it is `read_file`'s own: a path the caller
|
|
158
|
+
// may not read, or one that is not there, is refused here in the words
|
|
159
|
+
// `read_file` refuses it — and no token is minted, because the mint is
|
|
160
|
+
// below this line.
|
|
161
|
+
const result = await deps.readForTool(branch, wsPath, ctx);
|
|
162
|
+
const content =
|
|
163
|
+
result.kind === 'text' ? result.text : result.kind === 'image' ? result.note : result.message;
|
|
164
|
+
|
|
165
|
+
const appUrl = deps.appUrlFor(repoRelative, heading);
|
|
166
|
+
// No view on a plain-http deployment (Decision 8): a host's https
|
|
167
|
+
// sandbox cannot load from it. The text and the app address are still
|
|
168
|
+
// the answer, and the tool says why there is no view rather than
|
|
169
|
+
// handing back an address no host can open.
|
|
170
|
+
if (!deps.canBeReached()) {
|
|
171
|
+
return { path: raw, content, appUrl, branch, note: HTTP_DEPLOYMENT_NOTE };
|
|
172
|
+
}
|
|
173
|
+
// Minted for the identity THIS MCP session authenticated — the
|
|
174
|
+
// signed-in user, or the owner of the connection key the agent carries.
|
|
175
|
+
// Whoever is in the chat therefore sees and may change exactly what
|
|
176
|
+
// that person may, and the audit log attributes it to them.
|
|
177
|
+
const { embedUrl } = await deps.embedService.mintForUser({
|
|
178
|
+
userId: ctx.user.id,
|
|
179
|
+
reference: heading ? `${repoRelative}#${heading}` : repoRelative,
|
|
180
|
+
});
|
|
181
|
+
return { path: raw, content, embedUrl, appUrl, branch };
|
|
182
|
+
}),
|
|
183
|
+
);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* `path` as a repo-relative path, or null when it names nothing inside the
|
|
188
|
+
* knowledge base. Accepts it with or without the `<kbDir>/` prefix and with
|
|
189
|
+
* or without a leading slash, which is what `read_file` documents.
|
|
190
|
+
*/
|
|
191
|
+
export function toRepoRelative(path: string, kbDirName: string): string | null {
|
|
192
|
+
// A backslash is refused, not read as a separator — `read_file`'s contract,
|
|
193
|
+
// and a token must never name a file other than the one the caller wrote.
|
|
194
|
+
if (path.includes('\\')) return null;
|
|
195
|
+
const norm = path.replace(/^\.?\/+/, '').replace(/\/+$/, '');
|
|
196
|
+
if (!norm) return null;
|
|
197
|
+
const rel = norm === kbDirName ? '' : norm.startsWith(`${kbDirName}/`) ? norm.slice(kbDirName.length + 1) : norm;
|
|
198
|
+
if (!rel) return null;
|
|
199
|
+
// Traversal and the odd segment are refused HERE rather than deeper: the
|
|
200
|
+
// path is about to become part of a signed token, and a token is the one
|
|
201
|
+
// place a bad path would outlive the request that sent it.
|
|
202
|
+
// eslint-disable-next-line no-control-regex
|
|
203
|
+
if (/[\x00-\x1f\x7f]/.test(rel)) return null;
|
|
204
|
+
if (!rel.split('/').every((seg) => seg !== '' && seg !== '.' && seg !== '..')) return null;
|
|
205
|
+
return rel;
|
|
206
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import express, { type RequestHandler } from 'express';
|
|
2
|
+
import type { McpAppManifest } from '@bevel-software/platform-mcp-core';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* The deployment's MCP Apps over REST, for the LOCAL MCP server.
|
|
6
|
+
*
|
|
7
|
+
* `hexis-mcp` bridges a host to this deployment over HTTP: it discovers the
|
|
8
|
+
* tools as a UTCP manual, which has nowhere to carry a view, and it serves
|
|
9
|
+
* `resources/read` itself. So it needs the manifest — which tools carry a
|
|
10
|
+
* view, and the view's HTML and sandbox metadata — as data. One route, one
|
|
11
|
+
* answer, so the local server advertises the same apps the hosted endpoint
|
|
12
|
+
* does without knowing what any of them render.
|
|
13
|
+
*
|
|
14
|
+
* `manualAuth` for the same reason `all-tools` and `catalog-revision` use it:
|
|
15
|
+
* this is the agent surface, reached with a connection key or an exchanged
|
|
16
|
+
* grant. Nothing here is per-caller — every connection gets the same view —
|
|
17
|
+
* so the credential is a door, not a filter.
|
|
18
|
+
*/
|
|
19
|
+
export function createMcpAppRoutes(
|
|
20
|
+
apps: { manifest(): Promise<McpAppManifest> },
|
|
21
|
+
manualAuth: RequestHandler,
|
|
22
|
+
): express.Router {
|
|
23
|
+
const router = express.Router();
|
|
24
|
+
|
|
25
|
+
router.get('/agent/mcp-app', manualAuth, async (_req, res) => {
|
|
26
|
+
try {
|
|
27
|
+
const manifest = await apps.manifest();
|
|
28
|
+
// The view's HTML rides the manifest rather than sitting behind a
|
|
29
|
+
// second round trip per resource: it is one small static file, the
|
|
30
|
+
// local server needs all of it before it can declare the capability at
|
|
31
|
+
// all, and a second fetch is a second thing that can half-fail.
|
|
32
|
+
res.setHeader('Cache-Control', 'no-store');
|
|
33
|
+
res.json(manifest);
|
|
34
|
+
} catch (err) {
|
|
35
|
+
console.error('[embed] could not build the MCP App manifest:', err);
|
|
36
|
+
res.status(500).json({ error: 'Something went wrong.' });
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
return router;
|
|
41
|
+
}
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { readFile } from 'node:fs/promises';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import {
|
|
5
|
+
MCP_APP_MIME_TYPE,
|
|
6
|
+
type McpAppManifest,
|
|
7
|
+
type McpAppResource,
|
|
8
|
+
} from '@bevel-software/platform-mcp-core';
|
|
9
|
+
import { mcpAppDir } from '../../assets.js';
|
|
10
|
+
import { logger } from '../../shared/logging.js';
|
|
11
|
+
import { OPEN_PAGE_TOOL } from './embed.tools.js';
|
|
12
|
+
|
|
13
|
+
const log = logger('embed');
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* The `ui://` URI of the one view this deployment serves, NAMED BY ITS
|
|
17
|
+
* CONTENT: `ui://hexis/page-<hash>.html`, the hash being the view's own
|
|
18
|
+
* bytes.
|
|
19
|
+
*
|
|
20
|
+
* A host caches a view by its URI, and a changed view under an unchanged
|
|
21
|
+
* URI is served stale until the host happens to refetch — which is what
|
|
22
|
+
* Claude did after the view was rewritten (#391): it kept rendering the
|
|
23
|
+
* view it had cached, the one that goes blank. With the content in the
|
|
24
|
+
* name, every change to the view is a new URI, so no host can keep serving
|
|
25
|
+
* the old one. The prefix is stable so a reader can still tell what the
|
|
26
|
+
* resource is.
|
|
27
|
+
*/
|
|
28
|
+
export const OPEN_PAGE_VIEW_URI_PREFIX = 'ui://hexis/page-';
|
|
29
|
+
|
|
30
|
+
/** The URI the view with these bytes is served under. */
|
|
31
|
+
export function openPageViewUri(text: string): string {
|
|
32
|
+
return `${OPEN_PAGE_VIEW_URI_PREFIX}${createHash('sha256').update(text).digest('hex').slice(0, 12)}.html`;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** The view's file inside the packaged `mcp-app/` folder. */
|
|
36
|
+
const OPEN_PAGE_VIEW_FILE = 'page.html';
|
|
37
|
+
|
|
38
|
+
/** The MCP App views a deployment serves — the port the MCP endpoint, the manifest route and the catalog revision consume. */
|
|
39
|
+
export interface IMcpAppService {
|
|
40
|
+
/** The manifest: which tools carry a view, and the views themselves. */
|
|
41
|
+
manifest(): Promise<McpAppManifest>;
|
|
42
|
+
/** One view by its `ui://` address, or null when this deployment serves none at it. */
|
|
43
|
+
resource(uri: string): Promise<McpAppResource | null>;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* The deployment's MCP Apps, built once per process: which tools carry a
|
|
48
|
+
* view, and the views themselves with the sandbox metadata the host needs.
|
|
49
|
+
*
|
|
50
|
+
* Read once and cached — the file ships with the package and cannot change
|
|
51
|
+
* under a running process, and `resources/read` is on the handshake path of
|
|
52
|
+
* every connection that renders a page.
|
|
53
|
+
*/
|
|
54
|
+
export class McpAppService implements IMcpAppService {
|
|
55
|
+
private cached: Promise<McpAppManifest> | null = null;
|
|
56
|
+
|
|
57
|
+
constructor(
|
|
58
|
+
private readonly config: {
|
|
59
|
+
/** The deployment's public frontend address — the ONE origin the view may reach. */
|
|
60
|
+
readonly publicFrontendUrl: string;
|
|
61
|
+
/** Where the view's file lives. The packaged `mcp-app/` folder unless a test says otherwise. */
|
|
62
|
+
readonly viewDir?: string;
|
|
63
|
+
},
|
|
64
|
+
) {}
|
|
65
|
+
|
|
66
|
+
/** Every app this deployment serves. Empty only if the packaged view is unreadable. */
|
|
67
|
+
manifest(): Promise<McpAppManifest> {
|
|
68
|
+
return (this.cached ??= this.build());
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/** One view by URI, or null when this deployment serves none under it. */
|
|
72
|
+
async resource(uri: string): Promise<McpAppResource | null> {
|
|
73
|
+
const { resources } = await this.manifest();
|
|
74
|
+
return resources.find((r) => r.uri === uri) ?? null;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
private async build(): Promise<McpAppManifest> {
|
|
78
|
+
const file = path.join(this.config.viewDir ?? mcpAppDir(), OPEN_PAGE_VIEW_FILE);
|
|
79
|
+
let text: string;
|
|
80
|
+
try {
|
|
81
|
+
text = await readFile(file, 'utf8');
|
|
82
|
+
} catch (err) {
|
|
83
|
+
// No view, no app. Advertising a `resourceUri` whose resource cannot be
|
|
84
|
+
// read would have a host preload a failure and show an empty frame
|
|
85
|
+
// where the tool's text used to be; with no manifest `open_page` is an
|
|
86
|
+
// ordinary tool answering ordinary text, which is the graceful shape.
|
|
87
|
+
log.error(
|
|
88
|
+
`could not read the MCP App view at ${file}; ` +
|
|
89
|
+
`open_page will carry no view: ${err instanceof Error ? err.message : String(err)}`,
|
|
90
|
+
);
|
|
91
|
+
return { tools: {}, resources: [] };
|
|
92
|
+
}
|
|
93
|
+
const origin = originOf(this.config.publicFrontendUrl);
|
|
94
|
+
const uri = openPageViewUri(text);
|
|
95
|
+
return {
|
|
96
|
+
tools: { [OPEN_PAGE_TOOL]: { resourceUri: uri } },
|
|
97
|
+
resources: [
|
|
98
|
+
{
|
|
99
|
+
uri,
|
|
100
|
+
name: 'knowledge-base-page',
|
|
101
|
+
title: 'Knowledge base page',
|
|
102
|
+
description:
|
|
103
|
+
"The knowledge-base page an agent opened, rendered by the app's own renderer for its type, " +
|
|
104
|
+
'with Edit for a writer and Propose changes for everybody else.',
|
|
105
|
+
mimeType: MCP_APP_MIME_TYPE,
|
|
106
|
+
text,
|
|
107
|
+
ui: {
|
|
108
|
+
// EXACTLY this deployment's own public origin, and nothing else,
|
|
109
|
+
// for the two things the view asks of the host's sandbox:
|
|
110
|
+
// FETCHING the build manifest and the token-only embed API
|
|
111
|
+
// (`connectDomains`), and LOADING the embed bundle's scripts and
|
|
112
|
+
// stylesheets and the bytes the renderers draw
|
|
113
|
+
// (`resourceDomains`). No `frameDomains`: the view frames
|
|
114
|
+
// nothing. Claude's host drops that field and pins the sandbox's
|
|
115
|
+
// `frame-src` to `'self'`, which turned a framed `/embed` into a
|
|
116
|
+
// blank box — so the view loads the deployment's embed bundle
|
|
117
|
+
// into its own document instead. A knowledge-base HTML page
|
|
118
|
+
// still renders through the renderer's `srcdoc` sandbox, which
|
|
119
|
+
// that policy allows.
|
|
120
|
+
csp: {
|
|
121
|
+
connectDomains: origin ? [origin] : [],
|
|
122
|
+
resourceDomains: origin ? [origin] : [],
|
|
123
|
+
},
|
|
124
|
+
// Deliberately NO `domain`. The field asks the host for a
|
|
125
|
+
// dedicated sandbox origin, and the specification leaves its
|
|
126
|
+
// format and validation to each host ("servers MUST consult
|
|
127
|
+
// host-specific documentation") — a value one host accepts,
|
|
128
|
+
// another may reject, and a rejected resource is a view that
|
|
129
|
+
// never renders. This view keeps no storage and has no OAuth
|
|
130
|
+
// callback, so it needs no stable origin of its own; the host's
|
|
131
|
+
// default sandbox is the right one.
|
|
132
|
+
// The framed page draws its own surface; a second border around
|
|
133
|
+
// it reads as a box inside a box.
|
|
134
|
+
prefersBorder: false,
|
|
135
|
+
},
|
|
136
|
+
},
|
|
137
|
+
],
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* `url`'s origin, or null when it does not parse. Only the origin: a
|
|
144
|
+
* `connectDomains` / `resourceDomains` entry is an origin, and a path or a
|
|
145
|
+
* credential in one is either ignored or rejected by the host.
|
|
146
|
+
*/
|
|
147
|
+
export function originOf(url: string): string | null {
|
|
148
|
+
try {
|
|
149
|
+
const origin = new URL(url).origin;
|
|
150
|
+
// An address that parses but has no web origin (`file:`, `data:`) is
|
|
151
|
+
// serialised as the literal "null" — not an origin a host's CSP can name.
|
|
152
|
+
return origin === 'null' ? null : origin;
|
|
153
|
+
} catch {
|
|
154
|
+
return null;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Whether a public address can be reached from inside a host's sandbox at all.
|
|
160
|
+
*
|
|
161
|
+
* Hosts run an MCP App's view in a sandboxed, https iframe, and no browser
|
|
162
|
+
* will let an https document load scripts from, or fetch from, a plain-http
|
|
163
|
+
* origin. So a deployment reached over http has no embedded view —
|
|
164
|
+
* `open_page` still answers the page's text and its address in the app, and
|
|
165
|
+
* says why there is nothing rendered (see Decision 8).
|
|
166
|
+
*/
|
|
167
|
+
export function isSandboxReachableOrigin(url: string): boolean {
|
|
168
|
+
try {
|
|
169
|
+
return new URL(url).protocol === 'https:';
|
|
170
|
+
} catch {
|
|
171
|
+
return false;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
@@ -9,6 +9,8 @@ import { DeploymentSettingsService, SettingsValidationError } from '../../settin
|
|
|
9
9
|
import { GitHubAppClient, GitHubAppError, appJwt, normalizePrivateKey } from '../github-app.client.js';
|
|
10
10
|
import { GitHubAppConnection } from '../github-app.connection.js';
|
|
11
11
|
import { createGitHubAppRoutes, githubAppManifest } from '../github-app.routes.js';
|
|
12
|
+
import { setLogger } from '../../../shared/logging.js';
|
|
13
|
+
import type { ILogger, LogFields } from '../../../shared/logger.contract.js';
|
|
12
14
|
|
|
13
15
|
const ENC_KEY = 'kToAi8FXWDpDn3A6yQ/60O39bv05N7XzVOIu/0CJrFc=';
|
|
14
16
|
const { privateKey: PEM, publicKey: PUBLIC } = generateKeyPairSync('rsa', {
|
|
@@ -393,6 +395,80 @@ describe('GitHubAppConnection: the token git presents', () => {
|
|
|
393
395
|
await settled();
|
|
394
396
|
expect(connection.token()).toBe('installation-token-1');
|
|
395
397
|
});
|
|
398
|
+
|
|
399
|
+
/**
|
|
400
|
+
* The git runner reporting that the host threw the token out. The clock
|
|
401
|
+
* may still give it fifty minutes: the host's verdict wins, the token is
|
|
402
|
+
* dropped, and GitHub is asked for another at once — past the backoff a
|
|
403
|
+
* recent failure would otherwise impose. When GitHub will not replace it,
|
|
404
|
+
* NO token remains: that is what keeps the runner from offering the
|
|
405
|
+
* refused one again.
|
|
406
|
+
*/
|
|
407
|
+
it('replaces a token the host refused, with time to spare or not, and drops it when GitHub will not', async () => {
|
|
408
|
+
const world: Parameters<typeof github>[0] = {};
|
|
409
|
+
const { connection, hub, clock } = connected(world);
|
|
410
|
+
await connection.prepare();
|
|
411
|
+
expect(connection.token()).toBe('installation-token-1');
|
|
412
|
+
clock.now += 5 * 60_000;
|
|
413
|
+
await connection.prepare({ refused: true });
|
|
414
|
+
expect(connection.token()).toBe('installation-token-2');
|
|
415
|
+
expect(hub.tokensIssued()).toBe(2);
|
|
416
|
+
|
|
417
|
+
// Inside a remembered failure's backoff, the refusal still asks.
|
|
418
|
+
world.down = true;
|
|
419
|
+
await expect(connection.prepare({ refused: true })).rejects.toThrow();
|
|
420
|
+
expect(connection.token()).toBeNull();
|
|
421
|
+
world.down = false;
|
|
422
|
+
await expect(connection.prepare({ refused: true })).resolves.toBeUndefined();
|
|
423
|
+
expect(connection.token()).toBe('installation-token-3');
|
|
424
|
+
});
|
|
425
|
+
|
|
426
|
+
/**
|
|
427
|
+
* A deployment whose app settings are incomplete used to run every git
|
|
428
|
+
* call without a credential and say nothing about it — for hours, with
|
|
429
|
+
* every push failing. It says so now: once per state, not before every
|
|
430
|
+
* call, and again if the state changes.
|
|
431
|
+
*/
|
|
432
|
+
it('says ONCE which settings keep it from asking for a token, and says it again when they change', async () => {
|
|
433
|
+
const lines: string[] = [];
|
|
434
|
+
const capture = (bindings: LogFields = {}): ILogger => {
|
|
435
|
+
const line = (level: string) => (message: string, fields?: LogFields) =>
|
|
436
|
+
void lines.push(`${level} ${message} ${JSON.stringify({ ...bindings, ...fields })}`);
|
|
437
|
+
return { debug: line('debug'), info: line('info'), warn: line('warn'), error: line('error'), child: (m) => capture({ ...bindings, ...m }) };
|
|
438
|
+
};
|
|
439
|
+
const previous = setLogger(capture());
|
|
440
|
+
try {
|
|
441
|
+
const { connection, values } = connected();
|
|
442
|
+
const key = values.githubAppPrivateKey!;
|
|
443
|
+
values.githubAppPrivateKey = '';
|
|
444
|
+
await connection.prepare();
|
|
445
|
+
await connection.prepare();
|
|
446
|
+
await connection.prepare();
|
|
447
|
+
const said = lines.filter((l) => l.includes('no installation token can be asked for'));
|
|
448
|
+
expect(said).toHaveLength(1);
|
|
449
|
+
expect(said[0]).toContain('githubAppPrivateKey');
|
|
450
|
+
expect(said[0]).not.toContain('githubInstallationId');
|
|
451
|
+
expect(connection.token()).toBeNull();
|
|
452
|
+
|
|
453
|
+
// The state changes: a second setting goes too. Said again, naming both.
|
|
454
|
+
values.githubInstallationId = '';
|
|
455
|
+
await connection.prepare();
|
|
456
|
+
await connection.prepare();
|
|
457
|
+
expect(lines.filter((l) => l.includes('no installation token can be asked for'))).toHaveLength(2);
|
|
458
|
+
expect(lines.at(-1)).toContain('githubAppPrivateKey, githubInstallationId');
|
|
459
|
+
|
|
460
|
+
// Settings back: a token is asked for, and the next gap is said afresh.
|
|
461
|
+
values.githubAppPrivateKey = key;
|
|
462
|
+
values.githubInstallationId = '77';
|
|
463
|
+
await connection.prepare();
|
|
464
|
+
expect(connection.token()).toBe('installation-token-1');
|
|
465
|
+
values.githubInstallationId = '';
|
|
466
|
+
await connection.prepare();
|
|
467
|
+
expect(lines.filter((l) => l.includes('no installation token can be asked for'))).toHaveLength(3);
|
|
468
|
+
} finally {
|
|
469
|
+
setLogger(previous);
|
|
470
|
+
}
|
|
471
|
+
});
|
|
396
472
|
});
|
|
397
473
|
|
|
398
474
|
describe('GitHubAppConnection: what the deployment may be pointed at', () => {
|
|
@@ -59,6 +59,13 @@ export class GitHubAppConnection implements GitHubAppRepository {
|
|
|
59
59
|
private renewing: Promise<void> | null = null;
|
|
60
60
|
/** The last renewal failed: how many in a row have, and until when GitHub is not asked again. */
|
|
61
61
|
private failed: { times: number; until: number } | null = null;
|
|
62
|
+
/**
|
|
63
|
+
* The settings that were empty the last time no token could be asked for,
|
|
64
|
+
* so the log says so ONCE per state and not before every git call. A
|
|
65
|
+
* deployment in this state used to run for hours with every push failing
|
|
66
|
+
* and nothing in the log naming the cause.
|
|
67
|
+
*/
|
|
68
|
+
private saidUnaskable: string | null = null;
|
|
62
69
|
|
|
63
70
|
constructor(private readonly opts: GitHubAppConnectionOptions) {
|
|
64
71
|
this.client = opts.client ?? new GitHubAppClient();
|
|
@@ -138,20 +145,47 @@ export class GitHubAppConnection implements GitHubAppRepository {
|
|
|
138
145
|
* `asked` is for an admin waiting on the answer itself (the setup screen
|
|
139
146
|
* listing repositories, proving a connection): GitHub is asked whatever
|
|
140
147
|
* is remembered, and the failure is thrown.
|
|
148
|
+
*
|
|
149
|
+
* `refused` is the git runner reporting that the host threw out the token
|
|
150
|
+
* in hand. However much time the clock gives it, that token is dead: it is
|
|
151
|
+
* dropped first, so nothing presents it again, and GitHub is asked for
|
|
152
|
+
* another the way `asked` asks — now, and with the failure thrown. A
|
|
153
|
+
* renewal that fails leaves NO token, which is what tells the runner not
|
|
154
|
+
* to run the command again with the one the host just refused.
|
|
141
155
|
*/
|
|
142
|
-
async prepare(opts: { asked?: boolean } = {}): Promise<void> {
|
|
156
|
+
async prepare(opts: { asked?: boolean; refused?: boolean } = {}): Promise<void> {
|
|
143
157
|
const credentials = this.credentials();
|
|
144
158
|
const installationId = this.installationId();
|
|
145
|
-
if (!credentials || !installationId)
|
|
159
|
+
if (!credentials || !installationId) {
|
|
160
|
+
// Said once per state: every git call lands here while it lasts.
|
|
161
|
+
const empty = ['githubAppId', 'githubAppSlug', 'githubAppPrivateKey', 'githubAppClientId', 'githubAppClientSecret', 'githubInstallationId']
|
|
162
|
+
.filter((key) => !this.opts.read(key))
|
|
163
|
+
.join(', ');
|
|
164
|
+
if (this.saidUnaskable !== empty) {
|
|
165
|
+
this.saidUnaskable = empty;
|
|
166
|
+
this.log().error(
|
|
167
|
+
`no installation token can be asked for while these settings are empty: ${empty}. ` +
|
|
168
|
+
'Every git call to the repository host runs without a credential until they are set.',
|
|
169
|
+
);
|
|
170
|
+
}
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
this.saidUnaskable = null;
|
|
174
|
+
if (opts.refused) {
|
|
175
|
+
// The host's verdict outranks the clock: what it refused is not
|
|
176
|
+
// presented again, by anyone, whatever a renewal in flight brings.
|
|
177
|
+
this.held = null;
|
|
178
|
+
}
|
|
179
|
+
const insist = Boolean(opts.asked || opts.refused);
|
|
146
180
|
const held = this.held?.for === this.holder() ? this.held : null;
|
|
147
181
|
const good = held !== null && held.expiresAt > this.now();
|
|
148
182
|
if (good && held.expiresAt - this.now() > RENEW_AHEAD_MS) return;
|
|
149
|
-
if (!
|
|
183
|
+
if (!insist && this.failed && this.now() < this.failed.until) return;
|
|
150
184
|
|
|
151
185
|
this.renewing ??= this.renew(credentials, installationId).finally(() => {
|
|
152
186
|
this.renewing = null;
|
|
153
187
|
});
|
|
154
|
-
if (good && !
|
|
188
|
+
if (good && !insist) {
|
|
155
189
|
// Not waited on, so not thrown to anyone: the renewal has logged it.
|
|
156
190
|
this.renewing.catch(() => undefined);
|
|
157
191
|
return;
|