@bevel-software/platform-core-backend 0.26.0 → 0.28.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 +17 -0
- package/agent-guide/conventions.md +8 -0
- package/agent-guide/html-views.md +83 -0
- package/agent-guide/new-knowledge-base.md +24 -0
- package/agent-guide/tool-manuals.md +10 -0
- package/dist/assets.d.ts +19 -0
- package/dist/assets.d.ts.map +1 -1
- package/dist/assets.js +26 -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/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 +56 -5
- package/dist/core/create-core-server.js.map +1 -1
- package/dist/core/create-core-services.d.ts +33 -0
- package/dist/core/create-core-services.d.ts.map +1 -1
- package/dist/core/create-core-services.js +105 -8
- 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 +31 -0
- package/dist/modules/access/access-control.service.js.map +1 -1
- package/dist/modules/access/access.routes.d.ts +4 -1
- package/dist/modules/access/access.routes.d.ts.map +1 -1
- package/dist/modules/access/access.routes.js +66 -7
- package/dist/modules/access/access.routes.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/access/roles-admin.service.d.ts +35 -6
- package/dist/modules/access/roles-admin.service.d.ts.map +1 -1
- package/dist/modules/access/roles-admin.service.js +36 -9
- package/dist/modules/access/roles-admin.service.js.map +1 -1
- package/dist/modules/access/user-access-removal.service.js +1 -1
- package/dist/modules/access/user-access-removal.service.js.map +1 -1
- package/dist/modules/agent-guide/agent-guide.d.ts +6 -0
- package/dist/modules/agent-guide/agent-guide.d.ts.map +1 -1
- package/dist/modules/agent-guide/agent-guide.js +8 -0
- package/dist/modules/agent-guide/agent-guide.js.map +1 -1
- package/dist/modules/agent-guide/index.d.ts +1 -1
- package/dist/modules/agent-guide/index.d.ts.map +1 -1
- package/dist/modules/agent-guide/index.js +1 -1
- package/dist/modules/agent-guide/index.js.map +1 -1
- package/dist/modules/agent-instructions/compose.d.ts +5 -0
- package/dist/modules/agent-instructions/compose.d.ts.map +1 -1
- package/dist/modules/agent-instructions/compose.js +19 -2
- package/dist/modules/agent-instructions/compose.js.map +1 -1
- package/dist/modules/agent-instructions/shared-file-rules.js +19 -19
- 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-hooks.d.ts +46 -0
- package/dist/modules/auth/account-hooks.d.ts.map +1 -0
- package/dist/modules/auth/account-hooks.js +25 -0
- package/dist/modules/auth/account-hooks.js.map +1 -0
- package/dist/modules/auth/account-switch-guard.d.ts +15 -0
- package/dist/modules/auth/account-switch-guard.d.ts.map +1 -0
- package/dist/modules/auth/account-switch-guard.js +2 -0
- package/dist/modules/auth/account-switch-guard.js.map +1 -0
- package/dist/modules/auth/account-switch-lock.d.ts +34 -0
- package/dist/modules/auth/account-switch-lock.d.ts.map +1 -0
- package/dist/modules/auth/account-switch-lock.js +48 -0
- package/dist/modules/auth/account-switch-lock.js.map +1 -0
- package/dist/modules/auth/account.routes.d.ts +4 -1
- package/dist/modules/auth/account.routes.d.ts.map +1 -1
- package/dist/modules/auth/account.routes.js +110 -13
- 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/auth/auth.service.d.ts +101 -6
- package/dist/modules/auth/auth.service.d.ts.map +1 -1
- package/dist/modules/auth/auth.service.js +246 -51
- package/dist/modules/auth/auth.service.js.map +1 -1
- package/dist/modules/auth/password-hash.d.ts +5 -2
- package/dist/modules/auth/password-hash.d.ts.map +1 -1
- package/dist/modules/auth/password-hash.js +5 -2
- package/dist/modules/auth/password-hash.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/database/pg-error.d.ts +9 -0
- package/dist/modules/database/pg-error.d.ts.map +1 -0
- package/dist/modules/database/pg-error.js +17 -0
- package/dist/modules/database/pg-error.js.map +1 -0
- 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 +28 -1
- package/dist/modules/mcp/mcp.service.d.ts.map +1 -1
- package/dist/modules/mcp/mcp.service.js +64 -8
- 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/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/settings/deployment-settings.service.d.ts +34 -0
- package/dist/modules/settings/deployment-settings.service.d.ts.map +1 -1
- package/dist/modules/settings/deployment-settings.service.js +134 -1
- 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/skills/skills.tools.d.ts.map +1 -1
- package/dist/modules/skills/skills.tools.js +50 -32
- 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.tools.d.ts.map +1 -1
- package/dist/modules/tool-manuals/tool-manuals.tools.js +14 -5
- package/dist/modules/tool-manuals/tool-manuals.tools.js.map +1 -1
- package/dist/modules/tool-registry/description-length.d.ts +6 -2
- package/dist/modules/tool-registry/description-length.d.ts.map +1 -1
- package/dist/modules/tool-registry/description-length.js +27 -5
- package/dist/modules/tool-registry/description-length.js.map +1 -1
- package/dist/modules/tool-registry/guide-first.d.ts +4 -0
- package/dist/modules/tool-registry/guide-first.d.ts.map +1 -1
- package/dist/modules/tool-registry/guide-first.js +9 -1
- package/dist/modules/tool-registry/guide-first.js.map +1 -1
- package/dist/modules/workflow/agent-tools/change-request-read.tools.d.ts +53 -0
- package/dist/modules/workflow/agent-tools/change-request-read.tools.d.ts.map +1 -1
- package/dist/modules/workflow/agent-tools/change-request-read.tools.js +97 -68
- package/dist/modules/workflow/agent-tools/change-request-read.tools.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 +124 -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 +72 -1
- package/dist/modules/workflow/git/git.service.d.ts.map +1 -1
- package/dist/modules/workflow/git/git.service.js +172 -36
- package/dist/modules/workflow/git/git.service.js.map +1 -1
- 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/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.map +1 -1
- package/dist/modules/workflow/review-workflow/review-workflow.service.js +2 -1
- 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.service.d.ts +183 -15
- package/dist/modules/workflow/workflow.service.d.ts.map +1 -1
- package/dist/modules/workflow/workflow.service.js +807 -107
- 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 +3 -13
- package/dist/modules/workspace/startup/steps/seed-tree.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 +59 -1
- package/dist/modules/workspace/workspace.tools.d.ts.map +1 -1
- package/dist/modules/workspace/workspace.tools.js +443 -65
- 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 +73 -1
- package/dist/shared/domain-errors.d.ts.map +1 -1
- package/dist/shared/domain-errors.js +86 -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/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/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 +5 -3
- package/src/__tests__/packaged-assets-ship.test.ts +16 -4
- package/src/__tests__/pg-scratch.ts +48 -0
- package/src/assets.ts +28 -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/create-core-server.ts +69 -3
- package/src/core/create-core-services.ts +151 -6
- 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.admin-root-floor.test.ts +1 -0
- package/src/modules/access/__tests__/access-control.service.test.ts +19 -0
- package/src/modules/access/__tests__/access.routes.admins.test.ts +203 -0
- package/src/modules/access/__tests__/access.routes.batch.test.ts +25 -5
- package/src/modules/access/__tests__/access.routes.folder-governs.test.ts +1 -0
- package/src/modules/access/__tests__/access.routes.group-grant.test.ts +1 -1
- package/src/modules/access/__tests__/access.routes.overrides.test.ts +1 -1
- package/src/modules/access/__tests__/access.routes.proposal-branch.test.ts +1 -0
- package/src/modules/access/__tests__/access.routes.prospective.test.ts +1 -0
- package/src/modules/access/__tests__/access.routes.revoke.test.ts +1 -1
- package/src/modules/access/__tests__/access.routes.unknown-email.test.ts +1 -0
- package/src/modules/access/__tests__/roles-admin.security.test.ts +1 -1
- package/src/modules/access/__tests__/roles-admin.service.test.ts +15 -2
- package/src/modules/access/__tests__/roles.routes.test.ts +132 -7
- package/src/modules/access/__tests__/user-access-removal.service.test.ts +2 -2
- package/src/modules/access/__tests__/users-db-double.ts +12 -3
- package/src/modules/access/access-control.interface.ts +23 -0
- package/src/modules/access/access-control.service.ts +35 -0
- package/src/modules/access/access.routes.ts +67 -6
- package/src/modules/access/directory-sync-bot.ts +1 -1
- package/src/modules/access/roles-admin.service.ts +51 -11
- package/src/modules/access/user-access-removal.service.ts +1 -1
- package/src/modules/agent-guide/__tests__/agent-guide.test.ts +58 -0
- package/src/modules/agent-guide/__tests__/agent-guide.tools.test.ts +19 -1
- package/src/modules/agent-guide/agent-guide.ts +9 -0
- package/src/modules/agent-guide/index.ts +1 -0
- package/src/modules/agent-instructions/__tests__/shared-file-rules.test.ts +14 -0
- package/src/modules/agent-instructions/compose.ts +17 -2
- package/src/modules/agent-instructions/shared-file-rules.ts +19 -19
- 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-deactivation.test.ts +145 -16
- package/src/modules/auth/__tests__/account-hooks.test.ts +57 -0
- package/src/modules/auth/__tests__/account-switch-lock.pg.test.ts +78 -0
- package/src/modules/auth/__tests__/account-switch-lock.test.ts +43 -0
- package/src/modules/auth/__tests__/account.routes.test.ts +387 -9
- package/src/modules/auth/__tests__/auth.service.created.pg.test.ts +69 -0
- package/src/modules/auth/__tests__/auth.service.test.ts +159 -1
- package/src/modules/auth/account-hooks.ts +69 -0
- package/src/modules/auth/account-switch-guard.ts +14 -0
- package/src/modules/auth/account-switch-lock.ts +58 -0
- package/src/modules/auth/account.routes.ts +122 -13
- package/src/modules/auth/auth.middleware.ts +1 -1
- package/src/modules/auth/auth.service.ts +268 -52
- package/src/modules/auth/password-hash.ts +5 -2
- 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/__tests__/pg-error.test.ts +21 -0
- package/src/modules/database/__tests__/pii-backfill.pg.test.ts +6 -27
- package/src/modules/database/core-schema.ts +33 -3
- package/src/modules/database/pg-error.ts +15 -0
- 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__/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 +3 -1
- package/src/modules/mcp/__tests__/mcp.service.test.ts +23 -13
- package/src/modules/mcp/__tests__/tool-call-interface.e2e.test.ts +499 -0
- package/src/modules/mcp/mcp-auth.middleware.ts +2 -1
- package/src/modules/mcp/mcp.service.ts +81 -12
- package/src/modules/mcp/oauth/bevel-oauth-provider.ts +42 -4
- 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 +25 -2
- 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/settings/__tests__/deployment-settings.service.test.ts +150 -1
- package/src/modules/settings/__tests__/repository-source.test.ts +9 -0
- package/src/modules/settings/deployment-settings.service.ts +131 -1
- package/src/modules/settings/repository-source.ts +4 -4
- package/src/modules/skills/__tests__/skills.tools.description.test.ts +5 -1
- package/src/modules/skills/skills.tools.ts +55 -35
- 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/tool-manuals.tools.ts +15 -5
- package/src/modules/tool-registry/__tests__/own-tool-schemas.test.ts +14 -1
- package/src/modules/tool-registry/__tests__/tool-description-length.test.ts +23 -10
- package/src/modules/tool-registry/description-length.ts +34 -7
- package/src/modules/tool-registry/guide-first.ts +8 -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.tools.test.ts +41 -5
- package/src/modules/workflow/agent-tools/__tests__/workflow.tools.test.ts +127 -2
- package/src/modules/workflow/agent-tools/change-request-read.tools.ts +157 -122
- package/src/modules/workflow/agent-tools/workflow.tools.ts +129 -35
- package/src/modules/workflow/file-lock.service.ts +67 -5
- package/src/modules/workflow/git/__tests__/git.service.deleteBranch.test.ts +164 -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/git.service.ts +176 -38
- package/src/modules/workflow/git/node-git-runner.ts +82 -7
- 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/review-workflow.service.ts +2 -1
- package/src/modules/workflow/sanitize-error.ts +50 -0
- package/src/modules/workflow/workflow.service.ts +881 -113
- package/src/modules/workspace/__tests__/agent-downloads.test.ts +823 -0
- 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.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.branch-errors.test.ts +44 -1
- package/src/modules/workspace/__tests__/workspace.tools.test.ts +409 -12
- 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/seed-tree.ts +3 -12
- 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 +492 -63
- 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 +108 -11
- package/src/shared/git.contract.ts +8 -1
- 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
|
@@ -263,6 +263,19 @@ export interface IAccessControl {
|
|
|
263
263
|
relativePath: string,
|
|
264
264
|
): Promise<boolean>;
|
|
265
265
|
|
|
266
|
+
/**
|
|
267
|
+
* Batched `canDownload` — one config load per call, the same resolution
|
|
268
|
+
* as the single form, each path's own frontmatter `download:` rules
|
|
269
|
+
* included. A folder download judges every file it would pack through
|
|
270
|
+
* this, so a folder of a thousand files costs one model load, not a
|
|
271
|
+
* thousand.
|
|
272
|
+
*/
|
|
273
|
+
canDownloadBatch(
|
|
274
|
+
workspaceId: string,
|
|
275
|
+
userEmail: string,
|
|
276
|
+
relativePaths: string[],
|
|
277
|
+
): Promise<Map<string, boolean>>;
|
|
278
|
+
|
|
266
279
|
/**
|
|
267
280
|
* True iff `userEmail` is an `owner` of `relativePath` per the current
|
|
268
281
|
* access tree, resolved from the `owner:` lists alone (the `write` /
|
|
@@ -665,6 +678,16 @@ export interface IAccessControl {
|
|
|
665
678
|
*/
|
|
666
679
|
holdsAdminRootWrite(workspaceId: string, userEmail: string): Promise<boolean>;
|
|
667
680
|
|
|
681
|
+
/**
|
|
682
|
+
* Every address the resolver treats as an Admin in the working-tree model,
|
|
683
|
+
* each once: the Admin role's members — through a group too — and the
|
|
684
|
+
* deployment owners. The same membership answer {@link holdsAdminRootWrite}
|
|
685
|
+
* gives one address at a time, enumerated. When the model cannot be loaded
|
|
686
|
+
* (a `roles.yaml` that does not parse makes nobody an Admin), the
|
|
687
|
+
* deployment owners alone.
|
|
688
|
+
*/
|
|
689
|
+
adminEmails(workspaceId: string): Promise<string[]>;
|
|
690
|
+
|
|
668
691
|
/**
|
|
669
692
|
* Whether `userEmail` may put a misplaced platform file back at
|
|
670
693
|
* `destinationRelativePath` — the ONE write that is allowed to land on a
|
|
@@ -1581,6 +1581,22 @@ export class AccessControlService implements IAccessControl {
|
|
|
1581
1581
|
return hasPermissionResolved(model, 'download', userEmail, relativePath, own);
|
|
1582
1582
|
}
|
|
1583
1583
|
|
|
1584
|
+
async canDownloadBatch(
|
|
1585
|
+
workspaceId: string,
|
|
1586
|
+
userEmail: string,
|
|
1587
|
+
relativePaths: string[],
|
|
1588
|
+
): Promise<Map<string, boolean>> {
|
|
1589
|
+
const model = await this.loadModel(workspaceId);
|
|
1590
|
+
const repoDir = await this.repoDir(workspaceId);
|
|
1591
|
+
// Parallel own-entries reads, memoized — same shape as `canWriteBatch`.
|
|
1592
|
+
const owns = await Promise.all(relativePaths.map((p) => this.cachedOwnEntries(workspaceId, repoDir, p)));
|
|
1593
|
+
const result = new Map<string, boolean>();
|
|
1594
|
+
relativePaths.forEach((p, i) => {
|
|
1595
|
+
result.set(p, hasPermissionResolved(model, 'download', userEmail, p, owns[i]));
|
|
1596
|
+
});
|
|
1597
|
+
return result;
|
|
1598
|
+
}
|
|
1599
|
+
|
|
1584
1600
|
async canOwnerBatch(
|
|
1585
1601
|
workspaceId: string,
|
|
1586
1602
|
userEmail: string,
|
|
@@ -2148,6 +2164,25 @@ export class AccessControlService implements IAccessControl {
|
|
|
2148
2164
|
return isAdminEmail(model, canonicalEmail(userEmail));
|
|
2149
2165
|
}
|
|
2150
2166
|
|
|
2167
|
+
async adminEmails(workspaceId: string): Promise<string[]> {
|
|
2168
|
+
let model: AccessModel;
|
|
2169
|
+
try {
|
|
2170
|
+
model = await this.loadModel(workspaceId);
|
|
2171
|
+
} catch (err) {
|
|
2172
|
+
// As canRestorePlatformFile: with no model to ask, the deployment owners
|
|
2173
|
+
// are the only admins left. A `roles.yaml` that does not parse is that
|
|
2174
|
+
// by design; anything else (a clone being read, the disk) is said, so a
|
|
2175
|
+
// list that names fewer admins than there are is diagnosable.
|
|
2176
|
+
if (!(err instanceof AccessConfigError)) {
|
|
2177
|
+
log.warn('the access model could not be loaded; the admins list names the deployment owners only:', { err });
|
|
2178
|
+
}
|
|
2179
|
+
return [...this.deploymentOwners];
|
|
2180
|
+
}
|
|
2181
|
+
const candidates = new Set<string>(model.deploymentOwners);
|
|
2182
|
+
for (const email of model.roles.byEmail.keys()) candidates.add(email);
|
|
2183
|
+
return [...candidates].filter((email) => isAdminEmail(model, email));
|
|
2184
|
+
}
|
|
2185
|
+
|
|
2151
2186
|
async canRestorePlatformFile(
|
|
2152
2187
|
workspaceId: string,
|
|
2153
2188
|
userEmail: string,
|
|
@@ -21,6 +21,7 @@ import type { WorkspaceService } from '../workspace/workspace.service.js';
|
|
|
21
21
|
import type { KbContext } from '../../shared/kb-context.js';
|
|
22
22
|
import { branchForWorkspaceId } from '../../shared/workspace-id.js';
|
|
23
23
|
import type { AuthService } from '../auth/auth.service.js';
|
|
24
|
+
import type { IAccountSwitchGuard } from '../auth/account-switch-guard.js';
|
|
24
25
|
import type { WorkflowService } from '../workflow/workflow.service.js';
|
|
25
26
|
import type { WorkflowEventBus } from '../workflow/event-bus.js';
|
|
26
27
|
import { WorkflowDomainError } from '../../shared/domain-errors.js';
|
|
@@ -51,6 +52,7 @@ import { RolesAdminService } from './roles-admin.service.js';
|
|
|
51
52
|
import type { Principal } from '../access-model/access-splice.js';
|
|
52
53
|
import type { Database } from '../database/connection.js';
|
|
53
54
|
import { users } from '../database/schema.js';
|
|
55
|
+
import { canonicalEmail } from '../../shared/email-identity.js';
|
|
54
56
|
import '../auth/auth.middleware.js';
|
|
55
57
|
|
|
56
58
|
/** Verbs the share UI may grant. Verbs are independent — `download` is grantable on its own. */
|
|
@@ -85,6 +87,8 @@ export function createAccessRoutes(
|
|
|
85
87
|
accessControl: IAccessControl,
|
|
86
88
|
workspaceService: WorkspaceService,
|
|
87
89
|
authService: AuthService,
|
|
90
|
+
/** Auth's switch-off coordination, for the invite's promotion (`ifActive`). */
|
|
91
|
+
switchGuard: IAccountSwitchGuard,
|
|
88
92
|
workflowService: WorkflowService,
|
|
89
93
|
eventBus: WorkflowEventBus,
|
|
90
94
|
db: Database,
|
|
@@ -431,12 +435,15 @@ export function createAccessRoutes(
|
|
|
431
435
|
|
|
432
436
|
/**
|
|
433
437
|
* POST /api/workspace/:id/access/batch
|
|
434
|
-
* Body: `{ paths: string[], verb?: 'write' | 'owner' }`. Returns
|
|
438
|
+
* Body: `{ paths: string[], verb?: 'write' | 'owner' | 'read' }`. Returns
|
|
435
439
|
* `{ results: { [path]: boolean } }`.
|
|
436
440
|
*
|
|
437
441
|
* `verb` defaults to `write`, the question every existing caller asks.
|
|
438
442
|
* `owner` answers from the `owner:` lists alone — no admin rescue, and a
|
|
439
|
-
* writer is not an owner — which is what an Owner pill has to mean.
|
|
443
|
+
* writer is not an owner — which is what an Owner pill has to mean. `read`
|
|
444
|
+
* is the verdict the single lookup's `canRead` gives, for many paths at
|
|
445
|
+
* once: what New page asks on a draft branch, where a page may go wherever
|
|
446
|
+
* its author may read, of every Knowledge folder in one request.
|
|
440
447
|
*/
|
|
441
448
|
router.post('/workspace/:id/access/batch', async (req, res) => {
|
|
442
449
|
const user = await requireUser(req, res);
|
|
@@ -451,13 +458,18 @@ export function createAccessRoutes(
|
|
|
451
458
|
res.status(400).json({ error: 'paths cannot exceed 500 entries per request' });
|
|
452
459
|
return;
|
|
453
460
|
}
|
|
454
|
-
if (verb !== 'write' && verb !== 'owner') {
|
|
455
|
-
res.status(400).json({ error: 'verb must be "write" or "
|
|
461
|
+
if (verb !== 'write' && verb !== 'owner' && verb !== 'read') {
|
|
462
|
+
res.status(400).json({ error: 'verb must be "write", "owner" or "read"' });
|
|
456
463
|
return;
|
|
457
464
|
}
|
|
458
465
|
|
|
459
466
|
try {
|
|
460
|
-
const batch =
|
|
467
|
+
const batch =
|
|
468
|
+
verb === 'owner'
|
|
469
|
+
? accessControl.canOwnerBatch
|
|
470
|
+
: verb === 'read'
|
|
471
|
+
? accessControl.canReadBatch
|
|
472
|
+
: accessControl.canWriteBatch;
|
|
461
473
|
const result = await batch.call(
|
|
462
474
|
accessControl,
|
|
463
475
|
req.params.id,
|
|
@@ -1228,6 +1240,39 @@ export function createAccessRoutes(
|
|
|
1228
1240
|
}
|
|
1229
1241
|
});
|
|
1230
1242
|
|
|
1243
|
+
// Who the admins are, for anyone signed in: the top bar tells someone who
|
|
1244
|
+
// is not an admin to ask one, and names them. Names and emails ONLY — the
|
|
1245
|
+
// roster above (every role, its members, groups and references) stays
|
|
1246
|
+
// admin-only. Names come from the accounts table; an admin with no account
|
|
1247
|
+
// yet (a deployment admin before first sign-in, say) is named by address.
|
|
1248
|
+
// A role member whose account is switched off cannot sign in to invite
|
|
1249
|
+
// anyone, so is left out; a deployment admin is not (it signs in with the
|
|
1250
|
+
// environment's password regardless).
|
|
1251
|
+
router.get('/access/admins', async (req, res) => {
|
|
1252
|
+
const user = await requireUser(req, res);
|
|
1253
|
+
if (!user) return;
|
|
1254
|
+
try {
|
|
1255
|
+
const emails = await rolesAdmin.getAdminEmails();
|
|
1256
|
+
const rows =
|
|
1257
|
+
emails.length === 0
|
|
1258
|
+
? []
|
|
1259
|
+
: await db
|
|
1260
|
+
.select({ email: users.email, name: users.name, deactivatedAt: users.deactivatedAt })
|
|
1261
|
+
.from(users)
|
|
1262
|
+
.where(inArray(users.emailBidx, emails));
|
|
1263
|
+
const names = new Map(rows.map((r) => [canonicalEmail(r.email), r.name?.trim() ?? '']));
|
|
1264
|
+
const off = new Set(rows.filter((r) => r.deactivatedAt).map((r) => canonicalEmail(r.email)));
|
|
1265
|
+
const admins = emails
|
|
1266
|
+
.filter((email) => !off.has(email) || rolesAdmin.isFixedAdmin(email))
|
|
1267
|
+
.map((email) => ({ name: names.get(email) || email, email }))
|
|
1268
|
+
.sort((a, b) => a.name.localeCompare(b.name) || a.email.localeCompare(b.email));
|
|
1269
|
+
res.json({ admins });
|
|
1270
|
+
} catch (err) {
|
|
1271
|
+
const { status, body } = toHttpError(err);
|
|
1272
|
+
res.status(status).json(body);
|
|
1273
|
+
}
|
|
1274
|
+
});
|
|
1275
|
+
|
|
1231
1276
|
// NOTE: POST /access/roles (create), PATCH /access/roles/:canonical
|
|
1232
1277
|
// (rename), and DELETE /access/roles/:canonical are GONE — roles are
|
|
1233
1278
|
// app-defined capabilities, not user-editable objects.
|
|
@@ -1239,7 +1284,23 @@ export function createAccessRoutes(
|
|
|
1239
1284
|
await assertRolesAdmin(user.email);
|
|
1240
1285
|
const canonical = canonicalRoleName(req.params.canonical);
|
|
1241
1286
|
const email = requireNonEmptyString((req.body ?? {}).email, 'email');
|
|
1242
|
-
|
|
1287
|
+
// `ifActive`: the invite's promotion, which leaves a switched-off
|
|
1288
|
+
// account unchanged. Inside the roles file's lock, auth reads the
|
|
1289
|
+
// account under the address's switch lock and keeps that transaction
|
|
1290
|
+
// open until roles.yaml is written and committed
|
|
1291
|
+
// (`IAccountSwitchGuard.whileSwitchedOn`). So a switch-off either committed
|
|
1292
|
+
// before the read (the promotion is refused) or waits until the
|
|
1293
|
+
// promotion is written (it lands after, as for any Admin switched off
|
|
1294
|
+
// later: the place in roles stays, the credentials stop being honoured).
|
|
1295
|
+
const ifActive = (req.body ?? {}).ifActive;
|
|
1296
|
+
if (ifActive !== undefined && typeof ifActive !== 'boolean') {
|
|
1297
|
+
res.status(400).json({ error: 'ifActive must be a boolean' });
|
|
1298
|
+
return;
|
|
1299
|
+
}
|
|
1300
|
+
const whileSwitchedOn = (write: () => Promise<void>): Promise<void> => switchGuard.whileSwitchedOn(email, write);
|
|
1301
|
+
res.json({
|
|
1302
|
+
roles: await rolesAdmin.addMember(user, canonical, email, ifActive ? { aroundWrite: whileSwitchedOn } : undefined),
|
|
1303
|
+
});
|
|
1243
1304
|
} catch (err) {
|
|
1244
1305
|
const { status, body } = toHttpError(err);
|
|
1245
1306
|
res.status(status).json(body);
|
|
@@ -35,7 +35,7 @@ export async function ensureDirectorySyncBot(db: Database): Promise<AuthUser> {
|
|
|
35
35
|
.returning();
|
|
36
36
|
if (inserted.length > 0) {
|
|
37
37
|
const row = inserted[0];
|
|
38
|
-
log.info(`created sync-bot user id=${row.id}
|
|
38
|
+
log.info(`created sync-bot user id=${row.id}`);
|
|
39
39
|
return { id: row.id, email: row.email, name: row.name, avatarUrl: row.avatarUrl ?? undefined };
|
|
40
40
|
}
|
|
41
41
|
const [row] = await db
|
|
@@ -103,6 +103,13 @@ export interface RoleRosterEntry {
|
|
|
103
103
|
* email once, as fixed.
|
|
104
104
|
*/
|
|
105
105
|
fixedMembers: string[];
|
|
106
|
+
/**
|
|
107
|
+
* The note the page prints beside {@link fixedMembers}, and the sentence
|
|
108
|
+
* both Admin-membership refusals lead with. Sent with the roster so the
|
|
109
|
+
* page keeps no copy of the wording. Null when the role has no fixed
|
|
110
|
+
* members.
|
|
111
|
+
*/
|
|
112
|
+
fixedMembersNote: string | null;
|
|
106
113
|
/** Canonical names of groups this role is assigned to (`group:` members). */
|
|
107
114
|
groups: string[];
|
|
108
115
|
isAdmin: boolean;
|
|
@@ -165,11 +172,12 @@ export class RolesAdminService {
|
|
|
165
172
|
private readonly fixedAdminEmails: readonly string[];
|
|
166
173
|
/**
|
|
167
174
|
* The one explanation both Admin-role refusals carry, verbatim: the note the
|
|
168
|
-
* page prints beside a fixed member
|
|
169
|
-
*
|
|
175
|
+
* page prints beside a fixed member, which it reads from the roster's
|
|
176
|
+
* `fixedMembersNote`. One constant, so the refusal an API caller reads and
|
|
177
|
+
* the note a UI reader sees cannot drift apart.
|
|
170
178
|
*/
|
|
171
179
|
private static readonly FIXED_ADMIN_NOTE =
|
|
172
|
-
'
|
|
180
|
+
'Owner; cannot be removed here';
|
|
173
181
|
|
|
174
182
|
constructor(
|
|
175
183
|
private readonly workspaceService: IWorkspaceService,
|
|
@@ -227,9 +235,10 @@ export class RolesAdminService {
|
|
|
227
235
|
/**
|
|
228
236
|
* Is `email` a deployment admin — an address the server configuration makes
|
|
229
237
|
* an Admin, ahead of `roles.yaml`? Drives both the fixed member rows and
|
|
230
|
-
* the add/remove refusals on the Admin role
|
|
238
|
+
* the add/remove refusals on the Admin role, and keeps a switched-off
|
|
239
|
+
* deployment admin among the admins people are told to ask.
|
|
231
240
|
*/
|
|
232
|
-
|
|
241
|
+
isFixedAdmin(email: string): boolean {
|
|
233
242
|
return this.fixedAdminEmails.includes(canonicalEmail(email));
|
|
234
243
|
}
|
|
235
244
|
|
|
@@ -326,6 +335,8 @@ export class RolesAdminService {
|
|
|
326
335
|
// Only Admin has fixed members: `deploymentOwners` is an Admin rescue
|
|
327
336
|
// in the resolver, never a general grant, so no other role gains one.
|
|
328
337
|
fixedMembers: isAdmin ? [...this.fixedAdminEmails] : [],
|
|
338
|
+
fixedMembersNote:
|
|
339
|
+
isAdmin && this.fixedAdminEmails.length > 0 ? RolesAdminService.FIXED_ADMIN_NOTE : null,
|
|
329
340
|
groups: role.members
|
|
330
341
|
.filter(isGroupRefMember)
|
|
331
342
|
.map((m) => canonicalRoleName(m.slice(GROUP_REF_PREFIX.length))),
|
|
@@ -342,6 +353,18 @@ export class RolesAdminService {
|
|
|
342
353
|
return out;
|
|
343
354
|
}
|
|
344
355
|
|
|
356
|
+
/**
|
|
357
|
+
* The addresses the app treats as an Admin, each once — the resolver's own
|
|
358
|
+
* membership answer ({@link IAccessControl.adminEmails}), so who this names
|
|
359
|
+
* and who the admin gates admit cannot drift apart. Nothing else about
|
|
360
|
+
* roles: this backs a read any signed-in person may make (who to ask for an
|
|
361
|
+
* invite), unlike the roster.
|
|
362
|
+
*/
|
|
363
|
+
async getAdminEmails(): Promise<string[]> {
|
|
364
|
+
const workspaceId = await this.ensureWorkspace();
|
|
365
|
+
return this.accessControl.adminEmails(workspaceId);
|
|
366
|
+
}
|
|
367
|
+
|
|
345
368
|
/**
|
|
346
369
|
* Whether the default-branch roles.yaml parses. Drives the "roles file
|
|
347
370
|
* corrupted" banner. Auth-only (never admin-gated): a corrupted file resolves
|
|
@@ -446,10 +469,24 @@ export class RolesAdminService {
|
|
|
446
469
|
* admits it ahead of `roles.yaml` — so the write would add a row that means
|
|
447
470
|
* nothing, next to the fixed row the page already shows. Other roles are
|
|
448
471
|
* unaffected: a deployment admin is an ordinary member of "Sales".
|
|
472
|
+
*
|
|
473
|
+
* `aroundWrite`, when given, runs once the roles file's lock is held and
|
|
474
|
+
* is handed the edit itself (read, check, write, commit) to run. What it
|
|
475
|
+
* does around that call brackets the whole write: the invite holds the
|
|
476
|
+
* address's account-switch lock (a transaction-scoped advisory lock keyed
|
|
477
|
+
* on the canonical email, see `AuthService.whileSwitchedOn`) across it, so
|
|
478
|
+
* a switch-off cannot commit in between, whether or not the account exists
|
|
479
|
+
* yet (see the members route). It may throw instead of calling `write`;
|
|
480
|
+
* nothing is written then.
|
|
449
481
|
*/
|
|
450
|
-
async addMember(
|
|
482
|
+
async addMember(
|
|
483
|
+
actor: AuthUser,
|
|
484
|
+
canonical: string,
|
|
485
|
+
email: string,
|
|
486
|
+
opts?: { aroundWrite?: (write: () => Promise<void>) => Promise<void> },
|
|
487
|
+
): Promise<RoleRosterEntry[]> {
|
|
451
488
|
this.assertNotFixedAdmin(canonical, email);
|
|
452
|
-
await this.runEdit(actor, (text) => editAddMember(text, canonical, email));
|
|
489
|
+
await this.runEdit(actor, (text) => editAddMember(text, canonical, email), opts?.aroundWrite);
|
|
453
490
|
return this.getRoster();
|
|
454
491
|
}
|
|
455
492
|
|
|
@@ -682,17 +719,20 @@ export class RolesAdminService {
|
|
|
682
719
|
* `pre` produces the candidate (and may throw RolesAdminError for invariant
|
|
683
720
|
* violations before any write). Skips on a no-op. Every candidate passes
|
|
684
721
|
* the resolver's own parser (assertLoadable) plus the pre-disk validator
|
|
685
|
-
* before a byte lands.
|
|
722
|
+
* before a byte lands. `aroundWrite` wraps the locked edit (see
|
|
723
|
+
* {@link addMember}).
|
|
686
724
|
*/
|
|
687
725
|
private async runEdit(
|
|
688
726
|
actor: AuthUser,
|
|
689
727
|
pre: (currentText: string) => EditResult,
|
|
728
|
+
aroundWrite?: (write: () => Promise<void>) => Promise<void>,
|
|
690
729
|
): Promise<void> {
|
|
691
730
|
const workspaceId = await this.ensureWorkspace();
|
|
692
731
|
await this.assertRolesUnlocked(workspaceId, actor);
|
|
693
|
-
return this.locked.withFileLocks(workspaceId, actor, [ROLES_YAML], () =>
|
|
694
|
-
this.runEditLocked(workspaceId, actor, pre)
|
|
695
|
-
|
|
732
|
+
return this.locked.withFileLocks(workspaceId, actor, [ROLES_YAML], () => {
|
|
733
|
+
const write = () => this.runEditLocked(workspaceId, actor, pre);
|
|
734
|
+
return aroundWrite ? aroundWrite(write) : write();
|
|
735
|
+
});
|
|
696
736
|
}
|
|
697
737
|
|
|
698
738
|
private async runEditLocked(
|
|
@@ -492,7 +492,7 @@ export class UserAccessRemovalService {
|
|
|
492
492
|
/** Why `email` may not be removed from access files, or null when it may. */
|
|
493
493
|
private blockedReason(rolesText: string | undefined, email: string): string | null {
|
|
494
494
|
if (this.deploymentOwners.some((o) => canonicalEmail(o) === email)) {
|
|
495
|
-
return '
|
|
495
|
+
return 'The owner stays in roles and access rules.';
|
|
496
496
|
}
|
|
497
497
|
const admin = rolesText
|
|
498
498
|
? (() => {
|
|
@@ -299,6 +299,18 @@ describe('what the guide tells an agent', () => {
|
|
|
299
299
|
expect(prose).toContain('add people to existing roles, and use a GROUP for a task- or team-scoped set of people');
|
|
300
300
|
});
|
|
301
301
|
|
|
302
|
+
it('describes delete_branch where it says what an agent does with branches', async () => {
|
|
303
|
+
const text = section(await composeAgentGuide(DEFAULT_KB_LAYOUT), '### An agent proposes and syncs; a person merges');
|
|
304
|
+
const prose = text.replace(/\s+/g, ' ');
|
|
305
|
+
expect(prose).toContain('`delete_branch`');
|
|
306
|
+
expect(prose).toContain('Only its author');
|
|
307
|
+
expect(prose).toContain('`dryRun: true`');
|
|
308
|
+
expect(prose).toContain('`discardUnmerged: true`');
|
|
309
|
+
expect(prose).toContain('that proposes nothing is closed by the delete');
|
|
310
|
+
expect(prose).toContain('its author can withdraw it, or an Admin can decline it, in the app');
|
|
311
|
+
expect(prose).toContain('`lastCommit`');
|
|
312
|
+
});
|
|
313
|
+
|
|
302
314
|
it('documents giving a role to a group, with an example that parses as a valid roles.yaml', async () => {
|
|
303
315
|
const text = section(await composeAgentGuide(DEFAULT_KB_LAYOUT), '### Giving a role to a group');
|
|
304
316
|
const prose = text.replace(/\s+/g, ' ');
|
|
@@ -326,3 +338,49 @@ describe('what the guide tells an agent', () => {
|
|
|
326
338
|
expect(parsed.index.byEmail.get('pat@example.com')?.has('role/admin')).toBe(false);
|
|
327
339
|
});
|
|
328
340
|
});
|
|
341
|
+
|
|
342
|
+
/**
|
|
343
|
+
* The HTML views section: what an agent writing a live page is told about the
|
|
344
|
+
* frame. Its link rules are pinned against the renderer by core-frontend's
|
|
345
|
+
* `htmlViewsGuide.test.ts`, which reads the same file; what is pinned here is
|
|
346
|
+
* that it is served like every other section and that a distribution may
|
|
347
|
+
* reshape it.
|
|
348
|
+
*/
|
|
349
|
+
describe('the HTML views section', () => {
|
|
350
|
+
it('is served on its own, inside the whole guide, titled "HTML views"', async () => {
|
|
351
|
+
const sections = await agentGuideSections(DEFAULT_KB_LAYOUT);
|
|
352
|
+
const html = sections.find((s) => s.id === 'html-views')!;
|
|
353
|
+
expect(html.title).toBe('HTML views');
|
|
354
|
+
expect(html.body).not.toContain('{{');
|
|
355
|
+
expect(await composeAgentGuide(DEFAULT_KB_LAYOUT)).toContain(html.body);
|
|
356
|
+
// After the tool manuals, before the conventions.
|
|
357
|
+
const ids = sections.map((s) => s.id);
|
|
358
|
+
expect(ids.indexOf('html-views')).toBe(ids.indexOf('tool-manuals') + 1);
|
|
359
|
+
});
|
|
360
|
+
|
|
361
|
+
it('describes the frame, the two members core puts on window.bevel, and a fragment that scrolls the page', async () => {
|
|
362
|
+
const text = section(await composeAgentGuide(DEFAULT_KB_LAYOUT), '## HTML views').replace(/\s+/g, ' ');
|
|
363
|
+
expect(text).toContain('**No network.**');
|
|
364
|
+
expect(text).toContain('**Inline scripts and styles only.**');
|
|
365
|
+
expect(text).toContain('**Scripts run as ES modules**');
|
|
366
|
+
expect(text).toContain('**No browser storage.**');
|
|
367
|
+
expect(text).toContain('**No host navigation.**');
|
|
368
|
+
expect(text).toContain('`window.bevel.openNode(href)`');
|
|
369
|
+
expect(text).toContain('`window.bevel.navigate(href)`');
|
|
370
|
+
expect(text).toContain('A distribution may add data members of its own to `window.bevel`');
|
|
371
|
+
expect(text).toContain('**A bare fragment scrolls the page.**');
|
|
372
|
+
// Rendered for the deployment's layout like every other section.
|
|
373
|
+
const docs = section(await composeAgentGuide({ ...DEFAULT_KB_LAYOUT, knowledgeBaseDir: 'Docs' }), '## HTML views');
|
|
374
|
+
expect(docs).toContain('/workspace/main/Docs/Alice.md');
|
|
375
|
+
});
|
|
376
|
+
|
|
377
|
+
it('lets a distribution replace the section or drop it', async () => {
|
|
378
|
+
const replaced = await composeAgentGuide(DEFAULT_KB_LAYOUT, (sections) =>
|
|
379
|
+
sections.map((s) => (s.id === 'html-views' ? { id: s.id, body: '## HTML views\n\nOurs, graph-aware.\n' } : s)),
|
|
380
|
+
);
|
|
381
|
+
expect(section(replaced, '## HTML views').trim()).toBe('Ours, graph-aware.');
|
|
382
|
+
const dropped = await agentGuideSections(DEFAULT_KB_LAYOUT, (sections) => sections.filter((s) => s.id !== 'html-views'));
|
|
383
|
+
expect(dropped.map((s) => s.id)).not.toContain('html-views');
|
|
384
|
+
expect(joinGuideSections(dropped)).not.toContain('## HTML views');
|
|
385
|
+
});
|
|
386
|
+
});
|
|
@@ -9,7 +9,8 @@ import { createToolHandlerFactory } from '../../tool-helpers/tool-handler.js';
|
|
|
9
9
|
import type { ToolContext } from '../../tool-helpers/tool.contract.js';
|
|
10
10
|
import { toolDef } from '../../tool-helpers/tool-def.js';
|
|
11
11
|
import { GET_AGENT_GUIDE_TOOL, registerAgentGuideTool } from '../agent-guide.tools.js';
|
|
12
|
-
import
|
|
12
|
+
import { DEFAULT_KB_LAYOUT } from '@bevel-software/platform-shared';
|
|
13
|
+
import { agentGuideSections, joinGuideSections, type RenderedGuideSection } from '../agent-guide.js';
|
|
13
14
|
|
|
14
15
|
let server: Server | null = null;
|
|
15
16
|
|
|
@@ -186,4 +187,21 @@ describe('get_agent_guide', () => {
|
|
|
186
187
|
sectionsNow(SECTIONS);
|
|
187
188
|
expect(await describedAs()).toContain('`introduction` (Knowledge base)');
|
|
188
189
|
});
|
|
190
|
+
|
|
191
|
+
it('returns the platform\'s HTML views section on its own, and inside the whole guide', async () => {
|
|
192
|
+
const { call, registry, sectionsNow } = await serve();
|
|
193
|
+
const platform = await agentGuideSections(DEFAULT_KB_LAYOUT);
|
|
194
|
+
sectionsNow([...platform]);
|
|
195
|
+
const html = platform.find((s) => s.id === 'html-views')!;
|
|
196
|
+
expect(await call({ section: 'html-views' })).toEqual({
|
|
197
|
+
status: 200,
|
|
198
|
+
body: { guide: html.body, section: 'html-views', title: 'HTML views' },
|
|
199
|
+
});
|
|
200
|
+
const whole = await call();
|
|
201
|
+
expect(whole.body.guide).toBe(joinGuideSections(platform));
|
|
202
|
+
expect(String(whole.body.guide)).toContain('## HTML views');
|
|
203
|
+
// The description lists it, so an agent knows it can ask for it.
|
|
204
|
+
const def = (await registry.listExternal()).find((t) => t.name === GET_AGENT_GUIDE_TOOL)!;
|
|
205
|
+
expect(def.description).toContain('`html-views`');
|
|
206
|
+
});
|
|
189
207
|
});
|
|
@@ -79,6 +79,13 @@ export type AgentGuideReader = () => Promise<string>;
|
|
|
79
79
|
/** The computed section: the rules every file tool shares. */
|
|
80
80
|
export const WORKING_WITH_FILES_SECTION_ID = 'working-with-files';
|
|
81
81
|
|
|
82
|
+
/**
|
|
83
|
+
* What to do on a knowledge base nobody has written in yet: the section the
|
|
84
|
+
* `firstRun` note `start_session` answers with points at (see
|
|
85
|
+
* workspace/first-run.ts, which names it by this constant).
|
|
86
|
+
*/
|
|
87
|
+
export const NEW_KNOWLEDGE_BASE_SECTION_ID = 'new-knowledge-base';
|
|
88
|
+
|
|
82
89
|
/**
|
|
83
90
|
* Core's sections, in reading order. Every id but the shared-rules one names
|
|
84
91
|
* a file in the package's `agent-guide/` folder.
|
|
@@ -91,8 +98,10 @@ export const CORE_SECTION_IDS: readonly string[] = Object.freeze([
|
|
|
91
98
|
'access-control',
|
|
92
99
|
'skills',
|
|
93
100
|
'tool-manuals',
|
|
101
|
+
'html-views',
|
|
94
102
|
'conventions',
|
|
95
103
|
'finding-things',
|
|
104
|
+
NEW_KNOWLEDGE_BASE_SECTION_ID,
|
|
96
105
|
]);
|
|
97
106
|
|
|
98
107
|
/**
|
|
@@ -114,6 +114,20 @@ describe('the shared file rules are one text, in two places', () => {
|
|
|
114
114
|
|
|
115
115
|
});
|
|
116
116
|
|
|
117
|
+
describe('the delete rule for platform files', () => {
|
|
118
|
+
const managedItems = (): string => sharedFileRules(DEFAULT_KB_LAYOUT).find((r) => r.id === 'managed-items')!.body;
|
|
119
|
+
|
|
120
|
+
it('says a nested access.md is deleted by whoever may write it, and the root\'s platform files by nobody', async () => {
|
|
121
|
+
const body = managedItems();
|
|
122
|
+
expect(body).toContain('delete_file deletes a nested `access.md` for whoever may write it');
|
|
123
|
+
expect(body).toContain("its folder then follows its parent's rules");
|
|
124
|
+
expect(body).toContain("the repository root's `access.md` and `roles.yaml` are deleted by nobody");
|
|
125
|
+
// The sentence the refusal actually carries, as the tools and the app say it.
|
|
126
|
+
expect(body).toContain("\"<name> is the repository's own file and cannot be deleted.\"");
|
|
127
|
+
expect(await composeAgentGuide(DEFAULT_KB_LAYOUT)).toContain(body);
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
|
|
117
131
|
describe('the handshake text stays inside the length it pins', () => {
|
|
118
132
|
it('holds the shared section under its own cap', () => {
|
|
119
133
|
const section = sharedFileRulesSection(DEFAULT_KB_LAYOUT);
|
|
@@ -30,6 +30,7 @@ import {
|
|
|
30
30
|
stripHtmlComments,
|
|
31
31
|
type KbLayout,
|
|
32
32
|
} from '@bevel-software/platform-shared';
|
|
33
|
+
import { splitCallLine } from '@bevel-software/platform-mcp-core';
|
|
33
34
|
import { sharedFileRulesSection } from './shared-file-rules.js';
|
|
34
35
|
|
|
35
36
|
export { PREAMBLE_CAP, PREAMBLE_FILE, TOOL_PREFIX_CAP };
|
|
@@ -48,7 +49,13 @@ export const PLATFORM_HEADER =
|
|
|
48
49
|
'Before answering a question about the organisation, its people, customers, products, processes, projects or internal terms, ' +
|
|
49
50
|
'search the knowledge base: call `start_session` once, then `grep` for the key terms, `list_files` to orient, and `read_file` what matches. ' +
|
|
50
51
|
'Prefer what you find there over memory or the web, and say so when the knowledge base is silent on something the organisation should have documented. ' +
|
|
51
|
-
'Skills are available as prompts and through `list_skills` and `get_skill`.'
|
|
52
|
+
'Skills are available as prompts and through `list_skills` and `get_skill`. ' +
|
|
53
|
+
// There is no one calling shape to state: the knowledge-base tools take
|
|
54
|
+
// their arguments under `body`, a tool that calls another service takes them
|
|
55
|
+
// flat, and an agent told one rule for all of them sends a GET with a body.
|
|
56
|
+
// The per-tool `Call:` line is generated from each tool's own input schema,
|
|
57
|
+
// so pointing at it is both shorter and always right.
|
|
58
|
+
'Tools do not share one calling shape: call each tool exactly as the `Call:` line at the top of its description shows.';
|
|
52
59
|
|
|
53
60
|
/**
|
|
54
61
|
* The fixed first line of the tool prefix. It always leads, so an admin's
|
|
@@ -167,9 +174,17 @@ export function composeAgentInstructions(
|
|
|
167
174
|
* A tool description with the prefix ahead of it: the prefix, a blank line,
|
|
168
175
|
* then the original. Purpose line first, because claude.ai cuts descriptions
|
|
169
176
|
* near 500 characters.
|
|
177
|
+
*
|
|
178
|
+
* Except for the `Call:` line, which stays the very first line whatever else
|
|
179
|
+
* is prepended: it is how an agent learns the shape this tool's arguments take,
|
|
180
|
+
* and a description that opens with the purpose prefix instead would bury the
|
|
181
|
+
* one line the refusal for a wrong call points back to.
|
|
170
182
|
*/
|
|
171
183
|
export function prefixToolDescription(toolPrefix: string, description: string | undefined): string {
|
|
172
|
-
|
|
184
|
+
if (!description) return toolPrefix;
|
|
185
|
+
const { call, rest } = splitCallLine(description);
|
|
186
|
+
if (call === null) return `${toolPrefix}\n\n${description}`;
|
|
187
|
+
return rest === '' ? `${call}\n\n${toolPrefix}` : `${call}\n\n${toolPrefix}\n\n${rest}`;
|
|
173
188
|
}
|
|
174
189
|
|
|
175
190
|
/** An ATX heading line: `#` to `######`, then a space or the end. */
|
|
@@ -145,15 +145,15 @@ export function sharedFileRules(layout: KbLayout): readonly SharedFileRule[] {
|
|
|
145
145
|
// that take content as a JSON string names the route in one sentence of
|
|
146
146
|
// its own; WHY a file should go that way, and how, is here.
|
|
147
147
|
id: 'upload-route',
|
|
148
|
-
heading: 'Large, escape-heavy and binary content
|
|
148
|
+
heading: 'Large, escape-heavy and binary content: upload in, download out',
|
|
149
149
|
body:
|
|
150
|
-
'write_file, write_files and edit_file take content as a JSON string you
|
|
151
|
-
'
|
|
152
|
-
'
|
|
153
|
-
'
|
|
154
|
-
'
|
|
155
|
-
'
|
|
156
|
-
'
|
|
150
|
+
'write_file, write_files and edit_file take content as a JSON string you type out in full, so a long file ' +
|
|
151
|
+
'is cut off mid-answer, a file full of backslashes or `\\u` escapes fails to parse as a parameter, and an ' +
|
|
152
|
+
'image, a PDF or a zip cannot be sent at all. For those, call `request_file_upload`, POST the file (or one ' +
|
|
153
|
+
'zip of many) with any HTTP client (`curl -X POST --data-binary @<file> ' +
|
|
154
|
+
'"<uploadUrl>?filename=<name>"`), then `apply_file_upload` lands it in one commit. To take copies OUT, ' +
|
|
155
|
+
'`request_file_download` answers a one-time link per file and a zip per folder (`curl -o <name> ' +
|
|
156
|
+
'"<downloadUrl>"`). Either way no bytes pass through the conversation.',
|
|
157
157
|
},
|
|
158
158
|
{
|
|
159
159
|
id: 'dry-run-confirm',
|
|
@@ -163,22 +163,22 @@ export function sharedFileRules(layout: KbLayout): readonly SharedFileRule[] {
|
|
|
163
163
|
'what the call would touch, `allowed`, and `reason` when it may not run. A non-empty folder is deleted, and a ' +
|
|
164
164
|
'move that changes your access runs, only with `confirm: true`; without it the call changes nothing and ' +
|
|
165
165
|
'returns the same impact with `confirmationRequired: true`. Do NOT set `confirm: true` on your first call — ' +
|
|
166
|
-
'dry-run, check the impact, then confirm. delete_file takes neither: it
|
|
167
|
-
'
|
|
166
|
+
'dry-run, check the impact, then confirm. delete_file takes neither: check it first with file_stat ' +
|
|
167
|
+
'(`deletable`) if you are unsure. delete_branch has its own `dryRun`.',
|
|
168
168
|
},
|
|
169
169
|
{
|
|
170
170
|
id: 'managed-items',
|
|
171
171
|
heading: 'What these tools never move or delete',
|
|
172
172
|
body:
|
|
173
|
-
`A platform file (${platformFileList(layout)}) is
|
|
174
|
-
'
|
|
175
|
-
|
|
176
|
-
'
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
'
|
|
180
|
-
'able to write
|
|
181
|
-
'file_stat reports `managed`, `movable` and `deletable`
|
|
173
|
+
`A platform file (${platformFileList(layout)}) is never moved: "<name> is a platform file and stays in its folder." ` +
|
|
174
|
+
'A folder moved or deleted takes its own along, in one change. delete_file deletes a nested `access.md` for ' +
|
|
175
|
+
"whoever may write it (its folder then follows its parent's rules) and refuses `.bevelignore`; the repository " +
|
|
176
|
+
"root's `access.md` and `roles.yaml` are deleted by nobody: \"<name> is the repository's own file and cannot be " +
|
|
177
|
+
'deleted." A platform folder (the root, or a reserved one like ' +
|
|
178
|
+
`\`${layout.knowledgeBaseDir}/\`), git metadata, and making a platform file or folder at a destination are ` +
|
|
179
|
+
'refused; so is a path that is or crosses a symlink: links are never followed or removed. On a protected ' +
|
|
180
|
+
'branch you must be able to write all a call touches — for a folder, every file under it, at its old and new ' +
|
|
181
|
+
'path. file_stat reports `managed`, `movable` and `deletable` up front.',
|
|
182
182
|
},
|
|
183
183
|
{
|
|
184
184
|
id: 'refused-for-permissions',
|