@bevel-software/platform-core-backend 0.25.0 → 0.26.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 +234 -0
- package/agent-guide/conventions.md +27 -0
- package/agent-guide/directory-structure.md +145 -0
- package/agent-guide/finding-things.md +7 -0
- package/agent-guide/introduction.md +27 -0
- package/agent-guide/skills.md +47 -0
- package/agent-guide/tool-manuals.md +217 -0
- package/agent-guide/where-a-new-file-goes.md +36 -0
- package/dist/assets.d.ts +7 -0
- package/dist/assets.d.ts.map +1 -1
- package/dist/assets.js +9 -0
- package/dist/assets.js.map +1 -1
- package/dist/core/core-ports.d.ts +11 -0
- package/dist/core/core-ports.d.ts.map +1 -1
- package/dist/core/core-ports.js.map +1 -1
- package/dist/core/create-core-server.d.ts.map +1 -1
- package/dist/core/create-core-server.js +13 -2
- package/dist/core/create-core-server.js.map +1 -1
- package/dist/core/create-core-services.d.ts +9 -0
- package/dist/core/create-core-services.d.ts.map +1 -1
- package/dist/core/create-core-services.js +14 -4
- package/dist/core/create-core-services.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 +9 -0
- package/dist/modules/access/access-control.interface.d.ts.map +1 -1
- package/dist/modules/access/access-control.service.d.ts +1 -0
- package/dist/modules/access/access-control.service.d.ts.map +1 -1
- package/dist/modules/access/access-control.service.js +16 -0
- package/dist/modules/access/access-control.service.js.map +1 -1
- package/dist/modules/agent-guide/agent-guide.d.ts +139 -0
- package/dist/modules/agent-guide/agent-guide.d.ts.map +1 -0
- package/dist/modules/agent-guide/agent-guide.js +191 -0
- package/dist/modules/agent-guide/agent-guide.js.map +1 -0
- package/dist/modules/agent-guide/agent-guide.tools.d.ts +24 -0
- package/dist/modules/agent-guide/agent-guide.tools.d.ts.map +1 -0
- package/dist/modules/agent-guide/agent-guide.tools.js +100 -0
- package/dist/modules/agent-guide/agent-guide.tools.js.map +1 -0
- package/dist/modules/agent-guide/index.d.ts +4 -0
- package/dist/modules/agent-guide/index.d.ts.map +1 -0
- package/dist/modules/agent-guide/index.js +4 -0
- package/dist/modules/agent-guide/index.js.map +1 -0
- package/dist/modules/agent-instructions/agent-instructions.routes.d.ts +3 -2
- package/dist/modules/agent-instructions/agent-instructions.routes.d.ts.map +1 -1
- package/dist/modules/agent-instructions/agent-instructions.routes.js +3 -2
- package/dist/modules/agent-instructions/agent-instructions.routes.js.map +1 -1
- package/dist/modules/agent-instructions/compose.d.ts +9 -6
- package/dist/modules/agent-instructions/compose.d.ts.map +1 -1
- package/dist/modules/agent-instructions/compose.js +9 -6
- package/dist/modules/agent-instructions/compose.js.map +1 -1
- package/dist/modules/agent-instructions/index.d.ts +1 -1
- package/dist/modules/agent-instructions/index.d.ts.map +1 -1
- package/dist/modules/agent-instructions/index.js +1 -1
- package/dist/modules/agent-instructions/index.js.map +1 -1
- package/dist/modules/agent-instructions/shared-file-rules.d.ts +10 -50
- package/dist/modules/agent-instructions/shared-file-rules.d.ts.map +1 -1
- package/dist/modules/agent-instructions/shared-file-rules.js +32 -85
- package/dist/modules/agent-instructions/shared-file-rules.js.map +1 -1
- package/dist/modules/mcp/mcp.service.d.ts +29 -2
- package/dist/modules/mcp/mcp.service.d.ts.map +1 -1
- package/dist/modules/mcp/mcp.service.js +113 -16
- package/dist/modules/mcp/mcp.service.js.map +1 -1
- package/dist/modules/mcp/tool-schema-guard.d.ts +105 -0
- package/dist/modules/mcp/tool-schema-guard.d.ts.map +1 -0
- package/dist/modules/mcp/tool-schema-guard.js +171 -0
- package/dist/modules/mcp/tool-schema-guard.js.map +1 -0
- package/dist/modules/plugins/plugins.tools.d.ts +36 -2
- package/dist/modules/plugins/plugins.tools.d.ts.map +1 -1
- package/dist/modules/plugins/plugins.tools.js +71 -14
- package/dist/modules/plugins/plugins.tools.js.map +1 -1
- package/dist/modules/settings/deployment-settings.service.d.ts +0 -7
- package/dist/modules/settings/deployment-settings.service.d.ts.map +1 -1
- package/dist/modules/settings/deployment-settings.service.js +14 -53
- package/dist/modules/settings/deployment-settings.service.js.map +1 -1
- package/dist/modules/settings/setup.routes.d.ts.map +1 -1
- package/dist/modules/settings/setup.routes.js +3 -6
- package/dist/modules/settings/setup.routes.js.map +1 -1
- package/dist/modules/skills/skills.tools.d.ts.map +1 -1
- package/dist/modules/skills/skills.tools.js +58 -16
- package/dist/modules/skills/skills.tools.js.map +1 -1
- package/dist/modules/tool-manuals/tool-manuals.contract.d.ts +23 -4
- package/dist/modules/tool-manuals/tool-manuals.contract.d.ts.map +1 -1
- package/dist/modules/tool-manuals/tool-manuals.contract.js.map +1 -1
- package/dist/modules/tool-manuals/tool-manuals.service.d.ts +4 -0
- package/dist/modules/tool-manuals/tool-manuals.service.d.ts.map +1 -1
- package/dist/modules/tool-manuals/tool-manuals.service.js +14 -0
- package/dist/modules/tool-manuals/tool-manuals.service.js.map +1 -1
- package/dist/modules/tool-manuals/tool-manuals.tools.d.ts +7 -0
- package/dist/modules/tool-manuals/tool-manuals.tools.d.ts.map +1 -1
- package/dist/modules/tool-manuals/tool-manuals.tools.js +66 -36
- package/dist/modules/tool-manuals/tool-manuals.tools.js.map +1 -1
- package/dist/modules/tool-registry/description-length.d.ts +14 -14
- package/dist/modules/tool-registry/description-length.d.ts.map +1 -1
- package/dist/modules/tool-registry/description-length.js +24 -26
- package/dist/modules/tool-registry/description-length.js.map +1 -1
- package/dist/modules/tool-registry/guide-first.d.ts +23 -0
- package/dist/modules/tool-registry/guide-first.d.ts.map +1 -0
- package/dist/modules/tool-registry/guide-first.js +32 -0
- package/dist/modules/tool-registry/guide-first.js.map +1 -0
- package/dist/modules/tool-registry/tool-registry.d.ts +6 -0
- package/dist/modules/tool-registry/tool-registry.d.ts.map +1 -1
- package/dist/modules/tool-registry/tool-registry.js +9 -2
- package/dist/modules/tool-registry/tool-registry.js.map +1 -1
- package/dist/modules/workflow/agent-tools/change-request-read-shape.d.ts +449 -0
- package/dist/modules/workflow/agent-tools/change-request-read-shape.d.ts.map +1 -0
- package/dist/modules/workflow/agent-tools/change-request-read-shape.js +481 -0
- package/dist/modules/workflow/agent-tools/change-request-read-shape.js.map +1 -0
- package/dist/modules/workflow/agent-tools/change-request-read.tools.d.ts +73 -0
- package/dist/modules/workflow/agent-tools/change-request-read.tools.d.ts.map +1 -0
- package/dist/modules/workflow/agent-tools/change-request-read.tools.js +582 -0
- package/dist/modules/workflow/agent-tools/change-request-read.tools.js.map +1 -0
- package/dist/modules/workflow/agent-tools/change-request-summary.d.ts +12 -1
- package/dist/modules/workflow/agent-tools/change-request-summary.d.ts.map +1 -1
- package/dist/modules/workflow/agent-tools/change-request-summary.js +5 -1
- package/dist/modules/workflow/agent-tools/change-request-summary.js.map +1 -1
- package/dist/modules/workflow/agent-tools/workflow.tools.d.ts.map +1 -1
- package/dist/modules/workflow/agent-tools/workflow.tools.js +9 -0
- package/dist/modules/workflow/agent-tools/workflow.tools.js.map +1 -1
- package/dist/modules/workflow/git/git.service.d.ts +210 -13
- package/dist/modules/workflow/git/git.service.d.ts.map +1 -1
- package/dist/modules/workflow/git/git.service.js +456 -91
- package/dist/modules/workflow/git/git.service.js.map +1 -1
- package/dist/modules/workflow/git/merge-commit.d.ts +73 -0
- package/dist/modules/workflow/git/merge-commit.d.ts.map +1 -0
- package/dist/modules/workflow/git/merge-commit.js +89 -0
- package/dist/modules/workflow/git/merge-commit.js.map +1 -0
- package/dist/modules/workflow/git/pull-request.service.d.ts +94 -1
- package/dist/modules/workflow/git/pull-request.service.d.ts.map +1 -1
- package/dist/modules/workflow/git/pull-request.service.js +332 -37
- package/dist/modules/workflow/git/pull-request.service.js.map +1 -1
- package/dist/modules/workflow/review-workflow/review-workflow.service.d.ts +35 -0
- package/dist/modules/workflow/review-workflow/review-workflow.service.d.ts.map +1 -1
- package/dist/modules/workflow/review-workflow/review-workflow.service.js +178 -12
- package/dist/modules/workflow/review-workflow/review-workflow.service.js.map +1 -1
- package/dist/modules/workflow/workflow.routes.d.ts +6 -2
- package/dist/modules/workflow/workflow.routes.d.ts.map +1 -1
- package/dist/modules/workflow/workflow.routes.js +7 -2
- package/dist/modules/workflow/workflow.routes.js.map +1 -1
- package/dist/modules/workflow/workflow.service.d.ts +4 -0
- 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/startup/kb-startup-runner.d.ts +70 -0
- package/dist/modules/workspace/startup/kb-startup-runner.d.ts.map +1 -1
- package/dist/modules/workspace/startup/kb-startup-runner.js +213 -20
- package/dist/modules/workspace/startup/kb-startup-runner.js.map +1 -1
- package/dist/modules/workspace/startup/steps/seed-tree.d.ts.map +1 -1
- package/dist/modules/workspace/startup/steps/seed-tree.js +22 -27
- package/dist/modules/workspace/startup/steps/seed-tree.js.map +1 -1
- package/dist/modules/workspace/startup/steps/template-files.step.d.ts +58 -52
- package/dist/modules/workspace/startup/steps/template-files.step.d.ts.map +1 -1
- package/dist/modules/workspace/startup/steps/template-files.step.js +209 -223
- package/dist/modules/workspace/startup/steps/template-files.step.js.map +1 -1
- package/dist/modules/workspace/startup/steps/template-source.d.ts +5 -3
- package/dist/modules/workspace/startup/steps/template-source.d.ts.map +1 -1
- package/dist/modules/workspace/startup/steps/template-source.js +5 -3
- package/dist/modules/workspace/startup/steps/template-source.js.map +1 -1
- package/dist/modules/workspace/workspace.tools.d.ts +10 -1
- package/dist/modules/workspace/workspace.tools.d.ts.map +1 -1
- package/dist/modules/workspace/workspace.tools.js +211 -18
- package/dist/modules/workspace/workspace.tools.js.map +1 -1
- package/dist/shared/domain-errors.d.ts +11 -0
- package/dist/shared/domain-errors.d.ts.map +1 -1
- package/dist/shared/domain-errors.js +14 -0
- package/dist/shared/domain-errors.js.map +1 -1
- package/dist/shared/hidden-tools.d.ts +44 -0
- package/dist/shared/hidden-tools.d.ts.map +1 -0
- package/dist/shared/hidden-tools.js +13 -0
- package/dist/shared/hidden-tools.js.map +1 -0
- package/kb-template/.bevelignore +0 -5
- package/package.json +4 -3
- package/src/__tests__/kb-layout-config.test.ts +10 -100
- package/src/__tests__/packaged-assets-ship.test.ts +54 -0
- package/src/assets.ts +10 -0
- package/src/core/core-ports.ts +11 -0
- package/src/core/create-core-server.ts +13 -2
- package/src/core/create-core-services.ts +28 -4
- package/src/index.ts +2 -2
- package/src/modules/access/__tests__/access-control.atref-batch.test.ts +58 -0
- package/src/modules/access/__tests__/access-control.platform-restore.test.ts +8 -7
- package/src/modules/access/__tests__/access-personal-plugin.test.ts +1 -18
- package/src/modules/access/access-control.interface.ts +15 -0
- package/src/modules/access/access-control.service.ts +21 -0
- package/src/modules/agent-guide/__tests__/agent-guide.test.ts +328 -0
- package/src/modules/agent-guide/__tests__/agent-guide.tools.test.ts +189 -0
- package/src/modules/agent-guide/agent-guide.tools.ts +122 -0
- package/src/modules/agent-guide/agent-guide.ts +291 -0
- package/src/modules/agent-guide/index.ts +21 -0
- package/src/modules/agent-instructions/__tests__/shared-file-rules.test.ts +28 -121
- package/src/modules/agent-instructions/agent-instructions.routes.ts +3 -2
- package/src/modules/agent-instructions/compose.ts +9 -6
- package/src/modules/agent-instructions/index.ts +0 -3
- package/src/modules/agent-instructions/shared-file-rules.ts +31 -93
- package/src/modules/mcp/__tests__/fake-downstream-mcp-server.ts +14 -3
- package/src/modules/mcp/__tests__/mcp.e2e.test.ts +250 -0
- package/src/modules/mcp/__tests__/mcp.service.test.ts +31 -23
- package/src/modules/mcp/__tests__/tool-schema-guard.test.ts +266 -0
- package/src/modules/mcp/mcp.service.ts +137 -19
- package/src/modules/mcp/tool-schema-guard.ts +196 -0
- package/src/modules/plugins/__tests__/plugins.tools.test.ts +154 -4
- package/src/modules/plugins/plugins.tools.ts +75 -15
- package/src/modules/settings/__tests__/deployment-settings.service.test.ts +26 -55
- package/src/modules/settings/deployment-settings.service.ts +13 -54
- package/src/modules/settings/setup.routes.ts +3 -6
- package/src/modules/skills/__tests__/skills.tools.description.test.ts +91 -0
- package/src/modules/skills/skills.tools.ts +62 -16
- package/src/modules/tool-manuals/__tests__/tool-manuals.detail.route.test.ts +57 -0
- package/src/modules/tool-manuals/__tests__/tool-manuals.tools.test.ts +73 -4
- package/src/modules/tool-manuals/tool-manuals.contract.ts +24 -4
- package/src/modules/tool-manuals/tool-manuals.service.ts +17 -0
- package/src/modules/tool-manuals/tool-manuals.tools.ts +74 -36
- package/src/modules/tool-registry/__tests__/own-tool-schemas.test.ts +160 -0
- package/src/modules/tool-registry/__tests__/tool-description-length.test.ts +61 -59
- package/src/modules/tool-registry/description-length.ts +24 -26
- package/src/modules/tool-registry/guide-first.ts +34 -0
- package/src/modules/tool-registry/tool-registry.ts +9 -2
- package/src/modules/workflow/__tests__/apply-failure.test.ts +6 -1
- package/src/modules/workflow/agent-tools/__tests__/change-request-read-shape.test.ts +705 -0
- package/src/modules/workflow/agent-tools/__tests__/change-request-read.tools.test.ts +1518 -0
- package/src/modules/workflow/agent-tools/__tests__/workflow.tools.test.ts +23 -2
- package/src/modules/workflow/agent-tools/change-request-read-shape.ts +712 -0
- package/src/modules/workflow/agent-tools/change-request-read.tools.ts +724 -0
- package/src/modules/workflow/agent-tools/change-request-summary.ts +5 -1
- package/src/modules/workflow/agent-tools/workflow.tools.ts +8 -0
- package/src/modules/workflow/git/__tests__/git.service.appliedChange.test.ts +285 -0
- package/src/modules/workflow/git/__tests__/git.service.changedFilesForPr.test.ts +124 -0
- package/src/modules/workflow/git/__tests__/git.service.mergeChangeRequest.test.ts +334 -0
- package/src/modules/workflow/git/__tests__/pull-request.service.list-fetch.test.ts +72 -2
- package/src/modules/workflow/git/__tests__/pull-request.service.placeholder.test.ts +24 -2
- package/src/modules/workflow/git/__tests__/pull-request.service.test.ts +620 -1
- package/src/modules/workflow/git/git.service.ts +537 -94
- package/src/modules/workflow/git/merge-commit.ts +88 -0
- package/src/modules/workflow/git/pull-request.service.ts +380 -54
- package/src/modules/workflow/review-workflow/__tests__/approval-states.test.ts +7 -1
- package/src/modules/workflow/review-workflow/__tests__/merge-records-own-commit.test.ts +407 -0
- package/src/modules/workflow/review-workflow/review-workflow.service.ts +189 -11
- package/src/modules/workflow/workflow.routes.ts +7 -2
- package/src/modules/workflow/workflow.service.ts +7 -0
- package/src/modules/workspace/__tests__/escape-sequences.routes.test.ts +4 -3
- package/src/modules/workspace/__tests__/workspace.routes.move-platform-files.test.ts +21 -10
- package/src/modules/workspace/__tests__/workspace.tools.agents-file.test.ts +33 -55
- package/src/modules/workspace/__tests__/workspace.tools.test.ts +255 -22
- package/src/modules/workspace/startup/__tests__/kb-startup-runner.test.ts +231 -1
- package/src/modules/workspace/startup/kb-startup-runner.ts +216 -19
- package/src/modules/workspace/startup/steps/__tests__/steps.test.ts +191 -489
- package/src/modules/workspace/startup/steps/seed-tree.ts +21 -27
- package/src/modules/workspace/startup/steps/template-files.step.ts +217 -249
- package/src/modules/workspace/startup/steps/template-source.ts +5 -3
- package/src/modules/workspace/workspace.tools.ts +226 -16
- package/src/shared/domain-errors.ts +15 -0
- package/src/shared/hidden-tools.ts +45 -0
- package/kb-template/AGENTS.md +0 -730
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shared-file-rules.d.ts","sourceRoot":"","sources":["../../../src/modules/agent-instructions/shared-file-rules.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"shared-file-rules.d.ts","sourceRoot":"","sources":["../../../src/modules/agent-instructions/shared-file-rules.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,OAAO,EAGL,KAAK,QAAQ,EACd,MAAM,iCAAiC,CAAC;AAGzC,oFAAoF;AACpF,eAAO,MAAM,oBAAoB,uBAAuB,CAAC;AAUzD;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,qBAAqB,OAAQ,CAAC;AAE3C,oEAAoE;AACpE,MAAM,WAAW,cAAc;IAC7B,gEAAgE;IAChE,EAAE,EAAE,MAAM,CAAC;IACX,iDAAiD;IACjD,OAAO,EAAE,MAAM,CAAC;IAChB,oFAAoF;IACpF,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,QAAQ,GAAG,SAAS,cAAc,EAAE,CAoH3E;AAsCD;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,QAAQ,GAAG,MAAM,CAK/D"}
|
|
@@ -14,29 +14,31 @@
|
|
|
14
14
|
*
|
|
15
15
|
* - the MCP `instructions` of the initialize handshake (see `compose.ts`),
|
|
16
16
|
* which Claude Code, Claude Desktop and Cursor put in the system prompt;
|
|
17
|
-
* - the platform
|
|
18
|
-
*
|
|
19
|
-
* on the web, the Agent SDK and Cline drop `instructions`, and a
|
|
20
|
-
* agent is told to read before its first action is always
|
|
17
|
+
* - the platform's agent guide, which `get_agent_guide` returns and a
|
|
18
|
+
* `read_file` of the guide's name serves (see `modules/agent-guide`) —
|
|
19
|
+
* claude.ai on the web, the Agent SDK and Cline drop `instructions`, and a
|
|
20
|
+
* guide the agent is told to read before its first action is always
|
|
21
|
+
* available.
|
|
21
22
|
*
|
|
22
23
|
* Both places get the SAME string, from {@link sharedFileRulesSection} — not
|
|
23
24
|
* two hand-mirrored copies. A rule written twice is a rule that drifts, and a
|
|
24
25
|
* drifted rule is worse than a repeated one, because the agent cannot tell
|
|
25
|
-
* which copy is current. Each description
|
|
26
|
-
*
|
|
26
|
+
* which copy is current. Each description opens instead with the one
|
|
27
|
+
* sentence sending the agent to the guide (`tool-registry/guide-first.ts`).
|
|
27
28
|
*
|
|
28
|
-
* Pure text, a function of the layout only: the guide's
|
|
29
|
-
* deployment
|
|
29
|
+
* Pure text, a function of the layout only: the guide's name is a deployment
|
|
30
|
+
* setting (an alias a deployment chose before the guide left the disk), so
|
|
31
|
+
* nothing here may snapshot `AGENTS.md`.
|
|
30
32
|
*/
|
|
31
|
-
import {
|
|
33
|
+
import { LEGACY_AGENTS_FILE, platformFilesByDepth, } from '@bevel-software/platform-shared';
|
|
32
34
|
import { CHAIN_FAILURES_RULE, CHAIN_LARGE_RESULTS_RULE } from '@bevel-software/platform-mcp-core';
|
|
33
35
|
/** The heading the rules live under, in both places and in the pointer sentence. */
|
|
34
36
|
export const SHARED_RULES_SECTION = 'Working with files';
|
|
35
37
|
/**
|
|
36
38
|
* The guide's name on a knowledge base seeded before it was renamed to
|
|
37
|
-
* {@link LEGACY_AGENTS_FILE}
|
|
38
|
-
*
|
|
39
|
-
*
|
|
39
|
+
* {@link LEGACY_AGENTS_FILE}, back when the guide was a file. The platform's
|
|
40
|
+
* own copy is taken out at startup now (see template-files.step.ts); one that
|
|
41
|
+
* stays is a file the organisation edited, so it is theirs and still named.
|
|
40
42
|
*/
|
|
41
43
|
const PRE_RENAME_AGENTS_FILE = 'CLAUDE.md';
|
|
42
44
|
/**
|
|
@@ -63,12 +65,11 @@ export const SHARED_FILE_RULES_CAP = 7_000;
|
|
|
63
65
|
* ones that said "this tool" or "this call" name the tools instead.
|
|
64
66
|
*/
|
|
65
67
|
export function sharedFileRules(layout) {
|
|
66
|
-
const agentsFile = agentsFileOf(layout);
|
|
67
68
|
return [
|
|
68
69
|
{
|
|
69
70
|
id: 'agent-guide',
|
|
70
71
|
heading: "This knowledge base's own conventions",
|
|
71
|
-
body: conventionsRule(
|
|
72
|
+
body: conventionsRule(),
|
|
72
73
|
},
|
|
73
74
|
{
|
|
74
75
|
id: 'content-kinds',
|
|
@@ -174,15 +175,14 @@ export function sharedFileRules(layout) {
|
|
|
174
175
|
}
|
|
175
176
|
/**
|
|
176
177
|
* The platform files as the rules list them — from the one function that knows
|
|
177
|
-
* which they are, so the list cannot drift from what actually refuses a move
|
|
178
|
-
* and the guide appears under this deployment's name for it.
|
|
178
|
+
* which they are, so the list cannot drift from what actually refuses a move.
|
|
179
179
|
*
|
|
180
180
|
* WITH THE DEPTH each name counts at, because the name alone is half the rule:
|
|
181
181
|
* `access.md` governs the folder it sits in and `.bevelignore` layers, so both
|
|
182
|
-
* are platform files wherever they are; `roles.yaml`
|
|
183
|
-
*
|
|
184
|
-
*
|
|
185
|
-
*
|
|
182
|
+
* are platform files wherever they are; `roles.yaml` is read from the
|
|
183
|
+
* repository root only, so a nested copy is ordinary content that moves and
|
|
184
|
+
* deletes like any page. An agent told only the names refuses a rename it may
|
|
185
|
+
* make, and trusts a nested `access.md` it may not.
|
|
186
186
|
*/
|
|
187
187
|
function platformFileList(layout) {
|
|
188
188
|
const { anyDepth, rootOnly } = platformFilesByDepth(layout);
|
|
@@ -190,27 +190,20 @@ function platformFileList(layout) {
|
|
|
190
190
|
return `${quoted(anyDepth)} in any folder, ${quoted(rootOnly)} at the repository root`;
|
|
191
191
|
}
|
|
192
192
|
/**
|
|
193
|
-
* The conventions reminder —
|
|
194
|
-
*
|
|
193
|
+
* The conventions reminder — where the platform's guide is, that the
|
|
194
|
+
* organisation's own conventions file comes with it, and to read both first.
|
|
195
195
|
*
|
|
196
|
-
*
|
|
197
|
-
*
|
|
198
|
-
*
|
|
199
|
-
*
|
|
200
|
-
*
|
|
201
|
-
* checkout. Under the default name the wording collapses to the one file it
|
|
202
|
-
* has always named.
|
|
196
|
+
* The guide is read by name at the repository root, where coding agents look
|
|
197
|
+
* for an `AGENTS.md` by convention, and `get_agent_guide` returns it alone.
|
|
198
|
+
* One name on every deployment, so the rule takes no layout. `CLAUDE.md` is
|
|
199
|
+
* named as a fallback because a knowledge base seeded before the rename may
|
|
200
|
+
* still carry one its people edited.
|
|
203
201
|
*/
|
|
204
|
-
function conventionsRule(
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
}
|
|
210
|
-
return (`Before your first read or change in a workspace, read \`${agentsFile}\` at the KB root, then ` +
|
|
211
|
-
`\`${LEGACY_AGENTS_FILE}\` if it also exists (the organisation's own conventions) — or ` +
|
|
212
|
-
`\`${PRE_RENAME_AGENTS_FILE}\` on a knowledge base seeded before it was renamed: together they hold the ` +
|
|
213
|
-
'conventions for this knowledge base, and you should follow them.');
|
|
202
|
+
function conventionsRule() {
|
|
203
|
+
return ("Before your first read or change in a workspace, call `get_agent_guide` and read the platform's guide " +
|
|
204
|
+
`(whole, or one section). read_file on \`${LEGACY_AGENTS_FILE}\` at the KB root answers with the same ` +
|
|
205
|
+
"guide, after the organisation's own conventions file of that name when it has one: follow both. A " +
|
|
206
|
+
`\`${PRE_RENAME_AGENTS_FILE}\` at the KB root is the organisation's own too; read it if it exists.`);
|
|
214
207
|
}
|
|
215
208
|
/**
|
|
216
209
|
* The shared rules as ONE markdown section — the string both channels carry,
|
|
@@ -223,50 +216,4 @@ export function sharedFileRulesSection(layout) {
|
|
|
223
216
|
.join('\n\n');
|
|
224
217
|
return `## ${SHARED_RULES_SECTION}\n\n${body}`;
|
|
225
218
|
}
|
|
226
|
-
/**
|
|
227
|
-
* The longest guide file name the pointer sentence spells out. Beyond this it
|
|
228
|
-
* names the guide by its ROLE instead (see {@link sharedRulesPointer}).
|
|
229
|
-
*
|
|
230
|
-
* There has to be a bound somewhere, because the pointer rides on every file
|
|
231
|
-
* tool and a file name is not a fixed cost: `validateFilename` allows a name
|
|
232
|
-
* of up to 255 bytes, so an unbounded pointer could reach 318 characters and
|
|
233
|
-
* push `file_stat` to 1,428 — over the description cap, recreating on a
|
|
234
|
-
* renamed deployment exactly the truncation this module exists to prevent, and
|
|
235
|
-
* invisibly, because every measurement is taken under the default layout.
|
|
236
|
-
*
|
|
237
|
-
* 40 is well past any name a deployment plausibly picks
|
|
238
|
-
* (`ENGINEERING-AGENT-CONVENTIONS.md` is 32) and the fallback below is only
|
|
239
|
-
* reachable past it.
|
|
240
|
-
*/
|
|
241
|
-
export const POINTER_GUIDE_NAME_BUDGET = 40;
|
|
242
|
-
/**
|
|
243
|
-
* The one sentence a tool description ends with, in place of the paragraphs it
|
|
244
|
-
* used to carry. Short on purpose: it costs every description the same ~100
|
|
245
|
-
* characters at worst, and its whole job is to name the section and the file
|
|
246
|
-
* to read.
|
|
247
|
-
*
|
|
248
|
-
* BOUNDED BY CONSTRUCTION, which is what lets the description cap mean
|
|
249
|
-
* something on a deployment that renamed its guide: a name within
|
|
250
|
-
* {@link POINTER_GUIDE_NAME_BUDGET} is spelled out, and a longer one gets the
|
|
251
|
-
* generic wording. Naming the file is the better sentence and wins whenever it
|
|
252
|
-
* fits; a name past the budget is pathological, and there the choice is between
|
|
253
|
-
* a sentence that says where to look and a catalog entry the client cuts. The
|
|
254
|
-
* guide's own name is still in the section's first rule either way.
|
|
255
|
-
*
|
|
256
|
-
* An absent layout means the default one, as it does in
|
|
257
|
-
* `composeAgentInstructions`: a caller reading the layout from configuration
|
|
258
|
-
* gets `undefined` when none is set, and the pointer must still name a file.
|
|
259
|
-
*/
|
|
260
|
-
export function sharedRulesPointer(layout = DEFAULT_KB_LAYOUT) {
|
|
261
|
-
const agentsFile = agentsFileOf(layout);
|
|
262
|
-
const where = agentsFile.length <= POINTER_GUIDE_NAME_BUDGET ? agentsFile : 'the agent guide at the KB root';
|
|
263
|
-
return ` Shared rules for all file tools: see "${SHARED_RULES_SECTION}" in ${where}.`;
|
|
264
|
-
}
|
|
265
|
-
/**
|
|
266
|
-
* The most the pointer can ever cost a description, over every layout. What the
|
|
267
|
-
* description cap is measured against, the way the tool prefix is measured at
|
|
268
|
-
* ITS cap rather than at whatever the current admin wrote: a description that
|
|
269
|
-
* only fits beside the short default guide name does not really fit.
|
|
270
|
-
*/
|
|
271
|
-
export const SHARED_RULES_POINTER_MAX = Math.max(sharedRulesPointer({ ...DEFAULT_KB_LAYOUT, agentsFile: `${'x'.repeat(POINTER_GUIDE_NAME_BUDGET - 3)}.md` }).length, sharedRulesPointer({ ...DEFAULT_KB_LAYOUT, agentsFile: `${'x'.repeat(POINTER_GUIDE_NAME_BUDGET + 10)}.md` }).length);
|
|
272
219
|
//# sourceMappingURL=shared-file-rules.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shared-file-rules.js","sourceRoot":"","sources":["../../../src/modules/agent-instructions/shared-file-rules.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"shared-file-rules.js","sourceRoot":"","sources":["../../../src/modules/agent-instructions/shared-file-rules.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,6 +5,7 @@ import type { KbLayout } from '@bevel-software/platform-shared';
|
|
|
5
5
|
import { type ISecretsVaultService } from '../secrets-vault/secrets-vault.contract.js';
|
|
6
6
|
import type { IToolManualService } from '../tool-manuals/tool-manuals.contract.js';
|
|
7
7
|
import type { SpillStore } from '../workspace/spill-store.js';
|
|
8
|
+
import type { HiddenToolSource } from '../../shared/hidden-tools.js';
|
|
8
9
|
import type { InternalTokenService } from '../tool-auth/internal-token.service.js';
|
|
9
10
|
import type { IAgentEventRecorder } from '../audit/audit.contract.js';
|
|
10
11
|
import { type DownstreamPoolOptions } from './downstream-pool.js';
|
|
@@ -33,8 +34,8 @@ export interface McpProxyOptions {
|
|
|
33
34
|
readAgentPreamble?: AgentPreambleReader;
|
|
34
35
|
/**
|
|
35
36
|
* The layout in effect, read per request: the shared file rules name the
|
|
36
|
-
*
|
|
37
|
-
*
|
|
37
|
+
* guide by the name a deployment saved for it, and the setup save applies
|
|
38
|
+
* a layout without a restart. A GETTER, so nothing snapshots the
|
|
38
39
|
* pre-setup default. Absent, the rules name `AGENTS.md`.
|
|
39
40
|
*/
|
|
40
41
|
kbLayout?: () => KbLayout;
|
|
@@ -136,6 +137,14 @@ export declare class McpService {
|
|
|
136
137
|
* server's tools.
|
|
137
138
|
*/
|
|
138
139
|
private readonly knownDownstreamTools;
|
|
140
|
+
/**
|
|
141
|
+
* The JSON Schema check on connected tools, and the memory of what it found.
|
|
142
|
+
* Process-wide rather than per request, because a schema's validity is a
|
|
143
|
+
* property of the server and not of the caller — and because the point of
|
|
144
|
+
* remembering is that the check runs when a server's tools are loaded, not
|
|
145
|
+
* once per request and never on a tool call. See {@link ToolSchemaGuard}.
|
|
146
|
+
*/
|
|
147
|
+
private readonly toolSchemas;
|
|
139
148
|
private readonly downstream;
|
|
140
149
|
constructor(opts: McpProxyOptions, secretsVault?: ISecretsVaultService | undefined, toolManuals?: IToolManualService | undefined, internalTokens?: InternalTokenService | undefined, revokeOAuthAccess?: ((bearer: string) => Promise<void>) | undefined, auditRecorder?: IAgentEventRecorder | undefined);
|
|
141
150
|
/**
|
|
@@ -248,6 +257,24 @@ export declare class McpService {
|
|
|
248
257
|
* corrected `mcp.json` URL) is tried on the very next request.
|
|
249
258
|
*/
|
|
250
259
|
private discoverTools;
|
|
260
|
+
/**
|
|
261
|
+
* Check the input schema of every tool the servers just advertised, and take
|
|
262
|
+
* the invalid ones OFF the client's tool repository.
|
|
263
|
+
*
|
|
264
|
+
* The repository is the single place `tools/list`, `list_tools`/`tools_info`
|
|
265
|
+
* and the TypeScript interfaces `call_tool_chain` generates are all built
|
|
266
|
+
* from, so removing a tool here removes it from all three — which is what
|
|
267
|
+
* "not offered to agents" has to mean. Its siblings are untouched: the check
|
|
268
|
+
* is per tool, so one bad schema costs that tool and nothing else of the
|
|
269
|
+
* server.
|
|
270
|
+
*
|
|
271
|
+
* A client would otherwise drop such a tool itself, silently, and the agent
|
|
272
|
+
* would be left without it and without a reason. Hidden here, the reason
|
|
273
|
+
* reaches the people who manage the server (see {@link ToolSchemaGuard}).
|
|
274
|
+
*/
|
|
275
|
+
private hideInvalidSchemas;
|
|
276
|
+
/** The schema findings the owner-facing surfaces report — see {@link ToolSchemaGuard}. */
|
|
277
|
+
get hiddenTools(): HiddenToolSource;
|
|
251
278
|
/**
|
|
252
279
|
* Make one `mcp` manual's tools part of this request's client, backed by the
|
|
253
280
|
* pooled connection for (user, manual).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp.service.d.ts","sourceRoot":"","sources":["../../../src/modules/mcp/mcp.service.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAcnE,OAAO,YAAY,CAAC;AACpB,OAAO,WAAW,CAAC;AA0BnB,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iCAAiC,CAAC;AAEhE,OAAO,EAGL,KAAK,oBAAoB,EAC1B,MAAM,4CAA4C,CAAC;AAEpD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0CAA0C,CAAC;AACnF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;
|
|
1
|
+
{"version":3,"file":"mcp.service.d.ts","sourceRoot":"","sources":["../../../src/modules/mcp/mcp.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -16,9 +16,11 @@ import { RequestAudit } from '../audit/request-audit.js';
|
|
|
16
16
|
import { ManualFailureMemo } from './manual-failure-memo.js';
|
|
17
17
|
import { DownstreamPool, POOL_KEY_SEPARATOR } from './downstream-pool.js';
|
|
18
18
|
import { SurfaceLogThrottle } from './surface-log-throttle.js';
|
|
19
|
+
import { ToolSchemaGuard } from './tool-schema-guard.js';
|
|
19
20
|
import { DownstreamRefreshGuard, isDownstreamTokenRejection } from './downstream-token-refresh.js';
|
|
20
21
|
import { printable } from '../../shared/printable.js';
|
|
21
|
-
import { composeAgentInstructions, prefixToolDescription, PREFIXED_TOOLS,
|
|
22
|
+
import { composeAgentInstructions, prefixToolDescription, PREFIXED_TOOLS, } from '../agent-instructions/index.js';
|
|
23
|
+
import { guideFirstDescription } from '../tool-registry/guide-first.js';
|
|
22
24
|
/**
|
|
23
25
|
* Upper bound on one `loopbackJson` round-trip (manual list, skill fetch) so a
|
|
24
26
|
* hung loopback can't stall a request. Generous: these endpoints answer in
|
|
@@ -105,6 +107,14 @@ export class McpService {
|
|
|
105
107
|
* server's tools.
|
|
106
108
|
*/
|
|
107
109
|
knownDownstreamTools = new Map();
|
|
110
|
+
/**
|
|
111
|
+
* The JSON Schema check on connected tools, and the memory of what it found.
|
|
112
|
+
* Process-wide rather than per request, because a schema's validity is a
|
|
113
|
+
* property of the server and not of the caller — and because the point of
|
|
114
|
+
* remembering is that the check runs when a server's tools are loaded, not
|
|
115
|
+
* once per request and never on a tool call. See {@link ToolSchemaGuard}.
|
|
116
|
+
*/
|
|
117
|
+
toolSchemas = new ToolSchemaGuard();
|
|
108
118
|
// The downstream connection pool for `mcp` manuals — see the class doc.
|
|
109
119
|
downstream;
|
|
110
120
|
constructor(opts,
|
|
@@ -295,14 +305,17 @@ export class McpService {
|
|
|
295
305
|
// different name, and one fixed example is necessarily wrong on one of the
|
|
296
306
|
// two surfaces.
|
|
297
307
|
//
|
|
298
|
-
//
|
|
299
|
-
//
|
|
300
|
-
//
|
|
301
|
-
// `
|
|
302
|
-
//
|
|
308
|
+
// What a chain does with a failure, a large result or an image is
|
|
309
|
+
// stated once, in the shared rules — in the guide and in the handshake
|
|
310
|
+
// instructions — and not on the chain itself (an EMPTY pointer is how
|
|
311
|
+
// `mcp-core` is told the rules are served elsewhere). Like every tool of
|
|
312
|
+
// the platform's own, each meta-tool opens with the one sentence saying
|
|
313
|
+
// what to do before any of them, which is where those rules are. The
|
|
314
|
+
// registry puts the sentence on the tools it lists; the meta-tools are
|
|
315
|
+
// built here, so here it is.
|
|
303
316
|
const metaTools = codeModeMetaTools(EXTERNAL_KB_MANUAL_NAME, examplePool, {
|
|
304
|
-
sharedRulesPointer:
|
|
305
|
-
});
|
|
317
|
+
sharedRulesPointer: '',
|
|
318
|
+
}).map((tool) => ({ ...tool, description: guideFirstDescription(tool.description) }));
|
|
306
319
|
// Log only when a tool was dropped (name/schema/duplicate) — that's the
|
|
307
320
|
// anomaly worth surfacing, since a downstream client would otherwise hide
|
|
308
321
|
// it by rejecting the whole response.
|
|
@@ -316,7 +329,7 @@ export class McpService {
|
|
|
316
329
|
};
|
|
317
330
|
});
|
|
318
331
|
server.setRequestHandler(CallToolRequestSchema, async (request, extra) => {
|
|
319
|
-
const { client, tools, unavailable, catalogNames } = await requestSurface();
|
|
332
|
+
const { client, tools, unavailable, catalogNames, hidden: hiddenTools } = await requestSurface();
|
|
320
333
|
const toolName = request.params.name;
|
|
321
334
|
const args = request.params.arguments ?? {};
|
|
322
335
|
if (META_TOOL_NAMES.has(toolName)) {
|
|
@@ -359,6 +372,23 @@ export class McpService {
|
|
|
359
372
|
};
|
|
360
373
|
const proxied = tools.find((t) => t.mcpName === toolName);
|
|
361
374
|
if (!proxied) {
|
|
375
|
+
// A tool this process hid for an invalid schema: say that, rather than
|
|
376
|
+
// "Unknown tool" about a tool the agent has every reason to think
|
|
377
|
+
// exists. The place and the reason are deliberately NOT here — they are
|
|
378
|
+
// for the people who manage the server, who are the only ones who can
|
|
379
|
+
// act on them.
|
|
380
|
+
const hidden = hiddenTools.get(toolName);
|
|
381
|
+
if (hidden) {
|
|
382
|
+
// The UTCP name, as every other audit path records a tool: the
|
|
383
|
+
// flattened agent name loses the server segment of a multi-segment
|
|
384
|
+
// `<manual>.<server>.<tool>`, and an audit trail that names a
|
|
385
|
+
// different tool than the rest of the trail is worse than none.
|
|
386
|
+
if (audit)
|
|
387
|
+
await audit.denied(hidden.utcpName, args);
|
|
388
|
+
return toolError(`The "${toolName}" tool is hidden from agents because its schema is invalid, so it cannot be ` +
|
|
389
|
+
`called. The people who manage its server can see the place in the schema and the reason, on ` +
|
|
390
|
+
`the tool's page in Hexis and through \`list_tool_setup\`.`);
|
|
391
|
+
}
|
|
362
392
|
// Not on the surface — but if the name belongs to a manual that is off
|
|
363
393
|
// it only because this caller's sign-in is gone (and nothing in this
|
|
364
394
|
// process has seen its tools yet), the honest answer is the sign-in
|
|
@@ -427,7 +457,7 @@ export class McpService {
|
|
|
427
457
|
const manuals = await this.fetchManualTemplates(loopbackBearer);
|
|
428
458
|
const catalogMs = performance.now() - started;
|
|
429
459
|
const client = await this.buildClient(loopbackBearer, userId, manuals);
|
|
430
|
-
const { tools, unavailable, catalogNames } = await this.discoverTools(client, manuals, userId);
|
|
460
|
+
const { tools, unavailable, catalogNames, hidden } = await this.discoverTools(client, manuals, userId);
|
|
431
461
|
const totalMs = performance.now() - started;
|
|
432
462
|
// Per user: on a shape change or once per interval, never per request —
|
|
433
463
|
// see SurfaceLogThrottle for why both halves matter.
|
|
@@ -441,7 +471,7 @@ export class McpService {
|
|
|
441
471
|
`(catalog ${catalogMs.toFixed(0)}ms, registration ${(totalMs - catalogMs).toFixed(0)}ms)` +
|
|
442
472
|
(decision.suppressed > 0 ? ` [+${decision.suppressed} identical rebuild(s) since last line]` : ''));
|
|
443
473
|
}
|
|
444
|
-
return { client, tools, unavailable, catalogNames };
|
|
474
|
+
return { client, tools, unavailable, catalogNames, hidden };
|
|
445
475
|
}
|
|
446
476
|
/**
|
|
447
477
|
* The instructions and tool prefix. A reader failure (a disk fault; ENOENT
|
|
@@ -591,11 +621,31 @@ export class McpService {
|
|
|
591
621
|
async discoverTools(client, manuals, userId) {
|
|
592
622
|
const routes = new Map();
|
|
593
623
|
const unavailable = [];
|
|
624
|
+
// Taken BEFORE a single manual is registered, so it ranks this load by the
|
|
625
|
+
// freshness of what it is about to read — see ToolSchemaGuard.beginLoad.
|
|
626
|
+
const loadId = this.toolSchemas.beginLoad();
|
|
594
627
|
const catalogNames = new Map();
|
|
595
628
|
for (const m of manuals) {
|
|
596
629
|
if (m.call_template_type === 'mcp')
|
|
597
630
|
catalogNames.set(utcpManualName(m), String(m.name));
|
|
598
631
|
}
|
|
632
|
+
// Every manual's catalog name, which is how the owner-facing surfaces know
|
|
633
|
+
// it. `catalogNames` above is the credential catalog's map and covers `mcp`
|
|
634
|
+
// manuals only; the schema check is about the tools of every connected
|
|
635
|
+
// server, so it needs the whole list. Taken HERE, before registration:
|
|
636
|
+
// registering a manual renames the template in place, so `m.name` read
|
|
637
|
+
// afterwards is the rewritten identifier and `my-server` would be recorded
|
|
638
|
+
// as `my_server` — a name no tool page ever looks up.
|
|
639
|
+
// Keyed by the rewritten name, which two manuals can share (the collision
|
|
640
|
+
// handled below): the KB manual's entry is the one that stays, since it is
|
|
641
|
+
// the one that is registered when a `.tool` collides with it.
|
|
642
|
+
const manualCatalogNames = new Map();
|
|
643
|
+
for (const m of manuals) {
|
|
644
|
+
const rewritten = utcpManualName(m);
|
|
645
|
+
if (manualCatalogNames.get(rewritten) === EXTERNAL_KB_MANUAL_NAME)
|
|
646
|
+
continue;
|
|
647
|
+
manualCatalogNames.set(rewritten, String(m.name));
|
|
648
|
+
}
|
|
599
649
|
// The shared layer rewrites every manual name (`[^\w]` → `_`) and tools
|
|
600
650
|
// route by the rewritten prefix, so two manuals whose names rewrite to one
|
|
601
651
|
// identifier would silently share it. Sequential registration used to
|
|
@@ -677,11 +727,58 @@ export class McpService {
|
|
|
677
727
|
if (routes.size > 0)
|
|
678
728
|
routeToDownstream(client, routes);
|
|
679
729
|
const utcpTools = await client.getTools();
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
730
|
+
const flattened = utcpTools.map((tool) => flattenManualTool(tool, EXTERNAL_KB_MANUAL_NAME));
|
|
731
|
+
const { tools, hidden } = await this.hideInvalidSchemas(client, flattened, manualCatalogNames, userId, loadId);
|
|
732
|
+
return { tools, unavailable, catalogNames, hidden };
|
|
733
|
+
}
|
|
734
|
+
/**
|
|
735
|
+
* Check the input schema of every tool the servers just advertised, and take
|
|
736
|
+
* the invalid ones OFF the client's tool repository.
|
|
737
|
+
*
|
|
738
|
+
* The repository is the single place `tools/list`, `list_tools`/`tools_info`
|
|
739
|
+
* and the TypeScript interfaces `call_tool_chain` generates are all built
|
|
740
|
+
* from, so removing a tool here removes it from all three — which is what
|
|
741
|
+
* "not offered to agents" has to mean. Its siblings are untouched: the check
|
|
742
|
+
* is per tool, so one bad schema costs that tool and nothing else of the
|
|
743
|
+
* server.
|
|
744
|
+
*
|
|
745
|
+
* A client would otherwise drop such a tool itself, silently, and the agent
|
|
746
|
+
* would be left without it and without a reason. Hidden here, the reason
|
|
747
|
+
* reaches the people who manage the server (see {@link ToolSchemaGuard}).
|
|
748
|
+
*/
|
|
749
|
+
async hideInvalidSchemas(client, tools, catalogNames, userId, loadId) {
|
|
750
|
+
const byManual = new Map();
|
|
751
|
+
// EVERY manual of this surface is screened, including the ones that
|
|
752
|
+
// advertised nothing. A server that removed its last invalid tool, and one
|
|
753
|
+
// whose tools never loaded at all (a sign-in that has gone), both come
|
|
754
|
+
// through here with an empty group — and an empty group is what clears the
|
|
755
|
+
// marker. Screening only the groups that have tools would leave the tool
|
|
756
|
+
// page, `list_tool_setup` and the hidden-tool answer on a call all
|
|
757
|
+
// reporting a defect this process can no longer see.
|
|
758
|
+
for (const manual of catalogNames.values())
|
|
759
|
+
byManual.set(manual, []);
|
|
760
|
+
for (const tool of tools) {
|
|
761
|
+
const manual = catalogNames.get(tool.manualName) ?? tool.manualName;
|
|
762
|
+
byManual.set(manual, [...(byManual.get(manual) ?? []), tool]);
|
|
763
|
+
}
|
|
764
|
+
const found = this.toolSchemas.screen(userId, loadId, byManual);
|
|
765
|
+
const hidden = new Map();
|
|
766
|
+
for (const tool of found.values())
|
|
767
|
+
hidden.set(tool.name, tool);
|
|
768
|
+
if (found.size === 0)
|
|
769
|
+
return { tools, hidden };
|
|
770
|
+
for (const utcpName of found.keys()) {
|
|
771
|
+
await client.config.tool_repository.removeTool(utcpName);
|
|
772
|
+
}
|
|
773
|
+
// Logged every time rather than throttled: a hidden tool is the one thing
|
|
774
|
+
// about this surface that a person has to act on, and it is rare.
|
|
775
|
+
log.warn(`hiding ${found.size} connected tool(s) whose input schema is not valid JSON Schema: ` +
|
|
776
|
+
`${[...found.values()].map((t) => `${t.name} (${t.path}: ${t.reason})`).join(', ')}`);
|
|
777
|
+
return { tools: tools.filter((tool) => !found.has(tool.utcpName)), hidden };
|
|
778
|
+
}
|
|
779
|
+
/** The schema findings the owner-facing surfaces report — see {@link ToolSchemaGuard}. */
|
|
780
|
+
get hiddenTools() {
|
|
781
|
+
return this.toolSchemas;
|
|
685
782
|
}
|
|
686
783
|
/**
|
|
687
784
|
* Make one `mcp` manual's tools part of this request's client, backed by the
|