@bevel-software/platform-core-backend 0.33.0 → 0.35.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 +146 -289
- package/agent-guide/conventions.md +23 -25
- package/agent-guide/directory-structure.md +72 -120
- package/agent-guide/drafts-and-change-requests.md +92 -0
- package/agent-guide/for-git-users.md +47 -0
- package/agent-guide/glossary.md +36 -0
- package/agent-guide/how-agents-find-things.md +49 -0
- package/agent-guide/html-views.md +239 -8
- package/agent-guide/new-knowledge-base.md +9 -8
- package/agent-guide/skills.md +67 -42
- package/agent-guide/start-here.md +65 -0
- package/agent-guide/tool-manuals.md +133 -155
- package/agent-guide/tools.md +67 -0
- package/agent-guide/where-a-new-file-goes.md +45 -28
- package/dist/core/catalog-revision.d.ts +12 -1
- package/dist/core/catalog-revision.d.ts.map +1 -1
- package/dist/core/catalog-revision.js +23 -3
- package/dist/core/catalog-revision.js.map +1 -1
- package/dist/core/core-ports.d.ts +41 -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.map +1 -1
- package/dist/core/create-core-server.js +15 -8
- package/dist/core/create-core-server.js.map +1 -1
- package/dist/core/create-core-services.d.ts +22 -5
- package/dist/core/create-core-services.d.ts.map +1 -1
- package/dist/core/create-core-services.js +44 -16
- package/dist/core/create-core-services.js.map +1 -1
- package/dist/core/lifecycle.d.ts +16 -0
- package/dist/core/lifecycle.d.ts.map +1 -1
- package/dist/core/lifecycle.js +12 -2
- package/dist/core/lifecycle.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/modules/access/access-control.interface.d.ts +39 -9
- package/dist/modules/access/access-control.interface.d.ts.map +1 -1
- package/dist/modules/access/access-control.service.d.ts +15 -3
- package/dist/modules/access/access-control.service.d.ts.map +1 -1
- package/dist/modules/access/access-control.service.js +239 -75
- package/dist/modules/access/access-control.service.js.map +1 -1
- package/dist/modules/access/access-mutation.service.d.ts +22 -24
- package/dist/modules/access/access-mutation.service.d.ts.map +1 -1
- package/dist/modules/access/access-mutation.service.js +48 -51
- package/dist/modules/access/access-mutation.service.js.map +1 -1
- package/dist/modules/access/access-view.d.ts.map +1 -1
- package/dist/modules/access/access-view.js +12 -11
- package/dist/modules/access/access-view.js.map +1 -1
- package/dist/modules/access/access.routes.d.ts +3 -0
- package/dist/modules/access/access.routes.d.ts.map +1 -1
- package/dist/modules/access/access.routes.js +58 -33
- package/dist/modules/access/access.routes.js.map +1 -1
- package/dist/modules/access/groups-admin.routes.d.ts.map +1 -1
- package/dist/modules/access/groups-admin.routes.js +4 -2
- package/dist/modules/access/groups-admin.routes.js.map +1 -1
- package/dist/modules/access/groups-admin.service.d.ts +44 -13
- package/dist/modules/access/groups-admin.service.d.ts.map +1 -1
- package/dist/modules/access/groups-admin.service.js +80 -38
- package/dist/modules/access/groups-admin.service.js.map +1 -1
- package/dist/modules/access/groups-edit.d.ts +1 -1
- package/dist/modules/access/groups-edit.d.ts.map +1 -1
- package/dist/modules/access/groups-edit.js +1 -1
- package/dist/modules/access/groups-edit.js.map +1 -1
- package/dist/modules/access/index.d.ts +1 -1
- package/dist/modules/access/index.d.ts.map +1 -1
- package/dist/modules/access/reference-scan.d.ts +116 -24
- package/dist/modules/access/reference-scan.d.ts.map +1 -1
- package/dist/modules/access/reference-scan.js +305 -44
- package/dist/modules/access/reference-scan.js.map +1 -1
- package/dist/modules/access/roles-admin.service.d.ts +17 -8
- package/dist/modules/access/roles-admin.service.d.ts.map +1 -1
- package/dist/modules/access/roles-admin.service.js +32 -23
- package/dist/modules/access/roles-admin.service.js.map +1 -1
- package/dist/modules/access-model/access-grammar.d.ts +35 -10
- package/dist/modules/access-model/access-grammar.d.ts.map +1 -1
- package/dist/modules/access-model/access-grammar.js +60 -20
- package/dist/modules/access-model/access-grammar.js.map +1 -1
- package/dist/modules/access-model/access-splice.d.ts +22 -18
- package/dist/modules/access-model/access-splice.d.ts.map +1 -1
- package/dist/modules/access-model/access-splice.js +20 -14
- package/dist/modules/access-model/access-splice.js.map +1 -1
- package/dist/modules/access-model/group-files.d.ts +1 -0
- package/dist/modules/access-model/group-files.d.ts.map +1 -1
- package/dist/modules/access-model/group-files.js +5 -1
- package/dist/modules/access-model/group-files.js.map +1 -1
- package/dist/modules/agent-guide/agent-guide.d.ts +47 -7
- package/dist/modules/agent-guide/agent-guide.d.ts.map +1 -1
- package/dist/modules/agent-guide/agent-guide.js +103 -13
- package/dist/modules/agent-guide/agent-guide.js.map +1 -1
- package/dist/modules/agent-guide/agent-guide.tools.d.ts +6 -2
- package/dist/modules/agent-guide/agent-guide.tools.d.ts.map +1 -1
- package/dist/modules/agent-guide/agent-guide.tools.js +46 -22
- package/dist/modules/agent-guide/agent-guide.tools.js.map +1 -1
- package/dist/modules/agent-guide/guide-budget.d.ts +48 -0
- package/dist/modules/agent-guide/guide-budget.d.ts.map +1 -0
- package/dist/modules/agent-guide/guide-budget.js +67 -0
- package/dist/modules/agent-guide/guide-budget.js.map +1 -0
- package/dist/modules/agent-guide/index.d.ts +2 -1
- package/dist/modules/agent-guide/index.d.ts.map +1 -1
- package/dist/modules/agent-guide/index.js +2 -1
- package/dist/modules/agent-guide/index.js.map +1 -1
- package/dist/modules/agent-instructions/compose.d.ts +3 -1
- package/dist/modules/agent-instructions/compose.d.ts.map +1 -1
- package/dist/modules/agent-instructions/compose.js +7 -1
- package/dist/modules/agent-instructions/compose.js.map +1 -1
- package/dist/modules/agent-instructions/shared-file-rules.d.ts +5 -1
- package/dist/modules/agent-instructions/shared-file-rules.d.ts.map +1 -1
- package/dist/modules/agent-instructions/shared-file-rules.js +26 -9
- package/dist/modules/agent-instructions/shared-file-rules.js.map +1 -1
- package/dist/modules/agent-scope/agent-scope.contract.d.ts +67 -0
- package/dist/modules/agent-scope/agent-scope.contract.d.ts.map +1 -0
- package/dist/modules/agent-scope/agent-scope.contract.js +27 -0
- package/dist/modules/agent-scope/agent-scope.contract.js.map +1 -0
- package/dist/modules/agent-scope/connection-scope.d.ts +111 -0
- package/dist/modules/agent-scope/connection-scope.d.ts.map +1 -0
- package/dist/modules/agent-scope/connection-scope.js +165 -0
- package/dist/modules/agent-scope/connection-scope.js.map +1 -0
- package/dist/modules/agent-scope/index.d.ts +3 -0
- package/dist/modules/agent-scope/index.d.ts.map +1 -0
- package/dist/modules/agent-scope/index.js +3 -0
- package/dist/modules/agent-scope/index.js.map +1 -0
- package/dist/modules/audit/agent-audit.service.d.ts.map +1 -1
- package/dist/modules/audit/agent-audit.service.js +2 -0
- package/dist/modules/audit/agent-audit.service.js.map +1 -1
- package/dist/modules/audit/audit.contract.d.ts +6 -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/auth/account-admission.d.ts +12 -0
- package/dist/modules/auth/account-admission.d.ts.map +1 -1
- package/dist/modules/auth/account-admission.js +15 -0
- package/dist/modules/auth/account-admission.js.map +1 -1
- package/dist/modules/auth/auth.middleware.d.ts +27 -1
- package/dist/modules/auth/auth.middleware.d.ts.map +1 -1
- package/dist/modules/auth/auth.middleware.js +42 -4
- package/dist/modules/auth/auth.middleware.js.map +1 -1
- package/dist/modules/auth/auth.routes.d.ts +13 -9
- package/dist/modules/auth/auth.routes.d.ts.map +1 -1
- package/dist/modules/auth/auth.routes.js +35 -29
- package/dist/modules/auth/auth.routes.js.map +1 -1
- package/dist/modules/auth/auth.service.d.ts +55 -6
- package/dist/modules/auth/auth.service.d.ts.map +1 -1
- package/dist/modules/auth/auth.service.js +128 -34
- package/dist/modules/auth/auth.service.js.map +1 -1
- package/dist/modules/auth/index.d.ts +1 -1
- package/dist/modules/auth/index.d.ts.map +1 -1
- package/dist/modules/auth/index.js +1 -1
- package/dist/modules/auth/index.js.map +1 -1
- package/dist/modules/auth/oidc-auth-provider.d.ts.map +1 -1
- package/dist/modules/auth/oidc-auth-provider.js +2 -9
- package/dist/modules/auth/oidc-auth-provider.js.map +1 -1
- package/dist/modules/code-mode/code-mode.tool.js +2 -2
- package/dist/modules/code-mode/code-mode.tool.js.map +1 -1
- package/dist/modules/connection-probe/connection-probe.service.d.ts +0 -12
- package/dist/modules/connection-probe/connection-probe.service.d.ts.map +1 -1
- package/dist/modules/connection-probe/connection-probe.service.js +1 -38
- package/dist/modules/connection-probe/connection-probe.service.js.map +1 -1
- package/dist/modules/database/core-schema.d.ts +68 -0
- package/dist/modules/database/core-schema.d.ts.map +1 -1
- package/dist/modules/database/core-schema.js +33 -0
- package/dist/modules/database/core-schema.js.map +1 -1
- package/dist/modules/declared-variables/declared-variables.routes.d.ts +8 -1
- package/dist/modules/declared-variables/declared-variables.routes.d.ts.map +1 -1
- package/dist/modules/declared-variables/declared-variables.routes.js +13 -2
- package/dist/modules/declared-variables/declared-variables.routes.js.map +1 -1
- package/dist/modules/embed/embed.tools.d.ts.map +1 -1
- package/dist/modules/embed/embed.tools.js +5 -0
- package/dist/modules/embed/embed.tools.js.map +1 -1
- package/dist/modules/kb-fs/index.d.ts +2 -0
- package/dist/modules/kb-fs/index.d.ts.map +1 -1
- package/dist/modules/kb-fs/index.js +1 -0
- package/dist/modules/kb-fs/index.js.map +1 -1
- package/dist/modules/kb-fs/locking-filesystem.d.ts.map +1 -1
- package/dist/modules/kb-fs/locking-filesystem.js +7 -1
- package/dist/modules/kb-fs/locking-filesystem.js.map +1 -1
- package/dist/modules/kb-fs/repo-path.d.ts +26 -6
- package/dist/modules/kb-fs/repo-path.d.ts.map +1 -1
- package/dist/modules/kb-fs/repo-path.js +22 -7
- package/dist/modules/kb-fs/repo-path.js.map +1 -1
- package/dist/modules/kb-fs/tmp-ref.d.ts +36 -0
- package/dist/modules/kb-fs/tmp-ref.d.ts.map +1 -0
- package/dist/modules/kb-fs/tmp-ref.js +76 -0
- package/dist/modules/kb-fs/tmp-ref.js.map +1 -0
- package/dist/modules/mcp/mcp-auth.middleware.d.ts +7 -0
- package/dist/modules/mcp/mcp-auth.middleware.d.ts.map +1 -1
- package/dist/modules/mcp/mcp-auth.middleware.js +14 -1
- package/dist/modules/mcp/mcp-auth.middleware.js.map +1 -1
- package/dist/modules/mcp/mcp.routes.d.ts +7 -1
- package/dist/modules/mcp/mcp.routes.d.ts.map +1 -1
- package/dist/modules/mcp/mcp.routes.js +39 -4
- package/dist/modules/mcp/mcp.routes.js.map +1 -1
- package/dist/modules/mcp/mcp.service.d.ts +11 -0
- package/dist/modules/mcp/mcp.service.d.ts.map +1 -1
- package/dist/modules/mcp/mcp.service.js +74 -48
- package/dist/modules/mcp/mcp.service.js.map +1 -1
- package/dist/modules/mcp/oauth/bevel-oauth-provider.d.ts +24 -1
- package/dist/modules/mcp/oauth/bevel-oauth-provider.d.ts.map +1 -1
- package/dist/modules/mcp/oauth/bevel-oauth-provider.js +45 -10
- package/dist/modules/mcp/oauth/bevel-oauth-provider.js.map +1 -1
- package/dist/modules/mcp/oauth/oauth-consent.routes.d.ts +9 -0
- package/dist/modules/mcp/oauth/oauth-consent.routes.d.ts.map +1 -1
- package/dist/modules/mcp/oauth/oauth-consent.routes.js +34 -1
- package/dist/modules/mcp/oauth/oauth-consent.routes.js.map +1 -1
- 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.map +1 -1
- package/dist/modules/plugins/plugin-links.d.ts +18 -2
- package/dist/modules/plugins/plugin-links.d.ts.map +1 -1
- package/dist/modules/plugins/plugin-links.js.map +1 -1
- package/dist/modules/plugins/plugins.routes.d.ts +5 -1
- package/dist/modules/plugins/plugins.routes.d.ts.map +1 -1
- package/dist/modules/plugins/plugins.routes.js +32 -5
- package/dist/modules/plugins/plugins.routes.js.map +1 -1
- package/dist/modules/secrets-vault/db-secrets-vault.service.d.ts +11 -1
- package/dist/modules/secrets-vault/db-secrets-vault.service.d.ts.map +1 -1
- package/dist/modules/secrets-vault/db-secrets-vault.service.js +159 -24
- package/dist/modules/secrets-vault/db-secrets-vault.service.js.map +1 -1
- package/dist/modules/secrets-vault/index.d.ts +1 -1
- package/dist/modules/secrets-vault/index.d.ts.map +1 -1
- package/dist/modules/secrets-vault/index.js +1 -1
- package/dist/modules/secrets-vault/index.js.map +1 -1
- package/dist/modules/secrets-vault/secrets-vault.contract.d.ts +53 -11
- package/dist/modules/secrets-vault/secrets-vault.contract.d.ts.map +1 -1
- package/dist/modules/secrets-vault/secrets-vault.contract.js +27 -0
- package/dist/modules/secrets-vault/secrets-vault.contract.js.map +1 -1
- package/dist/modules/secrets-vault/secrets-vault.routes.d.ts +9 -0
- package/dist/modules/secrets-vault/secrets-vault.routes.d.ts.map +1 -1
- package/dist/modules/secrets-vault/secrets-vault.routes.js +100 -42
- package/dist/modules/secrets-vault/secrets-vault.routes.js.map +1 -1
- package/dist/modules/settings/oidc-check.d.ts.map +1 -1
- package/dist/modules/settings/oidc-check.js +5 -17
- package/dist/modules/settings/oidc-check.js.map +1 -1
- package/dist/modules/skills/index.d.ts +3 -3
- package/dist/modules/skills/index.d.ts.map +1 -1
- package/dist/modules/skills/index.js +0 -2
- package/dist/modules/skills/index.js.map +1 -1
- package/dist/modules/skills/skills.contract.d.ts +16 -0
- package/dist/modules/skills/skills.contract.d.ts.map +1 -1
- package/dist/modules/skills/skills.service.d.ts.map +1 -1
- package/dist/modules/skills/skills.service.js +6 -1
- package/dist/modules/skills/skills.service.js.map +1 -1
- package/dist/modules/skills/skills.tools.d.ts.map +1 -1
- package/dist/modules/skills/skills.tools.js +25 -13
- package/dist/modules/skills/skills.tools.js.map +1 -1
- package/dist/modules/tool-auth/external-api-key.interface.d.ts +11 -0
- package/dist/modules/tool-auth/external-api-key.interface.d.ts.map +1 -1
- package/dist/modules/tool-auth/external-api-key.interface.js.map +1 -1
- package/dist/modules/tool-auth/external-api-key.service.d.ts +1 -0
- package/dist/modules/tool-auth/external-api-key.service.d.ts.map +1 -1
- package/dist/modules/tool-auth/external-api-key.service.js +4 -1
- package/dist/modules/tool-auth/external-api-key.service.js.map +1 -1
- package/dist/modules/tool-auth/index.d.ts +1 -1
- package/dist/modules/tool-auth/index.d.ts.map +1 -1
- package/dist/modules/tool-auth/internal-token.service.d.ts +9 -0
- package/dist/modules/tool-auth/internal-token.service.d.ts.map +1 -1
- package/dist/modules/tool-auth/internal-token.service.js +1 -0
- package/dist/modules/tool-auth/internal-token.service.js.map +1 -1
- package/dist/modules/tool-auth/tool-auth.middleware.d.ts +27 -3
- package/dist/modules/tool-auth/tool-auth.middleware.d.ts.map +1 -1
- package/dist/modules/tool-auth/tool-auth.middleware.js +32 -6
- package/dist/modules/tool-auth/tool-auth.middleware.js.map +1 -1
- package/dist/modules/tool-helpers/tool-context.d.ts +7 -0
- package/dist/modules/tool-helpers/tool-context.d.ts.map +1 -1
- package/dist/modules/tool-helpers/tool-context.js +3 -0
- package/dist/modules/tool-helpers/tool-context.js.map +1 -1
- package/dist/modules/tool-helpers/tool-def.js +1 -1
- package/dist/modules/tool-helpers/tool-def.js.map +1 -1
- package/dist/modules/tool-helpers/tool-handler.d.ts +15 -0
- package/dist/modules/tool-helpers/tool-handler.d.ts.map +1 -1
- package/dist/modules/tool-helpers/tool-handler.js +19 -0
- package/dist/modules/tool-helpers/tool-handler.js.map +1 -1
- package/dist/modules/tool-helpers/tool.contract.d.ts +10 -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-helpers/validate-token.d.ts +3 -1
- package/dist/modules/tool-helpers/validate-token.d.ts.map +1 -1
- package/dist/modules/tool-helpers/validate-token.js +1 -1
- package/dist/modules/tool-helpers/validate-token.js.map +1 -1
- package/dist/modules/tool-manuals/index.d.ts +3 -3
- package/dist/modules/tool-manuals/index.d.ts.map +1 -1
- package/dist/modules/tool-manuals/index.js +0 -2
- package/dist/modules/tool-manuals/index.js.map +1 -1
- package/dist/modules/tool-manuals/mcp-json-discovery.d.ts +7 -1
- package/dist/modules/tool-manuals/mcp-json-discovery.d.ts.map +1 -1
- package/dist/modules/tool-manuals/mcp-json-discovery.js +69 -38
- package/dist/modules/tool-manuals/mcp-json-discovery.js.map +1 -1
- package/dist/modules/tool-manuals/tool-manuals.contract.d.ts +46 -6
- package/dist/modules/tool-manuals/tool-manuals.contract.d.ts.map +1 -1
- package/dist/modules/tool-manuals/tool-manuals.routes.d.ts +7 -1
- package/dist/modules/tool-manuals/tool-manuals.routes.d.ts.map +1 -1
- package/dist/modules/tool-manuals/tool-manuals.routes.js +41 -4
- package/dist/modules/tool-manuals/tool-manuals.routes.js.map +1 -1
- package/dist/modules/tool-manuals/tool-manuals.service.d.ts +24 -13
- package/dist/modules/tool-manuals/tool-manuals.service.d.ts.map +1 -1
- package/dist/modules/tool-manuals/tool-manuals.service.js +138 -59
- package/dist/modules/tool-manuals/tool-manuals.service.js.map +1 -1
- package/dist/modules/tool-manuals/tool-manuals.tools.d.ts +8 -2
- package/dist/modules/tool-manuals/tool-manuals.tools.d.ts.map +1 -1
- package/dist/modules/tool-manuals/tool-manuals.tools.js +56 -20
- package/dist/modules/tool-manuals/tool-manuals.tools.js.map +1 -1
- package/dist/modules/tool-registry/manual.routes.d.ts +8 -1
- package/dist/modules/tool-registry/manual.routes.d.ts.map +1 -1
- package/dist/modules/tool-registry/manual.routes.js +27 -7
- package/dist/modules/tool-registry/manual.routes.js.map +1 -1
- package/dist/modules/tool-registry/tool.contract.d.ts +7 -0
- package/dist/modules/tool-registry/tool.contract.d.ts.map +1 -1
- package/dist/modules/tool-registry/tool.contract.js.map +1 -1
- package/dist/modules/workflow/agent-tools/workflow.tools.d.ts.map +1 -1
- package/dist/modules/workflow/agent-tools/workflow.tools.js +36 -27
- package/dist/modules/workflow/agent-tools/workflow.tools.js.map +1 -1
- package/dist/modules/workflow/git/git.service.d.ts +2 -2
- package/dist/modules/workflow/git/git.service.d.ts.map +1 -1
- package/dist/modules/workflow/git/git.service.js +20 -35
- package/dist/modules/workflow/git/git.service.js.map +1 -1
- package/dist/modules/workflow/workflow.service.d.ts +2 -1
- package/dist/modules/workflow/workflow.service.d.ts.map +1 -1
- package/dist/modules/workflow/workflow.service.js +3 -0
- package/dist/modules/workflow/workflow.service.js.map +1 -1
- package/dist/modules/workspace/agent-access.gate.d.ts +1 -1
- package/dist/modules/workspace/agent-access.gate.d.ts.map +1 -1
- package/dist/modules/workspace/agent-access.gate.js +1 -1
- package/dist/modules/workspace/agent-access.gate.js.map +1 -1
- package/dist/modules/workspace/file-readers/doc-extract.service.d.ts +28 -4
- package/dist/modules/workspace/file-readers/doc-extract.service.d.ts.map +1 -1
- package/dist/modules/workspace/file-readers/doc-extract.service.js +61 -40
- package/dist/modules/workspace/file-readers/doc-extract.service.js.map +1 -1
- package/dist/modules/workspace/index.d.ts +8 -0
- package/dist/modules/workspace/index.d.ts.map +1 -1
- package/dist/modules/workspace/index.js +8 -0
- package/dist/modules/workspace/index.js.map +1 -1
- package/dist/modules/workspace/nul-scan.d.ts +19 -0
- package/dist/modules/workspace/nul-scan.d.ts.map +1 -0
- package/dist/modules/workspace/nul-scan.js +55 -0
- package/dist/modules/workspace/nul-scan.js.map +1 -0
- package/dist/modules/workspace/pattern-matcher.contract.d.ts +110 -27
- package/dist/modules/workspace/pattern-matcher.contract.d.ts.map +1 -1
- package/dist/modules/workspace/pattern-matcher.contract.js +30 -13
- package/dist/modules/workspace/pattern-matcher.contract.js.map +1 -1
- package/dist/modules/workspace/ripgrep-search.d.ts +54 -0
- package/dist/modules/workspace/ripgrep-search.d.ts.map +1 -0
- package/dist/modules/workspace/ripgrep-search.js +657 -0
- package/dist/modules/workspace/ripgrep-search.js.map +1 -0
- package/dist/modules/workspace/ripgrep-version.d.ts +15 -0
- package/dist/modules/workspace/ripgrep-version.d.ts.map +1 -0
- package/dist/modules/workspace/ripgrep-version.js +31 -0
- package/dist/modules/workspace/ripgrep-version.js.map +1 -0
- package/dist/modules/workspace/startup/beside-checkout.d.ts +8 -5
- package/dist/modules/workspace/startup/beside-checkout.d.ts.map +1 -1
- package/dist/modules/workspace/startup/beside-checkout.js +14 -5
- package/dist/modules/workspace/startup/beside-checkout.js.map +1 -1
- package/dist/modules/workspace/worker-pool.d.ts +3 -4
- package/dist/modules/workspace/worker-pool.d.ts.map +1 -1
- package/dist/modules/workspace/worker-pool.js.map +1 -1
- package/dist/modules/workspace/workspace-tmp.d.ts +146 -0
- package/dist/modules/workspace/workspace-tmp.d.ts.map +1 -0
- package/dist/modules/workspace/workspace-tmp.js +435 -0
- package/dist/modules/workspace/workspace-tmp.js.map +1 -0
- package/dist/modules/workspace/workspace.routes.d.ts.map +1 -1
- package/dist/modules/workspace/workspace.routes.js +5 -26
- package/dist/modules/workspace/workspace.routes.js.map +1 -1
- package/dist/modules/workspace/workspace.service.d.ts +47 -6
- package/dist/modules/workspace/workspace.service.d.ts.map +1 -1
- package/dist/modules/workspace/workspace.service.js +86 -6
- package/dist/modules/workspace/workspace.service.js.map +1 -1
- package/dist/modules/workspace/workspace.tools.d.ts +3 -2
- package/dist/modules/workspace/workspace.tools.d.ts.map +1 -1
- package/dist/modules/workspace/workspace.tools.js +531 -137
- package/dist/modules/workspace/workspace.tools.js.map +1 -1
- package/dist/shared/oauth-token-error.d.ts +23 -0
- package/dist/shared/oauth-token-error.d.ts.map +1 -0
- package/dist/shared/oauth-token-error.js +47 -0
- package/dist/shared/oauth-token-error.js.map +1 -0
- package/dist/shared/path-order.d.ts +28 -8
- package/dist/shared/path-order.d.ts.map +1 -1
- package/dist/shared/path-order.js +37 -8
- package/dist/shared/path-order.js.map +1 -1
- package/dist/shared/read-capped.d.ts +19 -0
- package/dist/shared/read-capped.d.ts.map +1 -0
- package/dist/shared/read-capped.js +45 -0
- package/dist/shared/read-capped.js.map +1 -0
- package/migrations/0022_session_version.sql +6 -0
- package/migrations/0023_agent_path.sql +3 -0
- package/migrations/meta/0022_snapshot.json +2360 -0
- package/migrations/meta/0023_snapshot.json +2378 -0
- package/migrations/meta/_journal.json +14 -0
- package/package.json +4 -3
- package/src/__tests__/hexis-catalog.ts +144 -0
- package/src/__tests__/pg-scratch.test.ts +69 -0
- package/src/__tests__/pg-scratch.ts +31 -0
- package/src/__tests__/real-disk.ts +21 -0
- package/src/__tests__/slow-ripgrep.ts +65 -0
- package/src/__tests__/tokens.ts +19 -0
- package/src/__tests__/tool-manuals.ts +32 -0
- package/src/__tests__/tool-wiring.ts +25 -0
- package/src/core/__tests__/boot-without-ripgrep.test.ts +34 -0
- package/src/core/__tests__/catalog-revision.test.ts +89 -0
- package/src/core/__tests__/damaged-document.tools.test.ts +2 -2
- package/src/core/__tests__/gated-boot.test.ts +8 -1
- package/src/core/__tests__/lifecycle.test.ts +46 -13
- package/src/core/__tests__/oauth-sign-in-real-file.test.ts +179 -0
- package/src/core/catalog-revision.ts +24 -2
- package/src/core/core-ports.ts +42 -0
- package/src/core/create-core-server.ts +14 -1
- package/src/core/create-core-services.ts +62 -15
- package/src/core/lifecycle.ts +26 -2
- package/src/index.ts +1 -1
- package/src/modules/access/__tests__/access-control.admin-root-floor.test.ts +12 -0
- package/src/modules/access/__tests__/access-control.colliding-name-cases.test.ts +113 -0
- package/src/modules/access/__tests__/access-control.frontmatter-head.test.ts +117 -0
- package/src/modules/access/__tests__/access-control.group-named-admin.test.ts +122 -0
- package/src/modules/access/__tests__/access-control.preview-relocation.test.ts +50 -0
- package/src/modules/access/__tests__/access-declarations.test.ts +19 -0
- package/src/modules/access/__tests__/access-groups.test.ts +55 -22
- package/src/modules/access/__tests__/access-mutation.service.test.ts +85 -59
- package/src/modules/access/__tests__/access-restrict-here.test.ts +7 -5
- package/src/modules/access/__tests__/access.routes.admins.test.ts +1 -0
- package/src/modules/access/__tests__/access.routes.batch.test.ts +2 -0
- package/src/modules/access/__tests__/access.routes.folder-governs.test.ts +2 -0
- package/src/modules/access/__tests__/access.routes.group-grant.test.ts +50 -14
- package/src/modules/access/__tests__/access.routes.overrides.test.ts +2 -1
- package/src/modules/access/__tests__/access.routes.proposal-branch.test.ts +1 -0
- package/src/modules/access/__tests__/access.routes.prospective.test.ts +52 -10
- package/src/modules/access/__tests__/access.routes.revoke.test.ts +18 -13
- package/src/modules/access/__tests__/access.routes.unknown-email.test.ts +2 -0
- package/src/modules/access/__tests__/grant-sources.test.ts +20 -15
- package/src/modules/access/__tests__/groups-admin.routes.test.ts +61 -0
- package/src/modules/access/__tests__/groups-admin.service.test.ts +211 -18
- package/src/modules/access/__tests__/holder-changes.test.ts +127 -0
- package/src/modules/access/__tests__/reference-scan.test.ts +366 -14
- package/src/modules/access/__tests__/roles-admin.security.test.ts +1 -1
- package/src/modules/access/__tests__/roles-admin.service.test.ts +43 -22
- package/src/modules/access/__tests__/roles-capabilities.test.ts +6 -2
- package/src/modules/access/__tests__/roles.routes.test.ts +1 -1
- package/src/modules/access/access-control.interface.ts +43 -10
- package/src/modules/access/access-control.service.ts +250 -72
- package/src/modules/access/access-mutation.service.ts +48 -53
- package/src/modules/access/access-view.ts +12 -10
- package/src/modules/access/access.routes.ts +66 -37
- package/src/modules/access/groups-admin.routes.ts +4 -2
- package/src/modules/access/groups-admin.service.ts +114 -44
- package/src/modules/access/groups-edit.ts +1 -1
- package/src/modules/access/index.ts +1 -1
- package/src/modules/access/reference-scan.ts +319 -46
- package/src/modules/access/roles-admin.service.ts +43 -26
- package/src/modules/access/synced-groups-writer.ts +1 -1
- package/src/modules/access-model/__tests__/access-grammar.test.ts +38 -1
- package/src/modules/access-model/__tests__/access-splice.test.ts +50 -8
- package/src/modules/access-model/access-grammar.ts +65 -20
- package/src/modules/access-model/access-splice.ts +31 -23
- package/src/modules/access-model/group-files.ts +5 -0
- package/src/modules/agent-guide/__tests__/agent-guide.test.ts +110 -25
- package/src/modules/agent-guide/__tests__/agent-guide.tools.test.ts +38 -11
- package/src/modules/agent-guide/__tests__/guide-budget.test.ts +95 -0
- package/src/modules/agent-guide/__tests__/guide-eval.test.ts +182 -0
- package/src/modules/agent-guide/__tests__/guide-matches-code.test.ts +263 -0
- package/src/modules/agent-guide/__tests__/tool-surface.json +514 -0
- package/src/modules/agent-guide/__tests__/tool-surface.test.ts +75 -0
- package/src/modules/agent-guide/agent-guide.tools.ts +51 -22
- package/src/modules/agent-guide/agent-guide.ts +120 -13
- package/src/modules/agent-guide/guide-budget.ts +73 -0
- package/src/modules/agent-guide/index.ts +12 -0
- package/src/modules/agent-instructions/__tests__/shared-file-rules.test.ts +5 -4
- package/src/modules/agent-instructions/compose.ts +7 -1
- package/src/modules/agent-instructions/shared-file-rules.ts +27 -9
- package/src/modules/agent-scope/__tests__/agent-surfaces.connect-as.test.ts +421 -0
- package/src/modules/agent-scope/__tests__/connection-scope.test.ts +46 -0
- package/src/modules/agent-scope/__tests__/in-memory-kb.ts +148 -0
- package/src/modules/agent-scope/agent-scope.contract.ts +83 -0
- package/src/modules/agent-scope/connection-scope.ts +199 -0
- package/src/modules/agent-scope/index.ts +15 -0
- package/src/modules/audit/agent-audit.service.ts +2 -0
- package/src/modules/audit/audit.contract.ts +6 -0
- package/src/modules/auth/__tests__/auth.middleware.test.ts +30 -2
- package/src/modules/auth/__tests__/auth.routes.test.ts +71 -5
- package/src/modules/auth/__tests__/auth.service.test.ts +90 -9
- package/src/modules/auth/__tests__/password-change-sessions.pg.test.ts +269 -0
- package/src/modules/auth/account-admission.ts +19 -0
- package/src/modules/auth/auth.middleware.ts +45 -4
- package/src/modules/auth/auth.routes.ts +46 -29
- package/src/modules/auth/auth.service.ts +135 -34
- package/src/modules/auth/index.ts +2 -0
- package/src/modules/auth/oidc-auth-provider.ts +2 -9
- package/src/modules/code-mode/code-mode.tool.ts +2 -2
- package/src/modules/connection-probe/__tests__/connection-probe.service.test.ts +5 -24
- package/src/modules/connection-probe/connection-probe.service.ts +1 -34
- package/src/modules/database/__tests__/session-version-migration.pg.test.ts +133 -0
- package/src/modules/database/core-schema.ts +33 -0
- package/src/modules/declared-variables/__tests__/declared-variables.route.test.ts +44 -1
- package/src/modules/declared-variables/declared-variables.routes.ts +12 -1
- package/src/modules/embed/__tests__/embed.tools.test.ts +12 -0
- package/src/modules/embed/embed.tools.ts +5 -0
- package/src/modules/kb-fs/__tests__/locking-filesystem.test.ts +25 -0
- package/src/modules/kb-fs/__tests__/repo-path.test.ts +53 -8
- package/src/modules/kb-fs/index.ts +2 -0
- package/src/modules/kb-fs/locking-filesystem.ts +7 -1
- package/src/modules/kb-fs/repo-path.ts +33 -7
- package/src/modules/kb-fs/tmp-ref.ts +81 -0
- package/src/modules/mcp/__tests__/connect-as.pg.test.ts +137 -0
- package/src/modules/mcp/__tests__/mcp-auth.middleware.test.ts +29 -5
- package/src/modules/mcp/__tests__/mcp-routes-harness.ts +8 -0
- package/src/modules/mcp/__tests__/mcp.connect-as.test.ts +195 -0
- package/src/modules/mcp/__tests__/mcp.routes.connect-as.test.ts +192 -0
- package/src/modules/mcp/__tests__/oauth-consent.connect-as.test.ts +146 -0
- package/src/modules/mcp/mcp-auth.middleware.ts +19 -2
- package/src/modules/mcp/mcp.routes.ts +39 -3
- package/src/modules/mcp/mcp.service.ts +112 -52
- package/src/modules/mcp/oauth/bevel-oauth-provider.ts +46 -8
- package/src/modules/mcp/oauth/oauth-consent.routes.ts +41 -1
- package/src/modules/plugins/__tests__/plugins.tools.test.ts +38 -2
- package/src/modules/plugins/index.ts +1 -1
- package/src/modules/plugins/plugin-links.ts +19 -2
- package/src/modules/plugins/plugins.routes.ts +35 -4
- package/src/modules/secrets-vault/__tests__/connect-pending.route.test.ts +113 -0
- package/src/modules/secrets-vault/__tests__/db-secrets-vault.oauth.test.ts +430 -3
- package/src/modules/secrets-vault/__tests__/oauth-live-declaration.route.test.ts +218 -0
- package/src/modules/secrets-vault/__tests__/oauth-return-to.route.test.ts +39 -6
- package/src/modules/secrets-vault/db-secrets-vault.service.ts +170 -27
- package/src/modules/secrets-vault/index.ts +1 -1
- package/src/modules/secrets-vault/secrets-vault.contract.ts +61 -11
- package/src/modules/secrets-vault/secrets-vault.routes.ts +114 -42
- package/src/modules/settings/oidc-check.ts +5 -18
- package/src/modules/skills/__tests__/skills.service.test.ts +34 -0
- package/src/modules/skills/index.ts +7 -2
- package/src/modules/skills/skills.contract.ts +17 -0
- package/src/modules/skills/skills.service.ts +5 -1
- package/src/modules/skills/skills.tools.ts +45 -14
- package/src/modules/tool-auth/__tests__/external-api-key.service.test.ts +4 -0
- package/src/modules/tool-auth/external-api-key.interface.ts +11 -1
- package/src/modules/tool-auth/external-api-key.service.ts +5 -2
- package/src/modules/tool-auth/index.ts +1 -1
- package/src/modules/tool-auth/internal-token.service.ts +10 -0
- package/src/modules/tool-auth/tool-auth.middleware.ts +45 -3
- package/src/modules/tool-helpers/__tests__/agent-roles-write.test.ts +19 -11
- package/src/modules/tool-helpers/__tests__/can-write.tools.test.ts +3 -1
- package/src/modules/tool-helpers/__tests__/route-tool-schemas.catalog.test.ts +38 -0
- package/src/modules/tool-helpers/tool-context.ts +10 -0
- package/src/modules/tool-helpers/tool-def.ts +1 -1
- package/src/modules/tool-helpers/tool-handler.ts +34 -0
- package/src/modules/tool-helpers/tool.contract.ts +10 -0
- package/src/modules/tool-helpers/validate-token.ts +4 -2
- package/src/modules/tool-manuals/__tests__/tool-manuals.archive.route.test.ts +80 -4
- package/src/modules/tool-manuals/__tests__/tool-manuals.mcp-oauth.test.ts +197 -11
- package/src/modules/tool-manuals/__tests__/tool-manuals.service.test.ts +42 -0
- package/src/modules/tool-manuals/__tests__/tool-manuals.tools.test.ts +99 -8
- package/src/modules/tool-manuals/index.ts +6 -2
- package/src/modules/tool-manuals/mcp-json-discovery.ts +73 -34
- package/src/modules/tool-manuals/tool-manuals.contract.ts +40 -6
- package/src/modules/tool-manuals/tool-manuals.routes.ts +40 -3
- package/src/modules/tool-manuals/tool-manuals.service.ts +169 -61
- package/src/modules/tool-manuals/tool-manuals.tools.ts +81 -25
- package/src/modules/tool-registry/__tests__/tool-description-length.test.ts +6 -113
- package/src/modules/tool-registry/manual.routes.ts +26 -5
- package/src/modules/tool-registry/tool.contract.ts +7 -0
- package/src/modules/workflow/__tests__/workflow.service.facade.test.ts +1 -1
- package/src/modules/workflow/__tests__/workflow.service.sync.test.ts +1 -1
- package/src/modules/workflow/agent-tools/__tests__/workflow.tools.test.ts +54 -3
- package/src/modules/workflow/agent-tools/workflow.tools.ts +36 -27
- package/src/modules/workflow/git/__tests__/git.service.list-branches.test.ts +130 -3
- package/src/modules/workflow/git/git.service.ts +29 -48
- package/src/modules/workflow/workflow.service.ts +5 -0
- package/src/modules/workspace/__tests__/git-internals.security.test.ts +2 -2
- package/src/modules/workspace/__tests__/holds-nul.test.ts +66 -0
- package/src/modules/workspace/__tests__/rest-tool-arguments.test.ts +3 -3
- package/src/modules/workspace/__tests__/ripgrep-search.test.ts +570 -0
- package/src/modules/workspace/__tests__/ripgrep-version.test.ts +29 -0
- package/src/modules/workspace/__tests__/workspace-tmp.tools.test.ts +928 -0
- package/src/modules/workspace/__tests__/workspace.routes.read-gate.test.ts +17 -37
- package/src/modules/workspace/__tests__/workspace.service.read-filter.test.ts +20 -8
- package/src/modules/workspace/__tests__/workspace.tools.agents-file.test.ts +10 -12
- package/src/modules/workspace/__tests__/workspace.tools.branch-errors.test.ts +22 -10
- package/src/modules/workspace/__tests__/workspace.tools.test.ts +549 -162
- package/src/modules/workspace/agent-access.gate.ts +1 -1
- package/src/modules/workspace/file-readers/__tests__/doc-extract.service.test.ts +10 -0
- package/src/modules/workspace/file-readers/doc-extract.service.ts +71 -38
- package/src/modules/workspace/index.ts +20 -0
- package/src/modules/workspace/nul-scan.ts +50 -0
- package/src/modules/workspace/pattern-matcher.contract.ts +123 -32
- package/src/modules/workspace/ripgrep-search.ts +715 -0
- package/src/modules/workspace/ripgrep-version.ts +35 -0
- package/src/modules/workspace/startup/__tests__/beside-checkout.test.ts +11 -0
- package/src/modules/workspace/startup/beside-checkout.ts +13 -5
- package/src/modules/workspace/worker-pool.ts +3 -4
- package/src/modules/workspace/workspace-tmp.ts +457 -0
- package/src/modules/workspace/workspace.routes.ts +6 -27
- package/src/modules/workspace/workspace.service.ts +92 -15
- package/src/modules/workspace/workspace.tools.ts +574 -176
- package/src/shared/__tests__/read-capped.test.ts +68 -0
- package/src/shared/oauth-token-error.ts +46 -0
- package/src/shared/path-order.ts +37 -8
- package/src/shared/read-capped.ts +40 -0
- package/starter-packs/engineering/Plugins/engineering-starter/access.md +1 -1
- package/starter-packs/general/Plugins/general-starter/access.md +1 -1
- package/starter-packs/operations/Plugins/operations-starter/access.md +1 -1
- package/starter-packs/sales/Plugins/sales-starter/access.md +1 -1
- package/starter-packs/support/Plugins/support-starter/access.md +1 -1
- package/agent-guide/finding-things.md +0 -7
- package/agent-guide/introduction.md +0 -27
- package/dist/modules/workspace/bounded-matcher.d.ts +0 -73
- package/dist/modules/workspace/bounded-matcher.d.ts.map +0 -1
- package/dist/modules/workspace/bounded-matcher.js +0 -200
- package/dist/modules/workspace/bounded-matcher.js.map +0 -1
- package/src/modules/workspace/__tests__/bounded-matcher.test.ts +0 -213
- package/src/modules/workspace/bounded-matcher.ts +0 -271
|
@@ -43,6 +43,7 @@ import {
|
|
|
43
43
|
EXTERNAL_KB_MANUAL_NAME,
|
|
44
44
|
MAX_CAPABILITIES,
|
|
45
45
|
type IToolManualService,
|
|
46
|
+
type ConnectorScope,
|
|
46
47
|
type ToolManualDescriptor,
|
|
47
48
|
type ToolManualDescriptorBase,
|
|
48
49
|
type ToolManualSummary,
|
|
@@ -58,6 +59,7 @@ import {
|
|
|
58
59
|
type ToolProbeTarget,
|
|
59
60
|
type ToolVariableScope,
|
|
60
61
|
type ToolVariableOAuth,
|
|
62
|
+
type LiveDeclaration,
|
|
61
63
|
} from './tool-manuals.contract.js';
|
|
62
64
|
|
|
63
65
|
const CACHE_TTL_MS = 60_000;
|
|
@@ -181,6 +183,19 @@ export function describeManualFault(err: unknown): string {
|
|
|
181
183
|
interface ScanResult {
|
|
182
184
|
manuals: ToolManualDescriptor[];
|
|
183
185
|
invalid: InvalidToolManual[];
|
|
186
|
+
/**
|
|
187
|
+
* Every manual the parse refused whose file still says which manual it is,
|
|
188
|
+
* by slug, with the reason. Not a listing surface (`invalid` is that, by
|
|
189
|
+
* path): it lets a sign-in started on a refused declaration answer why,
|
|
190
|
+
* where the slug alone would otherwise find nothing.
|
|
191
|
+
*/
|
|
192
|
+
refused: RefusedManual[];
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
interface RefusedManual {
|
|
196
|
+
slug: string;
|
|
197
|
+
path: string;
|
|
198
|
+
reason: string;
|
|
184
199
|
}
|
|
185
200
|
|
|
186
201
|
/**
|
|
@@ -190,7 +205,7 @@ interface ScanResult {
|
|
|
190
205
|
* convention instance is one push away from every empty scan in the process
|
|
191
206
|
* inheriting another's contents.
|
|
192
207
|
*/
|
|
193
|
-
const emptyScan = (): ScanResult => ({ manuals: [], invalid: [] });
|
|
208
|
+
const emptyScan = (): ScanResult => ({ manuals: [], invalid: [], refused: [] });
|
|
194
209
|
|
|
195
210
|
const manualSerializer = new UtcpManualSerializer();
|
|
196
211
|
const callTemplateSerializer = new CallTemplateSerializer();
|
|
@@ -208,8 +223,8 @@ export interface McpAuthDiscoveryPort {
|
|
|
208
223
|
/**
|
|
209
224
|
* The sign-in endpoints for an OWNER-REGISTERED client: the same metadata
|
|
210
225
|
* walk as `statusFor`, stopping short of dynamic registration — the manual
|
|
211
|
-
* already names its `clientId`. Nothing is persisted;
|
|
212
|
-
*
|
|
226
|
+
* already names its `clientId`. Nothing is persisted; every sign-in start
|
|
227
|
+
* completes the declaration afresh (`liveDeclaration`). Optional so a port that
|
|
213
228
|
* only knows the zero-config path still satisfies the interface.
|
|
214
229
|
*/
|
|
215
230
|
providerForDeclaredClient?(manualName: string, mcpUrl: string, clientId: string): Promise<McpAuthDiscoveryResult>;
|
|
@@ -304,8 +319,8 @@ export class ToolManualService implements IToolManualService {
|
|
|
304
319
|
return (await this.accessibleManuals(userEmail)).map(toSummary);
|
|
305
320
|
}
|
|
306
321
|
|
|
307
|
-
async listAccessibleCatalog(userEmail: string): Promise<AccessibleCatalog> {
|
|
308
|
-
const { manuals, invalid } = await this.accessibleScan(userEmail);
|
|
322
|
+
async listAccessibleCatalog(userEmail: string, within?: ConnectorScope): Promise<AccessibleCatalog> {
|
|
323
|
+
const { manuals, invalid } = await this.accessibleScan(userEmail, within);
|
|
309
324
|
return { tools: manuals.map(toSummary), invalid };
|
|
310
325
|
}
|
|
311
326
|
|
|
@@ -313,8 +328,8 @@ export class ToolManualService implements IToolManualService {
|
|
|
313
328
|
return (await this.scan()).manuals.map(toSummary);
|
|
314
329
|
}
|
|
315
330
|
|
|
316
|
-
async catalogFingerprints(userEmail: string): Promise<string[]> {
|
|
317
|
-
return (await this.accessibleManuals(userEmail)).map(manualFingerprint);
|
|
331
|
+
async catalogFingerprints(userEmail: string, within?: ConnectorScope): Promise<string[]> {
|
|
332
|
+
return (await this.accessibleManuals(userEmail, within)).map(manualFingerprint);
|
|
318
333
|
}
|
|
319
334
|
|
|
320
335
|
async getDetail(userEmail: string, slug: string): Promise<ToolManualDetail | null> {
|
|
@@ -341,14 +356,47 @@ export class ToolManualService implements IToolManualService {
|
|
|
341
356
|
};
|
|
342
357
|
}
|
|
343
358
|
|
|
344
|
-
async
|
|
345
|
-
|
|
359
|
+
async liveDeclaration(
|
|
360
|
+
userEmail: string,
|
|
361
|
+
slug: string,
|
|
362
|
+
varName: string,
|
|
363
|
+
): Promise<LiveDeclaration | null> {
|
|
364
|
+
// The disk walk the catalog's scan is built from, run afresh and never
|
|
365
|
+
// cached: a sign-in must follow the file as it is, and the catalog's scan
|
|
366
|
+
// can be a refresh behind it. The whole walk rather than the one file, so
|
|
367
|
+
// the descriptor comes out of exactly the parse, plugin discovery and
|
|
368
|
+
// namespace dedup the catalog applies — a sign-in start is rare and
|
|
369
|
+
// interactive, and a second, single-file reading of the same files is a
|
|
370
|
+
// second place for those rules to drift. A workspace that cannot be opened
|
|
371
|
+
// is an error here, never an empty answer: "no sign-in declared" would be
|
|
372
|
+
// the wrong diagnosis for a server that could not read its files.
|
|
373
|
+
const { manuals, refused } = await this.readableBy(await this.scanDisk(undefined, 'throw'), userEmail);
|
|
374
|
+
const m = manuals.find((x) => x.slug === slug);
|
|
375
|
+
if (!m) {
|
|
376
|
+
// The file is there and says it is this manual, but the parse refused
|
|
377
|
+
// it — e.g. its sign-in names an http:// or private token endpoint. That
|
|
378
|
+
// reason is the answer; "not found" would hide the one thing to fix.
|
|
379
|
+
const r = refused.find((x) => x.slug === slug);
|
|
380
|
+
return r ? { refused: r.reason } : null;
|
|
381
|
+
}
|
|
382
|
+
const variable = (m.variables ?? []).find((v) => v.name === varName);
|
|
383
|
+
// Completed by the catalog's own decoration, on this one fresh descriptor.
|
|
384
|
+
// Only when THIS variable is a sign-in: then the manual has a declared one,
|
|
385
|
+
// so the pass completes its endpoints from the server's metadata and never
|
|
386
|
+
// probes for (or registers) a zero-config client.
|
|
387
|
+
if (variable?.oauth) await this.decorateMcpOAuth([m]);
|
|
388
|
+
return { manual: toSummary(m), ...(variable ? { variable } : {}) };
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
async listLocalOnly(userEmail: string, within?: ConnectorScope): Promise<{ slug: string; name: string; path: string }[]> {
|
|
392
|
+
const manuals = await this.accessibleManuals(userEmail, within);
|
|
346
393
|
return manuals.filter((m) => m.remote === false).map((m) => ({ slug: m.slug, name: m.name, path: m.path }));
|
|
347
394
|
}
|
|
348
395
|
|
|
349
396
|
async listDeclaredOnlyOnBranch(
|
|
350
397
|
userEmail: string,
|
|
351
398
|
branch: string,
|
|
399
|
+
within?: ConnectorScope,
|
|
352
400
|
): Promise<{ name: string; path: string; type: ToolManualType }[]> {
|
|
353
401
|
if (!branch || branch === this.kb.defaultBranch) return [];
|
|
354
402
|
// Only a draft this process already holds a clone of — the one the caller
|
|
@@ -377,7 +425,7 @@ export class ToolManualService implements IToolManualService {
|
|
|
377
425
|
pending.map((m) => m.path),
|
|
378
426
|
);
|
|
379
427
|
return pending
|
|
380
|
-
.filter((m) => allowed.get(m.path) === true)
|
|
428
|
+
.filter((m) => allowed.get(m.path) === true && (within === undefined || within(m.path)))
|
|
381
429
|
.map((m) => ({ name: m.name, path: m.path, type: m.type }));
|
|
382
430
|
}
|
|
383
431
|
|
|
@@ -456,8 +504,11 @@ export class ToolManualService implements IToolManualService {
|
|
|
456
504
|
return { name: m.name, type: m.type, remote: m.remote, healthCheck: m.healthCheck, callTemplate };
|
|
457
505
|
}
|
|
458
506
|
|
|
459
|
-
async toManualCallTemplates(
|
|
460
|
-
|
|
507
|
+
async toManualCallTemplates(
|
|
508
|
+
userEmail: string,
|
|
509
|
+
opts?: { remoteOnly?: boolean; within?: ConnectorScope },
|
|
510
|
+
): Promise<CallTemplate[]> {
|
|
511
|
+
const manuals = await this.accessibleManuals(userEmail, opts?.within);
|
|
461
512
|
const out: CallTemplate[] = [];
|
|
462
513
|
for (const m of manuals) {
|
|
463
514
|
// Remote consumers (the hosted MCP proxy) don't get local-only manuals —
|
|
@@ -474,11 +525,17 @@ export class ToolManualService implements IToolManualService {
|
|
|
474
525
|
return out;
|
|
475
526
|
}
|
|
476
527
|
|
|
477
|
-
async resolveInlineManual(
|
|
528
|
+
async resolveInlineManual(
|
|
529
|
+
userEmail: string,
|
|
530
|
+
slug: string,
|
|
531
|
+
opts?: { within?: ConnectorScope },
|
|
532
|
+
): Promise<UtcpManualDict | null> {
|
|
478
533
|
const found = (await this.scan()).manuals.find((m) => m.slug === slug);
|
|
479
534
|
if (!found || found.type !== 'inline') return null;
|
|
480
535
|
const wsId = this.kb.defaultWorkspaceId();
|
|
481
536
|
if (!(await this.accessControl.canRead(wsId, userEmail, found.path))) return null;
|
|
537
|
+
// After the read gate, as every narrowing is: a connection's scope can only take away.
|
|
538
|
+
if (opts?.within && !opts.within(found.path)) return null;
|
|
482
539
|
try {
|
|
483
540
|
return manualSerializer.validateDict({
|
|
484
541
|
utcp_version: '1.1.0',
|
|
@@ -590,8 +647,8 @@ export class ToolManualService implements IToolManualService {
|
|
|
590
647
|
};
|
|
591
648
|
}
|
|
592
649
|
|
|
593
|
-
private async accessibleManuals(userEmail: string): Promise<ToolManualDescriptor[]> {
|
|
594
|
-
return (await this.accessibleScan(userEmail)).manuals;
|
|
650
|
+
private async accessibleManuals(userEmail: string, within?: ConnectorScope): Promise<ToolManualDescriptor[]> {
|
|
651
|
+
return (await this.accessibleScan(userEmail, within)).manuals;
|
|
595
652
|
}
|
|
596
653
|
|
|
597
654
|
/**
|
|
@@ -599,22 +656,33 @@ export class ToolManualService implements IToolManualService {
|
|
|
599
656
|
* ONE `canReadBatch`. Both halves are paths in the same workspace judged by
|
|
600
657
|
* the same rule, and splitting them into two calls would pay a second
|
|
601
658
|
* round-trip to ask the same question.
|
|
659
|
+
*
|
|
660
|
+
* `within` narrows the answer to a connection's connectors, AFTER the read
|
|
661
|
+
* gate: it can take a manual out of what the caller may read, never put one
|
|
662
|
+
* in. Absent, the answer is the caller's whole readable catalog.
|
|
602
663
|
*/
|
|
603
|
-
private async accessibleScan(userEmail: string): Promise<ScanResult> {
|
|
604
|
-
|
|
605
|
-
|
|
664
|
+
private async accessibleScan(userEmail: string, within?: ConnectorScope): Promise<ScanResult> {
|
|
665
|
+
return this.readableBy(await this.scan(), userEmail, within);
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
/** A scan cut to what this caller may read — see {@link accessibleScan}. */
|
|
669
|
+
private async readableBy(scan: ScanResult, userEmail: string, within?: ConnectorScope): Promise<ScanResult> {
|
|
670
|
+
const { manuals, invalid, refused } = scan;
|
|
671
|
+
if (manuals.length === 0 && invalid.length === 0 && refused.length === 0) return emptyScan();
|
|
606
672
|
const wsId = this.kb.defaultWorkspaceId();
|
|
607
673
|
const allowed = await this.accessControl.canReadBatch(wsId, userEmail, [
|
|
608
|
-
...new Set([...manuals.map((m) => m.path), ...invalid.map((i) => i.path)]),
|
|
674
|
+
...new Set([...manuals.map((m) => m.path), ...invalid.map((i) => i.path), ...refused.map((r) => r.path)]),
|
|
609
675
|
]);
|
|
610
676
|
// Fail closed: keep an entry only on an explicit `true` verdict (a missing
|
|
611
677
|
// entry is treated as denied, matching the KB's default-deny read model).
|
|
612
678
|
// A REFUSED file is gated the same way a listed one is: its path is a fact
|
|
613
679
|
// about the knowledge base, and "there is a broken tool at this path" is
|
|
614
680
|
// not something to tell someone who may not read that path.
|
|
681
|
+
const inScope = (p: string) => allowed.get(p) === true && (within === undefined || within(p));
|
|
615
682
|
return {
|
|
616
|
-
manuals: manuals.filter((m) =>
|
|
617
|
-
invalid: invalid.filter((i) =>
|
|
683
|
+
manuals: manuals.filter((m) => inScope(m.path)),
|
|
684
|
+
invalid: invalid.filter((i) => inScope(i.path)),
|
|
685
|
+
refused: refused.filter((r) => inScope(r.path)),
|
|
618
686
|
};
|
|
619
687
|
}
|
|
620
688
|
|
|
@@ -639,14 +707,14 @@ export class ToolManualService implements IToolManualService {
|
|
|
639
707
|
// See `TtlCache.begin`: taken before the read so an `invalidate()` that
|
|
640
708
|
// lands mid-scan discards this result instead of being overwritten by it.
|
|
641
709
|
const token = this.cache.begin();
|
|
642
|
-
const
|
|
710
|
+
const scanned = await this.scanDisk();
|
|
711
|
+
const { manuals } = scanned;
|
|
643
712
|
await this.decorateMcpOAuth(manuals);
|
|
644
713
|
// AFTER the oauth decoration, so an injected `${MCP_OAUTH}` header ref is
|
|
645
714
|
// already declared and isn't re-surfaced as a bare admin key.
|
|
646
715
|
for (const m of manuals) this.surfaceReferencedVariables(m);
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
return result;
|
|
716
|
+
this.cache.set(scanned, token);
|
|
717
|
+
return scanned;
|
|
650
718
|
}
|
|
651
719
|
|
|
652
720
|
/**
|
|
@@ -817,11 +885,12 @@ export class ToolManualService implements IToolManualService {
|
|
|
817
885
|
* (the owner registered an app with a provider that offers no dynamic
|
|
818
886
|
* registration — HubSpot, Google) gets its endpoints, PKCE and resource
|
|
819
887
|
* indicator from the server's own OAuth metadata, exactly as the zero-config
|
|
820
|
-
* path would. The descriptor is completed IN MEMORY
|
|
821
|
-
*
|
|
822
|
-
*
|
|
823
|
-
* incomplete and `setup.reason` says so — the secret
|
|
824
|
-
* with the same reason instead of
|
|
888
|
+
* path would. The descriptor is completed IN MEMORY, for the catalog's scan
|
|
889
|
+
* and for every sign-in start (`liveDeclaration`) alike, so nothing here
|
|
890
|
+
* persists. When the metadata can't be had, the declaration stays
|
|
891
|
+
* incomplete and `setup.reason` says so — the client-secret save and the
|
|
892
|
+
* sign-in start then refuse with the same reason instead of running a
|
|
893
|
+
* provider with no endpoints.
|
|
825
894
|
*/
|
|
826
895
|
private async completeDeclaredOAuth(
|
|
827
896
|
discovery: McpAuthDiscoveryPort,
|
|
@@ -880,11 +949,22 @@ export class ToolManualService implements IToolManualService {
|
|
|
880
949
|
* calls: a refusal lives only in the scan it came from, so a fixed file is a
|
|
881
950
|
* valid manual on the very next scan.
|
|
882
951
|
*/
|
|
883
|
-
private async scanDisk(
|
|
952
|
+
private async scanDisk(
|
|
953
|
+
branch: string = this.kb.defaultBranch,
|
|
954
|
+
/**
|
|
955
|
+
* What a workspace that cannot be opened means. For the catalog, an empty
|
|
956
|
+
* scan: a listing surface answers "nothing released" and the next scan
|
|
957
|
+
* tries again. For a sign-in start (`liveDeclaration`), the error itself:
|
|
958
|
+
* an empty answer there would read as "this tool has no sign-in", a
|
|
959
|
+
* misconfiguration, when the server could not read its files at all.
|
|
960
|
+
*/
|
|
961
|
+
workspaceFailure: 'empty' | 'throw' = 'empty',
|
|
962
|
+
): Promise<ScanResult> {
|
|
884
963
|
let wsId: string;
|
|
885
964
|
try {
|
|
886
965
|
wsId = (await this.workspaceService.getOrCreateForBranch(branch)).id;
|
|
887
|
-
} catch {
|
|
966
|
+
} catch (err) {
|
|
967
|
+
if (workspaceFailure === 'throw') throw err;
|
|
888
968
|
return emptyScan();
|
|
889
969
|
}
|
|
890
970
|
const kbRoot = path.join(await this.workspaceService.getWorkspacePath(wsId), this.kbDirName);
|
|
@@ -905,6 +985,7 @@ export class ToolManualService implements IToolManualService {
|
|
|
905
985
|
// The plugins (and their mcp.json text) come from the configured source, so
|
|
906
986
|
// a dialect that expands servers from a registry lands here unchanged.
|
|
907
987
|
const parsed: ToolManualDescriptor[] = [];
|
|
988
|
+
const refused: RefusedManual[] = [];
|
|
908
989
|
const discovered = await this.source.discover(kbRoot);
|
|
909
990
|
for (const plugin of discovered.plugins) {
|
|
910
991
|
if (plugin.mcpJsonText === null) continue; // no servers is the common case, not an error
|
|
@@ -913,7 +994,9 @@ export class ToolManualService implements IToolManualService {
|
|
|
913
994
|
// (a URL, a header, an added or dropped server, a `local: true` flip)
|
|
914
995
|
// moves every server's digest — which is correct, if slightly generous.
|
|
915
996
|
const from = sourceDigest(plugin.mcpJsonText + '\u0000' + (plugin.manifestText ?? ''));
|
|
916
|
-
|
|
997
|
+
const onRefused = (slug: string, reason: string, path: string) =>
|
|
998
|
+
refused.push({ slug, path, reason: describeManualFault(reason) });
|
|
999
|
+
for (const d of descriptorsFromMcpJson(plugin.relFolder, plugin.mcpJsonText, plugin.manifestText, layout, onRefused)) {
|
|
917
1000
|
d.sourceRevision = from;
|
|
918
1001
|
parsed.push(d);
|
|
919
1002
|
}
|
|
@@ -949,6 +1032,8 @@ export class ToolManualService implements IToolManualService {
|
|
|
949
1032
|
// outage from where the author stands: the tool is gone from every
|
|
950
1033
|
// listing, with nothing anywhere saying which file or why.
|
|
951
1034
|
invalid.push({ path: f.rel, reason: describeManualFault(err) });
|
|
1035
|
+
const slug = refusedToolManualName(baseName(f.rel), content);
|
|
1036
|
+
if (slug !== null) refused.push({ slug, path: f.rel, reason: describeManualFault(err) });
|
|
952
1037
|
continue;
|
|
953
1038
|
}
|
|
954
1039
|
// The route slug IS the id (unique after dedup below, snake_case → URL-safe),
|
|
@@ -997,7 +1082,7 @@ export class ToolManualService implements IToolManualService {
|
|
|
997
1082
|
// draft workspace, and a draft's half-written `.tool` is not news about the
|
|
998
1083
|
// served catalog — it would also flap the log every time an agent saves.
|
|
999
1084
|
if (branch === this.kb.defaultBranch) this.logInvalidOnChange(invalid);
|
|
1000
|
-
return { manuals, invalid };
|
|
1085
|
+
return { manuals, invalid, refused };
|
|
1001
1086
|
}
|
|
1002
1087
|
}
|
|
1003
1088
|
|
|
@@ -1109,6 +1194,54 @@ function manualName(raw: string): string {
|
|
|
1109
1194
|
return name;
|
|
1110
1195
|
}
|
|
1111
1196
|
|
|
1197
|
+
/**
|
|
1198
|
+
* The object a `.tool` file holds: its `---` block when fenced, the whole file
|
|
1199
|
+
* when not. Throws when that is not an object.
|
|
1200
|
+
*/
|
|
1201
|
+
function toolFileObject(content: string): Record<string, unknown> {
|
|
1202
|
+
const fm = extractFrontmatter(content);
|
|
1203
|
+
const source = fm ? fm.frontmatter : content;
|
|
1204
|
+
const parsed = parseYaml(source) as unknown;
|
|
1205
|
+
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
|
|
1206
|
+
throw new Error('`.tool` file must be a YAML/JSON object (in the `---` block when fenced)');
|
|
1207
|
+
}
|
|
1208
|
+
return parsed as Record<string, unknown>;
|
|
1209
|
+
}
|
|
1210
|
+
|
|
1211
|
+
/**
|
|
1212
|
+
* A `.tool`'s manual name — its UTCP namespace, and the slug the scan serves it
|
|
1213
|
+
* under. An explicit `id` is used VERBATIM, so it must be lowercase snake_case
|
|
1214
|
+
* (UTCP's namespace grammar). With no explicit id, fall back to `name` then the
|
|
1215
|
+
* filename and sanitize (legacy behaviour — keeps existing tools' namespaces).
|
|
1216
|
+
*/
|
|
1217
|
+
function toolManualName(obj: Record<string, unknown>, provisionalSlug: string): string {
|
|
1218
|
+
const explicitId = typeof obj.id === 'string' ? obj.id.trim() : '';
|
|
1219
|
+
if (!explicitId) return manualName(resolveDeclaredId(obj, provisionalSlug));
|
|
1220
|
+
if (!isValidId(explicitId)) {
|
|
1221
|
+
// The rejected id is NOT quoted back — see `describeManualFault`: this
|
|
1222
|
+
// message becomes an `invalid[].reason` on an agent transcript, a browser
|
|
1223
|
+
// and a log, and `id` is a field an author can paste anything into,
|
|
1224
|
+
// including the token they meant for a header. The field name plus the
|
|
1225
|
+
// rule is what the author needs; the value is in front of them.
|
|
1226
|
+
throw new Error('tool `id` must be lowercase snake_case (letters, digits, underscores)');
|
|
1227
|
+
}
|
|
1228
|
+
return explicitId;
|
|
1229
|
+
}
|
|
1230
|
+
|
|
1231
|
+
/**
|
|
1232
|
+
* The manual name of a `.tool` the parser REFUSED, when the file still says
|
|
1233
|
+
* which manual it is — by the same rule {@link normalizeToolManual} names a
|
|
1234
|
+
* manual it accepts. `null` when even that cannot be read (unparseable YAML,
|
|
1235
|
+
* a malformed `id`): then nothing can claim the refusal by name.
|
|
1236
|
+
*/
|
|
1237
|
+
function refusedToolManualName(provisionalSlug: string, content: string): string | null {
|
|
1238
|
+
try {
|
|
1239
|
+
return toolManualName(toolFileObject(content), provisionalSlug);
|
|
1240
|
+
} catch {
|
|
1241
|
+
return null;
|
|
1242
|
+
}
|
|
1243
|
+
}
|
|
1244
|
+
|
|
1112
1245
|
/**
|
|
1113
1246
|
* Parse + normalize a `.tool` file into a descriptor. THE TOOL IS THE
|
|
1114
1247
|
* FRONTMATTER: a fenced file's single `---` YAML block carries everything —
|
|
@@ -1132,34 +1265,9 @@ export function normalizeToolManual(
|
|
|
1132
1265
|
// finds its verbs inside the fence, the id index finds `id`/`name`, and the
|
|
1133
1266
|
// config keys live in the same object. A fence-less file is the legacy form
|
|
1134
1267
|
// (the whole file is the object) — JSON `.tool`s can't carry fences.
|
|
1135
|
-
const
|
|
1136
|
-
const source = fm ? fm.frontmatter : content;
|
|
1137
|
-
const parsed = parseYaml(source) as unknown;
|
|
1138
|
-
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
|
|
1139
|
-
throw new Error('`.tool` file must be a YAML/JSON object (in the `---` block when fenced)');
|
|
1140
|
-
}
|
|
1141
|
-
const obj = parsed as Record<string, unknown>;
|
|
1268
|
+
const obj = toolFileObject(content);
|
|
1142
1269
|
const type = normalizeType(obj.type);
|
|
1143
|
-
|
|
1144
|
-
// Identity: an explicit `id` is used VERBATIM as the UTCP manual namespace, so
|
|
1145
|
-
// it must be lowercase snake_case (UTCP's namespace grammar). With no explicit
|
|
1146
|
-
// id, fall back to `name` then the filename and sanitize (legacy behaviour —
|
|
1147
|
-
// keeps existing tools' namespaces).
|
|
1148
|
-
const explicitId = typeof obj.id === 'string' ? obj.id.trim() : '';
|
|
1149
|
-
let name: string;
|
|
1150
|
-
if (explicitId) {
|
|
1151
|
-
if (!isValidId(explicitId)) {
|
|
1152
|
-
// The rejected id is NOT quoted back — see `describeManualFault`: this
|
|
1153
|
-
// message becomes an `invalid[].reason` on an agent transcript, a browser
|
|
1154
|
-
// and a log, and `id` is a field an author can paste anything into,
|
|
1155
|
-
// including the token they meant for a header. The field name plus the
|
|
1156
|
-
// rule is what the author needs; the value is in front of them.
|
|
1157
|
-
throw new Error('tool `id` must be lowercase snake_case (letters, digits, underscores)');
|
|
1158
|
-
}
|
|
1159
|
-
name = explicitId;
|
|
1160
|
-
} else {
|
|
1161
|
-
name = manualName(resolveDeclaredId(obj, provisionalSlug));
|
|
1162
|
-
}
|
|
1270
|
+
const name = toolManualName(obj, provisionalSlug);
|
|
1163
1271
|
|
|
1164
1272
|
// A `.tool` may not reproduce a built-in manual's UTCP namespace — that would
|
|
1165
1273
|
// let it read the loopback creds seeded under that namespace on the agent's
|
|
@@ -5,20 +5,34 @@ import type { ToolContext, ToolHandlerFactory } from '../tool-helpers/index.js';
|
|
|
5
5
|
import { toolDef, declareRouteTool } from '../tool-helpers/index.js';
|
|
6
6
|
import type { IAccessControl } from '../access/index.js';
|
|
7
7
|
import { utcpNamespacedKey } from '../../shared/utcp-namespace.js';
|
|
8
|
-
import type { IToolManualService } from './tool-manuals.contract.js';
|
|
8
|
+
import type { ConnectorScope, IToolManualService } from './tool-manuals.contract.js';
|
|
9
9
|
import type { HiddenToolSource } from '../../shared/hidden-tools.js';
|
|
10
|
+
import { userSecretGap } from '../secrets-vault/index.js';
|
|
10
11
|
|
|
11
12
|
/**
|
|
12
13
|
* What `list_tool_setup` needs from the secrets vault (structurally satisfied
|
|
13
14
|
* by `ISecretsVaultService.statusFor`). A local port keeps this module free of
|
|
14
|
-
*
|
|
15
|
-
* `McpAuthDiscoveryPort` in the service.
|
|
15
|
+
* the vault service — the same decoupling discipline as
|
|
16
|
+
* `McpAuthDiscoveryPort` in the service. Only the vault's pure readiness rule
|
|
17
|
+
* (`userSecretGap`, its exported contract) is imported, the one the MCP proxy
|
|
18
|
+
* hides tools by.
|
|
16
19
|
*/
|
|
17
20
|
export interface VariableStatusPort {
|
|
18
21
|
statusFor(
|
|
19
22
|
userId: string,
|
|
20
23
|
keys: string[],
|
|
21
|
-
): Promise<
|
|
24
|
+
): Promise<
|
|
25
|
+
{
|
|
26
|
+
key: string;
|
|
27
|
+
adminConfigured: boolean;
|
|
28
|
+
/** What the owner's row is: a sign-in needs an `oauth` one, not a key left from when the variable was static. */
|
|
29
|
+
adminKind?: 'static' | 'oauth' | null;
|
|
30
|
+
userConfigured: boolean;
|
|
31
|
+
userAuthorized?: boolean;
|
|
32
|
+
userKind?: 'static' | 'oauth' | null;
|
|
33
|
+
grantedScopes?: string;
|
|
34
|
+
}[]
|
|
35
|
+
>;
|
|
22
36
|
}
|
|
23
37
|
|
|
24
38
|
/**
|
|
@@ -51,7 +65,9 @@ export function registerToolManualsTools(
|
|
|
51
65
|
hiddenTools?: HiddenToolSource;
|
|
52
66
|
},
|
|
53
67
|
): void {
|
|
54
|
-
registry.registerExternalTool((ctx) =>
|
|
68
|
+
registry.registerExternalTool((ctx) =>
|
|
69
|
+
buildListLocalToolsDef(toolManualService, ctx.userEmail, ctx.connectionScope?.connectorFilter()),
|
|
70
|
+
);
|
|
55
71
|
registry.registerInternalTool((ctx) => buildListLocalToolsDef(toolManualService, ctx.userEmail));
|
|
56
72
|
// The def above is built per catalog listing (its description names the
|
|
57
73
|
// tools configured for THIS caller), so declare the arguments here as well:
|
|
@@ -59,12 +75,22 @@ export function registerToolManualsTools(
|
|
|
59
75
|
// against them too.
|
|
60
76
|
declareRouteTool('list_local_tools', LIST_LOCAL_TOOLS_INPUTS);
|
|
61
77
|
|
|
78
|
+
// The local server's discovery read (`discovery`): it asks this route at
|
|
79
|
+
// startup for the connectors it must materialize, whatever tools the
|
|
80
|
+
// connection is offered — a connection made as an agent configuration that omits
|
|
81
|
+
// the tool is answered its connectors, not refused, or the local server
|
|
82
|
+
// could not start for that agent at all.
|
|
62
83
|
router.post(
|
|
63
84
|
'/agent/tools/list_local_tools',
|
|
64
85
|
toolAuth,
|
|
65
|
-
toolHandler(async (_args, ctx: ToolContext) =>
|
|
66
|
-
|
|
67
|
-
|
|
86
|
+
toolHandler(async (_args, ctx: ToolContext) => {
|
|
87
|
+
const within = ctx.connectionScope?.connectorFilter();
|
|
88
|
+
return {
|
|
89
|
+
tools: await (within
|
|
90
|
+
? toolManualService.listLocalOnly(ctx.user.email, within)
|
|
91
|
+
: toolManualService.listLocalOnly(ctx.user.email)),
|
|
92
|
+
};
|
|
93
|
+
}, { discovery: true }),
|
|
68
94
|
);
|
|
69
95
|
|
|
70
96
|
// A FUNCTION, not a constant — this factory runs at boot, and on a
|
|
@@ -228,7 +254,9 @@ export function registerToolManualsTools(
|
|
|
228
254
|
},
|
|
229
255
|
note: {
|
|
230
256
|
type: 'string',
|
|
231
|
-
description:
|
|
257
|
+
description:
|
|
258
|
+
'Present when something is left to do: what it takes for the tools in `onBranchOnly` to go live, and for ' +
|
|
259
|
+
'tools that need your own value or sign-in to work.',
|
|
232
260
|
},
|
|
233
261
|
},
|
|
234
262
|
required: ['tools', 'invalid', 'onBranchOnly'],
|
|
@@ -243,12 +271,17 @@ export function registerToolManualsTools(
|
|
|
243
271
|
toolHandler(async (args, ctx: ToolContext) => {
|
|
244
272
|
// The in-app agent is focused on its own draft; an external caller names it.
|
|
245
273
|
const branch = typeof args.branch === 'string' && args.branch ? args.branch : ctx.focusedBranch;
|
|
274
|
+
const within = ctx.connectionScope?.connectorFilter();
|
|
246
275
|
// The catalog comes back whole — what parsed AND what was refused — from
|
|
247
276
|
// ONE scan, so the refused files cost no second walk of the workspace and
|
|
248
277
|
// the two halves cannot disagree about which files made it.
|
|
249
278
|
const [{ tools: manuals, invalid }, pending] = await Promise.all([
|
|
250
|
-
|
|
251
|
-
|
|
279
|
+
// Only the connectors the caller's connection loads: setup is counted
|
|
280
|
+
// for the tools this connection can call, not every one the person can.
|
|
281
|
+
within
|
|
282
|
+
? toolManualService.listAccessibleCatalog(ctx.user.email, within)
|
|
283
|
+
: toolManualService.listAccessibleCatalog(ctx.user.email),
|
|
284
|
+
branch ? toolManualService.listDeclaredOnlyOnBranch(ctx.user.email, branch, within) : Promise.resolve([]),
|
|
252
285
|
]);
|
|
253
286
|
const allKeys = manuals.flatMap((m) => (m.variables ?? []).map((v) => varKey(m.name, v.name)));
|
|
254
287
|
const status = await deps.variableStatus.statusFor(ctx.user.id, allKeys);
|
|
@@ -285,25 +318,48 @@ export function registerToolManualsTools(
|
|
|
285
318
|
}),
|
|
286
319
|
);
|
|
287
320
|
const onBranchOnly = pending.map((p) => ({ ...p, branch: branch! }));
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
invalid,
|
|
292
|
-
onBranchOnly,
|
|
293
|
-
note:
|
|
321
|
+
const notes: string[] = [];
|
|
322
|
+
if (onBranchOnly.length > 0) {
|
|
323
|
+
notes.push(
|
|
294
324
|
`${onBranchOnly.map((p) => `\`${p.name}\``).join(', ')} ${onBranchOnly.length === 1 ? 'is' : 'are'} declared on ` +
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
325
|
+
`\`${branch}\` only. Tools are served from \`${deps.kb.defaultBranch}\`, so ${onBranchOnly.length === 1 ? 'it stays' : 'they stay'} ` +
|
|
326
|
+
'unlisted, uncallable and without a sign-in until that branch is merged: open a change request with ' +
|
|
327
|
+
`\`open_change_request\` (target \`${deps.kb.defaultBranch}\`), then ask the user to review and merge it in the app.`,
|
|
328
|
+
);
|
|
329
|
+
}
|
|
330
|
+
// The person's own part, said where the agent is when a tool "does not work": the
|
|
331
|
+
// reconnect step is the one agents leave out (the agent-guide benchmark, 2026-10-26).
|
|
332
|
+
// By the rule the proxy hides a tool by (`userSecretGap`), so the note
|
|
333
|
+
// names every tool that is hidden for want of the caller's own value. A
|
|
334
|
+
// sign-in waits on the owner's provider setup (an OAuth admin row, not a
|
|
335
|
+
// key left from when the variable was static — the Connect page counts
|
|
336
|
+
// that setup incomplete and the sign-in start refuses it): until then
|
|
337
|
+
// there is nothing to sign in to.
|
|
338
|
+
const needYou = manuals.filter((m) =>
|
|
339
|
+
(m.variables ?? []).some((v) => {
|
|
340
|
+
if (v.scope !== 'user') return false;
|
|
341
|
+
const st = statusByKey.get(varKey(m.name, v.name));
|
|
342
|
+
const gap = userSecretGap({ oauth: v.oauth != null, oauthScopes: v.oauth?.scopes }, st);
|
|
343
|
+
return gap !== null && (v.oauth == null || (st?.adminConfigured === true && st.adminKind === 'oauth'));
|
|
344
|
+
}),
|
|
345
|
+
);
|
|
346
|
+
if (needYou.length > 0) {
|
|
347
|
+
notes.push(
|
|
348
|
+
`${needYou.map((t) => `\`${t.name}\``).join(', ')} ${needYou.length === 1 ? 'needs' : 'need'} your own value or sign-in. ` +
|
|
349
|
+
'Set it yourself on the Connect page, never in the chat; then reconnect your assistant, or start a new chat, ' +
|
|
350
|
+
'so the tool is listed.',
|
|
351
|
+
);
|
|
352
|
+
}
|
|
353
|
+
if (notes.length === 0) return { tools, invalid, onBranchOnly };
|
|
354
|
+
return { tools, invalid, onBranchOnly, note: notes.join(' ') };
|
|
299
355
|
}),
|
|
300
356
|
);
|
|
301
357
|
}
|
|
302
358
|
|
|
303
359
|
/** "Local-only tools configured for you: `a`, `b`." (or a none note), filtered to what the caller may read. */
|
|
304
|
-
async function localToolsLine(svc: IToolManualService, userEmail?: string): Promise<string> {
|
|
360
|
+
async function localToolsLine(svc: IToolManualService, userEmail?: string, within?: ConnectorScope): Promise<string> {
|
|
305
361
|
if (!userEmail) return 'No local-only tools are currently configured.';
|
|
306
|
-
const tools = await svc.listLocalOnly(userEmail);
|
|
362
|
+
const tools = await (within ? svc.listLocalOnly(userEmail, within) : svc.listLocalOnly(userEmail));
|
|
307
363
|
if (tools.length === 0) return 'No local-only tools are currently configured.';
|
|
308
364
|
return `Local-only tools configured for you: ${tools.map((t) => `\`${t.name}\``).join(', ')}.`;
|
|
309
365
|
}
|
|
@@ -311,7 +367,7 @@ async function localToolsLine(svc: IToolManualService, userEmail?: string): Prom
|
|
|
311
367
|
/** `list_local_tools` takes nothing; a const so the route and the def share one declaration. */
|
|
312
368
|
const LIST_LOCAL_TOOLS_INPUTS = { type: 'object' as const, properties: {}, additionalProperties: false };
|
|
313
369
|
|
|
314
|
-
async function buildListLocalToolsDef(svc: IToolManualService, userEmail?: string): Promise<UtcpTool> {
|
|
370
|
+
async function buildListLocalToolsDef(svc: IToolManualService, userEmail?: string, within?: ConnectorScope): Promise<UtcpTool> {
|
|
315
371
|
return toolDef({
|
|
316
372
|
name: 'list_local_tools',
|
|
317
373
|
description:
|
|
@@ -324,7 +380,7 @@ async function buildListLocalToolsDef(svc: IToolManualService, userEmail?: strin
|
|
|
324
380
|
'machine. Otherwise each entry gives the tool’s name and its `.tool` file ' +
|
|
325
381
|
'path in the knowledge base — read that file with `read_file` and wire the tool into your local ' +
|
|
326
382
|
'setup by hand. ' +
|
|
327
|
-
(await localToolsLine(svc, userEmail)),
|
|
383
|
+
(await localToolsLine(svc, userEmail, within)),
|
|
328
384
|
path: '/api/agent/tools/list_local_tools',
|
|
329
385
|
inputs: LIST_LOCAL_TOOLS_INPUTS,
|
|
330
386
|
outputs: {
|