@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
|
@@ -14,13 +14,17 @@ import type { IExternalApiKeyService } from '../../tool-auth/external-api-key.in
|
|
|
14
14
|
* update / delete` pops the next queued result. `transaction` runs its
|
|
15
15
|
* callback against the same fake, so queued results are consumed in order.
|
|
16
16
|
* Every `where` predicate and `update` target is captured, so a test can pin
|
|
17
|
-
* WHICH rows a statement addressed (see {@link render}), not just that it ran
|
|
17
|
+
* WHICH rows a statement addressed (see {@link render}), not just that it ran;
|
|
18
|
+
* `orderBy` and `limit` too, since the fake applies neither and a test can
|
|
19
|
+
* only pin WHICH row of several a read keeps by the clauses it sent.
|
|
18
20
|
*/
|
|
19
21
|
function makeFakeDb(queue: unknown[]) {
|
|
20
|
-
const captured: { values: any[]; set: any[]; where: SQL[]; updateTargets: unknown[] } = {
|
|
22
|
+
const captured: { values: any[]; set: any[]; where: SQL[]; orderBy: SQL[][]; limit: number[]; updateTargets: unknown[] } = {
|
|
21
23
|
values: [],
|
|
22
24
|
set: [],
|
|
23
25
|
where: [],
|
|
26
|
+
orderBy: [],
|
|
27
|
+
limit: [],
|
|
24
28
|
updateTargets: [],
|
|
25
29
|
};
|
|
26
30
|
const counts = { insert: 0, select: 0, update: 0, delete: 0 };
|
|
@@ -36,10 +40,10 @@ function makeFakeDb(queue: unknown[]) {
|
|
|
36
40
|
chain.values = passthrough((a) => captured.values.push(a[0]));
|
|
37
41
|
chain.set = passthrough((a) => captured.set.push(a[0]));
|
|
38
42
|
chain.where = passthrough((a) => captured.where.push(a[0]));
|
|
39
|
-
chain.limit = passthrough();
|
|
43
|
+
chain.limit = passthrough((a) => captured.limit.push(a[0]));
|
|
40
44
|
chain.innerJoin = passthrough();
|
|
41
45
|
chain.from = passthrough();
|
|
42
|
-
chain.orderBy = passthrough();
|
|
46
|
+
chain.orderBy = passthrough((a) => captured.orderBy.push(a));
|
|
43
47
|
chain.groupBy = passthrough();
|
|
44
48
|
chain.returning = passthrough();
|
|
45
49
|
chain.then = (onF: any, onR: any) => Promise.resolve(result).then(onF, onR);
|
|
@@ -355,6 +359,62 @@ describe('AgentAuditService.revokeConnection', () => {
|
|
|
355
359
|
});
|
|
356
360
|
});
|
|
357
361
|
|
|
362
|
+
/**
|
|
363
|
+
* The onboarding's "is your agent connected yet?". The page polls it, so the
|
|
364
|
+
* contract worth pinning is what it reads (one person's LIVE, USED rows of
|
|
365
|
+
* each kind — never the event log) and how the two kinds are combined.
|
|
366
|
+
*/
|
|
367
|
+
describe('AgentAuditService.lastAgentUse', () => {
|
|
368
|
+
it('answers null when neither an agent connection nor a key has been used', async () => {
|
|
369
|
+
const { service, counts } = makeService([[] /* connections */, [] /* keys */]);
|
|
370
|
+
await expect(service.lastAgentUse(ALICE.id)).resolves.toBeNull();
|
|
371
|
+
expect(counts.select).toBe(2);
|
|
372
|
+
});
|
|
373
|
+
|
|
374
|
+
it("reads only the caller's live, used rows of each kind", async () => {
|
|
375
|
+
const { service, captured } = makeService([[], []]);
|
|
376
|
+
await service.lastAgentUse(ALICE.id);
|
|
377
|
+
const [connections, keys] = captured.where.map(render);
|
|
378
|
+
expect(connections!.sql).toContain('"agent_connections"."user_id" = $1');
|
|
379
|
+
expect(connections!.sql).toContain('"agent_connections"."revoked_at" is null');
|
|
380
|
+
expect(connections!.sql).toContain('"agent_connections"."last_used_at" is not null');
|
|
381
|
+
expect(connections!.params).toEqual([ALICE.id]);
|
|
382
|
+
expect(keys!.sql).toContain('"api_tokens"."user_id" = $1');
|
|
383
|
+
expect(keys!.sql).toContain('"api_tokens"."revoked_at" is null');
|
|
384
|
+
expect(keys!.sql).toContain('"api_tokens"."last_used_at" is not null');
|
|
385
|
+
expect(keys!.params).toEqual([ALICE.id]);
|
|
386
|
+
});
|
|
387
|
+
|
|
388
|
+
it('keeps the most recently used row of each kind, of however many a person has', async () => {
|
|
389
|
+
// The fake neither sorts nor limits, so what is pinned is what each read
|
|
390
|
+
// asks the database for: newest use first, one row.
|
|
391
|
+
const { service, captured } = makeService([[], []]);
|
|
392
|
+
await service.lastAgentUse(ALICE.id);
|
|
393
|
+
expect(captured.orderBy.map((clauses) => clauses.map((c) => render(c).sql))).toEqual([
|
|
394
|
+
['"agent_connections"."last_used_at" desc'],
|
|
395
|
+
['"api_tokens"."last_used_at" desc'],
|
|
396
|
+
]);
|
|
397
|
+
expect(captured.limit).toEqual([1, 1]);
|
|
398
|
+
});
|
|
399
|
+
|
|
400
|
+
it("names an agent connection by its client, and an unnamed one as such", async () => {
|
|
401
|
+
const at = new Date(NOW - 60_000);
|
|
402
|
+
const named = makeService([[{ client: 'Claude', at }], []]);
|
|
403
|
+
await expect(named.service.lastAgentUse(ALICE.id)).resolves.toEqual({ at, client: 'Claude', kind: 'agent' });
|
|
404
|
+
const unnamed = makeService([[{ client: null, at }], []]);
|
|
405
|
+
await expect(unnamed.service.lastAgentUse(ALICE.id)).resolves.toEqual({ at, client: 'Unnamed agent', kind: 'agent' });
|
|
406
|
+
});
|
|
407
|
+
|
|
408
|
+
it('answers with the newer of the two when both kinds have been used', async () => {
|
|
409
|
+
const older = new Date(NOW - DAY);
|
|
410
|
+
const newer = new Date(NOW - 60_000);
|
|
411
|
+
const keyNewer = makeService([[{ client: 'Claude', at: older }], [{ client: 'Laptop', at: newer }]]);
|
|
412
|
+
await expect(keyNewer.service.lastAgentUse(ALICE.id)).resolves.toEqual({ at: newer, client: 'Laptop', kind: 'key' });
|
|
413
|
+
const agentNewer = makeService([[{ client: 'Claude', at: newer }], [{ client: 'Laptop', at: older }]]);
|
|
414
|
+
await expect(agentNewer.service.lastAgentUse(ALICE.id)).resolves.toEqual({ at: newer, client: 'Claude', kind: 'agent' });
|
|
415
|
+
});
|
|
416
|
+
});
|
|
417
|
+
|
|
358
418
|
describe('retentionDaysFrom', () => {
|
|
359
419
|
it('reads a positive whole number of days, and blank, zero or negative as forever', () => {
|
|
360
420
|
expect(retentionDaysFrom('30')).toBe(30);
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { afterEach, describe, expect, it, vi } from 'vitest';
|
|
2
|
+
import express from 'express';
|
|
3
|
+
import type { Server } from 'node:http';
|
|
4
|
+
import { createAgentConnectionRoutes } from '../agent-connection.routes.js';
|
|
5
|
+
import type { AgentUse, IAgentConnectionStatus } from '../audit.contract.js';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* GET /onboarding/agent-connection — what the connect-your-agent page polls.
|
|
9
|
+
* The contract worth pinning:
|
|
10
|
+
*
|
|
11
|
+
* - it answers for the AUTHENTICATED user (req.userId) and nobody else;
|
|
12
|
+
* nothing in the request — query or otherwise — can name another account;
|
|
13
|
+
* - "not yet" and "connected" are the two shapes, the second with when, as
|
|
14
|
+
* what, and whether that name is an agent's or a connection key's label;
|
|
15
|
+
* - the answer is never cached, since the next poll expects it to change;
|
|
16
|
+
* - a failure is a generic 500, never the driver's message.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
const ALICE = 'u-alice';
|
|
20
|
+
const BOB = 'u-bob';
|
|
21
|
+
const CARA = 'u-cara';
|
|
22
|
+
|
|
23
|
+
const USES: Record<string, AgentUse> = {
|
|
24
|
+
[BOB]: { at: new Date(Date.UTC(2026, 9, 7, 12, 0, 0)), client: 'Claude', kind: 'agent' },
|
|
25
|
+
[CARA]: { at: new Date(Date.UTC(2026, 9, 7, 13, 0, 0)), client: 'Laptop', kind: 'key' },
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const status = {
|
|
29
|
+
lastAgentUse: vi.fn(async (userId: string) => USES[userId] ?? null),
|
|
30
|
+
} satisfies IAgentConnectionStatus;
|
|
31
|
+
|
|
32
|
+
let server: Server | undefined;
|
|
33
|
+
afterEach(() => {
|
|
34
|
+
server?.close();
|
|
35
|
+
server = undefined;
|
|
36
|
+
vi.clearAllMocks();
|
|
37
|
+
vi.restoreAllMocks();
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
/** Mount the route with a stand-in auth middleware stamping `as` as the caller. */
|
|
41
|
+
async function listen(as: string): Promise<string> {
|
|
42
|
+
const app = express();
|
|
43
|
+
app.use((req, _res, next) => {
|
|
44
|
+
req.userId = as;
|
|
45
|
+
next();
|
|
46
|
+
});
|
|
47
|
+
app.use('/api', createAgentConnectionRoutes(status));
|
|
48
|
+
await new Promise<void>((resolve) => {
|
|
49
|
+
server = app.listen(0, resolve);
|
|
50
|
+
});
|
|
51
|
+
const address = server!.address();
|
|
52
|
+
if (typeof address === 'string' || !address) throw new Error('no port');
|
|
53
|
+
return `http://127.0.0.1:${address.port}`;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
describe('GET /onboarding/agent-connection', () => {
|
|
57
|
+
it('says "not yet" for a caller whose agents have not been used', async () => {
|
|
58
|
+
const base = await listen(ALICE);
|
|
59
|
+
const res = await fetch(`${base}/api/onboarding/agent-connection`);
|
|
60
|
+
expect(res.status).toBe(200);
|
|
61
|
+
expect(await res.json()).toEqual({ connected: false });
|
|
62
|
+
expect(status.lastAgentUse).toHaveBeenCalledWith(ALICE);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it('says connected, with when and as what, once one has', async () => {
|
|
66
|
+
const base = await listen(BOB);
|
|
67
|
+
const res = await fetch(`${base}/api/onboarding/agent-connection`);
|
|
68
|
+
expect(await res.json()).toEqual({ connected: true, at: '2026-10-07T12:00:00.000Z', client: 'Claude', kind: 'agent' });
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it("keeps a connection key's kind: its label says nothing about which app holds it", async () => {
|
|
72
|
+
const base = await listen(CARA);
|
|
73
|
+
const res = await fetch(`${base}/api/onboarding/agent-connection`);
|
|
74
|
+
expect(await res.json()).toEqual({ connected: true, at: '2026-10-07T13:00:00.000Z', client: 'Laptop', kind: 'key' });
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it("answers for the caller alone — a named account in the query is not asked about", async () => {
|
|
78
|
+
const base = await listen(ALICE);
|
|
79
|
+
const res = await fetch(`${base}/api/onboarding/agent-connection?userId=${BOB}&user=${BOB}`);
|
|
80
|
+
expect(await res.json()).toEqual({ connected: false });
|
|
81
|
+
expect(status.lastAgentUse).toHaveBeenCalledTimes(1);
|
|
82
|
+
expect(status.lastAgentUse).toHaveBeenCalledWith(ALICE);
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it('is never cached: the next poll expects a different answer', async () => {
|
|
86
|
+
const base = await listen(ALICE);
|
|
87
|
+
const res = await fetch(`${base}/api/onboarding/agent-connection`);
|
|
88
|
+
expect(res.headers.get('cache-control')).toBe('no-store');
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it('reports a failed read as a generic 500, keeping the detail server-side', async () => {
|
|
92
|
+
const detail = 'connection to 10.0.0.4:5432 refused';
|
|
93
|
+
status.lastAgentUse.mockRejectedValueOnce(new Error(detail));
|
|
94
|
+
vi.spyOn(console, 'error').mockImplementation(() => {});
|
|
95
|
+
const base = await listen(ALICE);
|
|
96
|
+
const res = await fetch(`${base}/api/onboarding/agent-connection`);
|
|
97
|
+
expect(res.status).toBe(500);
|
|
98
|
+
const body = (await res.json()) as { error: string };
|
|
99
|
+
expect(body.error).toBe('Could not check your agent');
|
|
100
|
+
expect(body.error).not.toContain(detail);
|
|
101
|
+
});
|
|
102
|
+
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { and, count, desc, eq, isNull, lt, or, type SQL } from 'drizzle-orm';
|
|
1
|
+
import { and, count, desc, eq, isNotNull, isNull, lt, or, type SQL } from 'drizzle-orm';
|
|
2
2
|
import { logger } from '../../shared/logging.js';
|
|
3
3
|
import type { Database } from '../database/connection.js';
|
|
4
|
-
import { agentConnections, agentEvents, oauthTokens, users } from '../database/schema.js';
|
|
4
|
+
import { agentConnections, agentEvents, externalApiKeys, oauthTokens, users } from '../database/schema.js';
|
|
5
5
|
import type { IExternalApiKeyService } from '../tool-auth/external-api-key.interface.js';
|
|
6
6
|
import {
|
|
7
7
|
AuditPrincipalNotFoundError,
|
|
@@ -11,10 +11,12 @@ import {
|
|
|
11
11
|
type AgentEventInput,
|
|
12
12
|
type AgentEventPage,
|
|
13
13
|
type AgentEventView,
|
|
14
|
+
type AgentUse,
|
|
14
15
|
type AuditPrincipal,
|
|
15
16
|
type AuditPrincipalRef,
|
|
16
17
|
type AuditScope,
|
|
17
18
|
type IAgentAuditService,
|
|
19
|
+
type IAgentConnectionStatus,
|
|
18
20
|
type IAgentEventRecorder,
|
|
19
21
|
} from './audit.contract.js';
|
|
20
22
|
|
|
@@ -39,7 +41,7 @@ const PRUNE_INTERVAL_MS = 60 * 60_000;
|
|
|
39
41
|
* Connection keys are read through the key service rather than joined here,
|
|
40
42
|
* so their summary shape (kind, revoked-by, …) has exactly one definition.
|
|
41
43
|
*/
|
|
42
|
-
export class AgentAuditService implements IAgentAuditService, IAgentEventRecorder {
|
|
44
|
+
export class AgentAuditService implements IAgentAuditService, IAgentEventRecorder, IAgentConnectionStatus {
|
|
43
45
|
private lastPruneAt = 0;
|
|
44
46
|
|
|
45
47
|
constructor(
|
|
@@ -242,6 +244,59 @@ export class AgentAuditService implements IAgentAuditService, IAgentEventRecorde
|
|
|
242
244
|
};
|
|
243
245
|
}
|
|
244
246
|
|
|
247
|
+
/**
|
|
248
|
+
* Whether one person's agent has reached the platform yet — what the
|
|
249
|
+
* onboarding asks once on arrival (the `agent-connected` event the stamp
|
|
250
|
+
* paths emit tells it the moment it changes). Two single-row reads on the
|
|
251
|
+
* per-user indexes, never a scan of the event log.
|
|
252
|
+
*
|
|
253
|
+
* Read from the `last_used_at` stamps, not from `agent_events`: an agent
|
|
254
|
+
* stamps its connection (or key) on its FIRST authenticated request — the
|
|
255
|
+
* `initialize` / `tools/list` every client sends straight after connecting
|
|
256
|
+
* — while an event is written only once it calls a tool, which may be
|
|
257
|
+
* never. The stamps are also outside the retention sweep, so "connected"
|
|
258
|
+
* cannot quietly turn back into "waiting" when old events are pruned.
|
|
259
|
+
*
|
|
260
|
+
* Live rows only: an agent its owner disconnected, or an admin revoked, is
|
|
261
|
+
* not a connected agent, whatever it did before. The key's columns are read
|
|
262
|
+
* here rather than through the key service because the service has no
|
|
263
|
+
* single-row read and this question needs only two columns of one row.
|
|
264
|
+
*/
|
|
265
|
+
async lastAgentUse(userId: string): Promise<AgentUse | null> {
|
|
266
|
+
const [[agent], [key]] = await Promise.all([
|
|
267
|
+
this.db
|
|
268
|
+
.select({ client: agentConnections.clientName, at: agentConnections.lastUsedAt })
|
|
269
|
+
.from(agentConnections)
|
|
270
|
+
.where(
|
|
271
|
+
and(
|
|
272
|
+
eq(agentConnections.userId, userId),
|
|
273
|
+
isNull(agentConnections.revokedAt),
|
|
274
|
+
isNotNull(agentConnections.lastUsedAt),
|
|
275
|
+
),
|
|
276
|
+
)
|
|
277
|
+
.orderBy(desc(agentConnections.lastUsedAt))
|
|
278
|
+
.limit(1),
|
|
279
|
+
this.db
|
|
280
|
+
.select({ client: externalApiKeys.label, at: externalApiKeys.lastUsedAt })
|
|
281
|
+
.from(externalApiKeys)
|
|
282
|
+
.where(
|
|
283
|
+
and(
|
|
284
|
+
eq(externalApiKeys.userId, userId),
|
|
285
|
+
isNull(externalApiKeys.revokedAt),
|
|
286
|
+
isNotNull(externalApiKeys.lastUsedAt),
|
|
287
|
+
),
|
|
288
|
+
)
|
|
289
|
+
.orderBy(desc(externalApiKeys.lastUsedAt))
|
|
290
|
+
.limit(1),
|
|
291
|
+
]);
|
|
292
|
+
const uses = [
|
|
293
|
+
agent?.at ? { at: agent.at, client: agent.client ?? 'Unnamed agent', kind: 'agent' as const } : null,
|
|
294
|
+
key?.at ? { at: key.at, client: key.client, kind: 'key' as const } : null,
|
|
295
|
+
].filter((u): u is AgentUse => u !== null);
|
|
296
|
+
if (uses.length === 0) return null;
|
|
297
|
+
return uses.reduce((newest, u) => (u.at.getTime() > newest.at.getTime() ? u : newest));
|
|
298
|
+
}
|
|
299
|
+
|
|
245
300
|
async revokeConnection(id: string, by: 'owner' | 'admin', ownerUserId?: string): Promise<void> {
|
|
246
301
|
const scope = ownerUserId
|
|
247
302
|
? and(eq(agentConnections.id, id), eq(agentConnections.userId, ownerUserId))!
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import express from 'express';
|
|
2
|
+
import { logger } from '../../shared/logging.js';
|
|
3
|
+
import type { IAgentConnectionStatus } from './audit.contract.js';
|
|
4
|
+
import '../auth/auth.middleware.js'; // Express Request augmentation (req.userId)
|
|
5
|
+
|
|
6
|
+
const log = logger('audit');
|
|
7
|
+
|
|
8
|
+
/** What the onboarding reads: connected or not, and — once connected — when, as what, and through which kind of credential. */
|
|
9
|
+
export interface AgentConnectionResponse {
|
|
10
|
+
connected: boolean;
|
|
11
|
+
/** The agent's most recent call, ISO 8601. */
|
|
12
|
+
at?: string;
|
|
13
|
+
/** The agent's registered client name, or the connection key's label. */
|
|
14
|
+
client?: string;
|
|
15
|
+
/**
|
|
16
|
+
* Which of the two `client` is: `agent` for an OAuth connection's
|
|
17
|
+
* registered name, `key` for a connection key's free-text label. Only an
|
|
18
|
+
* `agent` name says which app connected.
|
|
19
|
+
*/
|
|
20
|
+
kind?: 'agent' | 'key';
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* GET /api/onboarding/agent-connection — "has an agent of mine reached the
|
|
25
|
+
* platform yet?", JWT-only (mounted behind the session middleware).
|
|
26
|
+
*
|
|
27
|
+
* The connect-your-agent page and the Get set up list ask it once on
|
|
28
|
+
* arrival, and again when the person comes back to the tab; the moment it
|
|
29
|
+
* changes is told by the `agent-connected` event the use-stamp paths emit
|
|
30
|
+
* over the event stream, so nothing asks on a timer. It answers for the
|
|
31
|
+
* CALLER alone: the user is the token's, and nothing in the request can name
|
|
32
|
+
* anyone else — there is no parameter to try.
|
|
33
|
+
*
|
|
34
|
+
* `no-store` because the answer is expected to change between two asks; a
|
|
35
|
+
* cached "not yet" would keep a page waiting on an agent that has already
|
|
36
|
+
* arrived.
|
|
37
|
+
*/
|
|
38
|
+
export function createAgentConnectionRoutes(status: IAgentConnectionStatus): express.Router {
|
|
39
|
+
const router = express.Router();
|
|
40
|
+
|
|
41
|
+
router.get('/onboarding/agent-connection', async (req, res) => {
|
|
42
|
+
res.set('Cache-Control', 'no-store');
|
|
43
|
+
try {
|
|
44
|
+
const use = await status.lastAgentUse(req.userId!);
|
|
45
|
+
const body: AgentConnectionResponse = use
|
|
46
|
+
? { connected: true, at: use.at.toISOString(), client: use.client, kind: use.kind }
|
|
47
|
+
: { connected: false };
|
|
48
|
+
res.json(body);
|
|
49
|
+
} catch (err) {
|
|
50
|
+
log.error('agent connection status failed:', { err });
|
|
51
|
+
res.status(500).json({ error: 'Could not check your agent' });
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
return router;
|
|
56
|
+
}
|
|
@@ -121,6 +121,32 @@ export interface IAgentAuditService {
|
|
|
121
121
|
revokeConnection(id: string, by: 'owner' | 'admin', ownerUserId?: string): Promise<void>;
|
|
122
122
|
}
|
|
123
123
|
|
|
124
|
+
/**
|
|
125
|
+
* The most recent use of any of one person's live agents: when, what it
|
|
126
|
+
* calls itself (the agent's registered client name, or the key's label), and
|
|
127
|
+
* which of the two that name is.
|
|
128
|
+
*/
|
|
129
|
+
export interface AgentUse {
|
|
130
|
+
at: Date;
|
|
131
|
+
client: string;
|
|
132
|
+
/**
|
|
133
|
+
* `agent`: an OAuth connection, and `client` is the name the agent
|
|
134
|
+
* registered. `key`: a connection key, and `client` is whatever label its
|
|
135
|
+
* owner typed — it says nothing about which app holds the key.
|
|
136
|
+
*/
|
|
137
|
+
kind: 'agent' | 'key';
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* The onboarding's "is your agent connected yet?" — answered for ONE person,
|
|
142
|
+
* from the use stamps the auth paths already write, so it costs two indexed
|
|
143
|
+
* single-row reads and records nothing new.
|
|
144
|
+
*/
|
|
145
|
+
export interface IAgentConnectionStatus {
|
|
146
|
+
/** The newest use among the person's live agent connections and connection keys; null when none has been used. */
|
|
147
|
+
lastAgentUse(userId: string): Promise<AgentUse | null>;
|
|
148
|
+
}
|
|
149
|
+
|
|
124
150
|
export class AuditPrincipalNotFoundError extends Error {
|
|
125
151
|
constructor() {
|
|
126
152
|
super('No such agent or key');
|
|
@@ -2,6 +2,7 @@ export * from './audit.contract.js';
|
|
|
2
2
|
export { AgentAuditService, MAX_EVENT_PAGE, retentionDaysFrom } from './agent-audit.service.js';
|
|
3
3
|
export { createAgentRestAuditMiddleware } from './agent-rest-audit.middleware.js';
|
|
4
4
|
export { createAuditRoutes } from './audit.routes.js';
|
|
5
|
+
export { createAgentConnectionRoutes, type AgentConnectionResponse } from './agent-connection.routes.js';
|
|
5
6
|
export { RequestAudit } from './request-audit.js';
|
|
6
7
|
export {
|
|
7
8
|
classifyToolCall,
|
|
@@ -67,6 +67,8 @@ describe('account routes — admin gate', () => {
|
|
|
67
67
|
body: JSON.stringify({ email: 'x@example.com', password: 'long-enough-pw' }),
|
|
68
68
|
});
|
|
69
69
|
expect(create.status).toBe(403);
|
|
70
|
+
// Not an admission refusal: nothing here may read as "no seat left".
|
|
71
|
+
expect(await create.json()).toEqual({ error: 'Admins only' });
|
|
70
72
|
expect(authService.createAccount).not.toHaveBeenCalled();
|
|
71
73
|
});
|
|
72
74
|
|
|
@@ -151,7 +153,7 @@ describe('account routes — admin gate', () => {
|
|
|
151
153
|
expect(accountErasure.eraseUser).toHaveBeenLastCalledWith('u2');
|
|
152
154
|
});
|
|
153
155
|
|
|
154
|
-
it('an account the admission port refuses → 403 carrying the port\'s own words', async () => {
|
|
156
|
+
it('an account the admission port refuses → 403 carrying the port\'s own words, marked as an admission refusal', async () => {
|
|
155
157
|
const base = await listen(makeApp({ admin: true }));
|
|
156
158
|
vi.mocked(authService.createAccount).mockRejectedValueOnce(
|
|
157
159
|
new AccountAdmissionRefusedError('No seat left on this plan'),
|
|
@@ -162,7 +164,7 @@ describe('account routes — admin gate', () => {
|
|
|
162
164
|
body: JSON.stringify({ email: 'b@example.com', password: 'long-enough-pw' }),
|
|
163
165
|
});
|
|
164
166
|
expect(refused.status).toBe(403);
|
|
165
|
-
expect(
|
|
167
|
+
expect(await refused.json()).toEqual({ error: 'No seat left on this plan', kind: 'admission' });
|
|
166
168
|
});
|
|
167
169
|
|
|
168
170
|
it('erasure failure → 500 with a generic body (no internal error text)', async () => {
|
|
@@ -370,7 +372,7 @@ describe('account routes — switching an account off and on', () => {
|
|
|
370
372
|
const base = await listen(makeApp({ admin: true }));
|
|
371
373
|
const res = await post(base, 'u2/reactivate');
|
|
372
374
|
expect(res.status).toBe(403);
|
|
373
|
-
expect(
|
|
375
|
+
expect(await res.json()).toEqual({ error: 'All 3 seats are taken', kind: 'admission' });
|
|
374
376
|
});
|
|
375
377
|
|
|
376
378
|
it('answers a refused deactivation (the deployment admin, say) with 400 and the reason', async () => {
|
|
@@ -73,7 +73,13 @@ export function createAccountRoutes(
|
|
|
73
73
|
const msg = error instanceof Error ? error.message : 'Unknown error';
|
|
74
74
|
// The deployment has no place for the account (a seat limit, say): the
|
|
75
75
|
// port's own words, as a refusal rather than a malformed request.
|
|
76
|
-
|
|
76
|
+
// `kind` tells it apart from `requireAdmin`'s 403, which a caller must
|
|
77
|
+
// not read as "no seat left".
|
|
78
|
+
if (error instanceof AccountAdmissionRefusedError) {
|
|
79
|
+
res.status(403).json({ error: msg, kind: 'admission' });
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
res.status(400).json({ error: msg });
|
|
77
83
|
}
|
|
78
84
|
});
|
|
79
85
|
|
|
@@ -107,7 +113,8 @@ export function createAccountRoutes(
|
|
|
107
113
|
|
|
108
114
|
// POST /api/admin/accounts/:userId/reactivate — switch it back on, if the
|
|
109
115
|
// deployment has room: the admission port is asked, as for a new account
|
|
110
|
-
// (a host that sells seats answers from its plan; 403 with its words
|
|
116
|
+
// (a host that sells seats answers from its plan; 403 with its words and
|
|
117
|
+
// `kind: 'admission'`).
|
|
111
118
|
router.post('/admin/accounts/:userId/reactivate', requireAdmin, async (req, res) => {
|
|
112
119
|
const userId = String(req.params.userId);
|
|
113
120
|
try {
|
|
@@ -119,7 +126,7 @@ export function createAccountRoutes(
|
|
|
119
126
|
res.status(204).end();
|
|
120
127
|
} catch (error) {
|
|
121
128
|
if (error instanceof AccountAdmissionRefusedError) {
|
|
122
|
-
res.status(403).json({ error: error.message });
|
|
129
|
+
res.status(403).json({ error: error.message, kind: 'admission' });
|
|
123
130
|
return;
|
|
124
131
|
}
|
|
125
132
|
log.error('switching an account on failed:', { err: error });
|
|
@@ -30,7 +30,7 @@ export const AUTH_COOKIE_NAME = 'bevel_token';
|
|
|
30
30
|
* beats the dep surface of a middleware. Returns `null` if the cookie
|
|
31
31
|
* is absent or empty.
|
|
32
32
|
*/
|
|
33
|
-
function readAuthCookie(req: Request): string | null {
|
|
33
|
+
export function readAuthCookie(req: Request): string | null {
|
|
34
34
|
const header = req.headers.cookie;
|
|
35
35
|
if (!header) return null;
|
|
36
36
|
for (const segment of header.split(';')) {
|
|
@@ -27,6 +27,16 @@ vi.mock('../code-mode-names.js', async (importOriginal) => {
|
|
|
27
27
|
}
|
|
28
28
|
if (name === 'down.run') throw new Error('repository unavailable: ECONNREFUSED');
|
|
29
29
|
if (name === 'solo.run') return { tool: { name: 'solo.run' }, utcpName: 'solo.run' };
|
|
30
|
+
if (name === 'kb.read_file') {
|
|
31
|
+
return {
|
|
32
|
+
tool: {
|
|
33
|
+
name: 'kb.read_file',
|
|
34
|
+
description: 'Read a file.',
|
|
35
|
+
inputs: { type: 'object', properties: { query: { type: 'string' } }, required: ['query'] },
|
|
36
|
+
},
|
|
37
|
+
utcpName: 'kb.read_file',
|
|
38
|
+
};
|
|
39
|
+
}
|
|
30
40
|
return null;
|
|
31
41
|
}),
|
|
32
42
|
};
|
|
@@ -35,7 +45,8 @@ vi.mock('../code-mode-names.js', async (importOriginal) => {
|
|
|
35
45
|
const { createToolsInfoTool } = await import('../code-mode.tool.js');
|
|
36
46
|
|
|
37
47
|
const client = {
|
|
38
|
-
toolToTypeScriptInterface: (tool: { name: string }) =>
|
|
48
|
+
toolToTypeScriptInterface: (tool: { name: string; description?: string }) =>
|
|
49
|
+
tool.description ? `/** ${tool.description} */ interface ${tool.name}` : `interface ${tool.name}`,
|
|
39
50
|
} as unknown as CodeModeUtcpClient;
|
|
40
51
|
|
|
41
52
|
type ToolsInfoResult = { interfaces: string; not_found: string[]; errors?: string[] };
|
|
@@ -58,11 +69,16 @@ describe('tools_info', () => {
|
|
|
58
69
|
|
|
59
70
|
it('omits the errors field entirely when every name resolves or misses cleanly', async () => {
|
|
60
71
|
const result = await run(['solo.run', 'nope']);
|
|
61
|
-
expect(result.interfaces).toBe('interface solo.run');
|
|
72
|
+
expect(result.interfaces).toBe('/** Call: solo.run({}) */ interface solo.run');
|
|
62
73
|
expect(result.not_found).toEqual(['nope']);
|
|
63
74
|
expect(result.errors).toBeUndefined();
|
|
64
75
|
});
|
|
65
76
|
|
|
77
|
+
it('shows each tool with its Call: line, as the chain description promises', async () => {
|
|
78
|
+
const result = await run(['kb.read_file']);
|
|
79
|
+
expect(result.interfaces).toBe('/** Call: kb.read_file({ query: "..." })\n\nRead a file. */ interface kb.read_file');
|
|
80
|
+
});
|
|
81
|
+
|
|
66
82
|
it('contains ONLY ambiguity — an outage rethrows instead of posing as partial success', async () => {
|
|
67
83
|
await expect(run(['solo.run', 'down.run'])).rejects.toThrow(/repository unavailable/);
|
|
68
84
|
});
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
chainExample,
|
|
12
12
|
type ChainExampleTool,
|
|
13
13
|
runToolChain,
|
|
14
|
+
withCallExample,
|
|
14
15
|
} from '@bevel-software/platform-mcp-core';
|
|
15
16
|
import type { SpillStore } from '../workspace/spill-store.js';
|
|
16
17
|
import { utcpNameToTsInterfaceName, findToolByName, AmbiguousToolNameError } from './code-mode-names.js';
|
|
@@ -46,7 +47,8 @@ export function createCallToolChainTool(
|
|
|
46
47
|
id: 'call_tool_chain',
|
|
47
48
|
description: [
|
|
48
49
|
CodeModeUtcpClient.AGENT_PROMPT_TEMPLATE,
|
|
49
|
-
`Execute JavaScript code with direct access to all registered UTCP tools as hierarchical functions
|
|
50
|
+
`Execute JavaScript code with direct access to all registered UTCP tools as hierarchical functions, synchronous, no await.${worked} The runtime is plain JavaScript — no type annotations or other TypeScript-only syntax — plus \`atob\`, \`btoa\`, \`TextEncoder\` and \`TextDecoder\` for base64 and UTF-8 bytes, as in a browser; there is no \`Buffer\`, no \`fetch\` and no \`require\`. Return the final value with \`return\`. Use \`list_tools\` and \`tools_info\` first to discover available tools and their interfaces.`,
|
|
51
|
+
`There is NO single calling shape: some tools take their arguments under a \`body\` object, others take them flat. Call each tool as the \`Call:\` line at the top of its own description shows — it is generated from that tool's input schema, and every tool in \`${ns}\` has one. Every argument a tool declares REQUIRED must be present; for the knowledge-base tools that includes \`branch\`. Arguments that do not match the schema are refused before anything is sent or run, and the refusal carries the tool's interface.`,
|
|
50
52
|
'Error handling inside the chain: a failing tool call THROWS, and the thrown error\'s `.message` holds the server\'s actual reason (e.g. a 403 with the explanation, not just a status code). If you catch it, surface `err.message` (and `err.status` / `err.data` when present) — NEVER `return { error: err }` or otherwise return the raw Error object, because an Error serializes to `{}` (its `message` is non-enumerable) and the reason is lost. If you don\'t need to handle it, just let it throw — the runtime already reports `err.message` back to you.',
|
|
51
53
|
`Failures are answered, never dropped: a chain that throws comes back with \`success: false\` and the reason, and one that outlives \`timeout\` (default ${CHAIN_TIMEOUT_DEFAULT_MS} ms, maximum ${CHAIN_TIMEOUT_MAX_MS} ms) comes back saying it timed out — raise \`timeout\` or split the work and run it again. Either way your next tool call works as usual.`,
|
|
52
54
|
'Large return values: if the returned value exceeds `max_output_size`, the full JSON is auto-spilled to a shared spill store (outside any workspace, never committed) and the response contains only a `__tool_chain_spill__/…` ref + a truncated marker. You can read the spill back with the regular `read_file` tool — pass that ref as `path` (its `branch` is ignored) plus `offset` / `limit` to slice it, never read a multi-MB file in full. Order of preference: (1) re-run `call_tool_chain` with a follow-up code chain that filters/maps the data inline and returns just what you need; (2) narrow the API call — shorter `fields`, tighter date window, lower `limit`; (3) last resort — `read_file` against the spill ref with `offset` / `limit`. The spill is read-only context only; do NOT use it as a way to persist KB content — for KB writes use the regular `write_file` / `edit_file` tools, which go through the lock/commit pipeline.',
|
|
@@ -176,7 +178,16 @@ export function createToolsInfoTool(client: CodeModeUtcpClient) {
|
|
|
176
178
|
try {
|
|
177
179
|
const found = await findToolByName(client, name);
|
|
178
180
|
if (found) {
|
|
179
|
-
|
|
181
|
+
// With its `Call:` line, as on the MCP surface (`meta-tools.ts`):
|
|
182
|
+
// the chain's description tells the agent to call each tool as
|
|
183
|
+
// that line shows, and this is where it reads the tool. The
|
|
184
|
+
// repository's tool is not ours to edit, so a copy carries it.
|
|
185
|
+
interfaces.push(
|
|
186
|
+
client.toolToTypeScriptInterface({
|
|
187
|
+
...found.tool,
|
|
188
|
+
description: withCallExample(found.tool.description, found.utcpName, found.tool.inputs),
|
|
189
|
+
}),
|
|
190
|
+
);
|
|
180
191
|
} else {
|
|
181
192
|
notFound.push(name);
|
|
182
193
|
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* CORE platform tables — the git-backed workspace/workflow, auth, access,
|
|
3
3
|
* change requests, locks, the pending-commits queue, connection keys, MCP
|
|
4
|
-
* OAuth,
|
|
5
|
-
* exactly these tables.
|
|
4
|
+
* OAuth, the Secrets Vault, and the embed's Atlassian account links. A
|
|
5
|
+
* core-only deployment migrates and runs on exactly these tables.
|
|
6
6
|
*
|
|
7
7
|
* Enterprise-only tables (chat, routines, watchlist, connectors, LLM config,
|
|
8
|
-
* SharePoint
|
|
8
|
+
* SharePoint links, feedback, upload, kb-revalidation) live in
|
|
9
9
|
* `enterprise-schema.ts`, which imports the FK targets (`users`,
|
|
10
10
|
* `externalApiKeys`) from here. `schema.ts` re-exports both, so existing
|
|
11
11
|
* imports keep working unchanged.
|
|
@@ -829,3 +829,33 @@ export const pluginJoinRequests = pgTable('plugin_join_requests', {
|
|
|
829
829
|
sql`${t.status} IN ('pending', 'opened', 'failed')`,
|
|
830
830
|
),
|
|
831
831
|
}));
|
|
832
|
+
|
|
833
|
+
/**
|
|
834
|
+
* Links an account from an outside system — today an Atlassian (Forge)
|
|
835
|
+
* account id — to a Hexis user, so an embed minted for that account resolves
|
|
836
|
+
* to a person whose read and write access the view obeys.
|
|
837
|
+
*
|
|
838
|
+
* KEPT UNDER ITS ENTERPRISE NAME, deliberately. The table was created by the
|
|
839
|
+
* Bevel Platform's own migration history before the embed moved into Hexis;
|
|
840
|
+
* an upgraded database already holds every link its Jira users made, and
|
|
841
|
+
* nobody is going to re-link. So the core migration creates it only if it is
|
|
842
|
+
* absent and adopts what is there otherwise (see
|
|
843
|
+
* `0017_atlassian_account_links.sql`), and the generic name this table
|
|
844
|
+
* deserves is not worth a data migration for a column nobody reads by name.
|
|
845
|
+
*
|
|
846
|
+
* Not sealed: an Atlassian account id is an opaque identifier from another
|
|
847
|
+
* system, which is the same reason the rest of those are left in the clear.
|
|
848
|
+
*
|
|
849
|
+
* PK is the account id — one Hexis user per Atlassian account — while one
|
|
850
|
+
* user may hold several account ids across sites, which is what `by_user`
|
|
851
|
+
* serves. Links die with the user (`onDelete: 'cascade'`): an erasure request
|
|
852
|
+
* must never be blocked by a leftover embed link.
|
|
853
|
+
*/
|
|
854
|
+
export const atlassianAccountLinks = pgTable('atlassian_account_links', {
|
|
855
|
+
atlassianAccountId: text('atlassian_account_id').primaryKey(),
|
|
856
|
+
userId: uuid('user_id').notNull().references(() => users.id, { onDelete: 'cascade' }),
|
|
857
|
+
createdAt: timestamp('created_at').defaultNow().notNull(),
|
|
858
|
+
updatedAt: timestamp('updated_at').defaultNow().notNull(),
|
|
859
|
+
}, (t) => ({
|
|
860
|
+
byUser: index('atlassian_account_links_by_user').on(t.userId),
|
|
861
|
+
}));
|