Files
dsh-context/tests/host/toolSources.spec.ts
T
3244ff29a9 feat: tool plugin source attribution in the Context browser (#25)
Tool-schema rows in the Context browser carry a best-effort source tag
for the registering plugin, recovered without a harness change:

- a harness-logged `plugin` field passes through verbatim (future-proof);
- MCP-proxied tools resolve `mcp:<server>` from their public names;
- shipped first-party tools resolve from a pinned package map;
- a live `tools.register()` hook (cordis `internal/get` reader slot,
  with a caller-package stack fallback for local-link installs) tags
  third-party, agent-scoped, and dynamic registrations, and peels a
  prior incarnation's wrapper on reload;
- tools already registered when the plugin mounts render a localized
  "unknown plugin" tag explaining the boot-order gap.

Priority: `mcp:<server>` > live record > pinned map > unknown. The
chip rides the shared tag frame tinted with the brand badge tokens.

Rebased onto v0.35.0 with maintainer review fixes; the attribution
priority and reload-safety rework and the chip theming are described
in the PR review comment.

Co-authored-by: Nwflower <1679659@qq.com>
Co-authored-by: bowenliang123 <liang.bowen.123@qq.com>
2026-08-28 09:50:10 +08:00

58 lines
2.6 KiB
TypeScript

// Unit tests for host/toolSources.ts — best-effort tool-to-plugin attribution:
// MCP server recovery from the `mcp__` name prefix, and the pinned first-party
// package map. (A harness-logged `plugin` field, when one appears, passes
// through headers.ts ahead of everything here.)
import assert from 'node:assert/strict'
import { describe, test } from 'vitest'
import {
FIRST_PARTY_SOURCES,
MCP_PREFIX,
mcpServerOf,
mcpSourceOf,
} from '../../src/host/toolSources'
describe('mcpServerOf', () => {
test('recovers the server from a plain mcp__server__tool name', () => {
assert.equal(mcpServerOf('mcp__github__get_issue'), 'github')
assert.equal(mcpServerOf('mcp__my_server__send_message'), 'my_server')
assert.equal(mcpServerOf('mcp__a__b__c'), 'a__b', 'server names may themselves contain __')
})
test('non-MCP names and malformed prefixes resolve to undefined', () => {
assert.equal(mcpServerOf('bash'), undefined)
assert.equal(mcpServerOf('mcp_server_tool'), undefined, 'no mcp__ prefix')
assert.equal(mcpServerOf('mcp__alone'), undefined, 'the prefix separator is not a server separator')
assert.equal(mcpServerOf('mcp____'), undefined, 'a second separator right at the prefix edge')
assert.equal(mcpServerOf('mcp____tool'), undefined, 'an empty server between separators')
})
test('hash-appended overlong names resolve the server that survived truncation', () => {
const hex64 = '0123456789abcdef'.repeat(4)
// Overlong names get '_<64-hex>' appended; the last __ separator survives
// unless the truncation cut into it.
assert.equal(mcpServerOf(`mcp__github__tool_${hex64}`), 'github')
assert.equal(mcpServerOf(`mcp__github__tool_${'z'.repeat(64)}`), 'github')
})
})
describe('mcpSourceOf', () => {
test('labels proxied tools with their server; other names stay unattributed', () => {
assert.equal(mcpSourceOf('mcp__github__get_issue'), 'mcp:github')
assert.equal(mcpSourceOf('mcp__alone'), undefined)
assert.equal(mcpSourceOf('bash'), undefined)
})
})
describe('FIRST_PARTY_SOURCES', () => {
test('the pinned map is frozen and carries the documented core names', () => {
assert.ok(Object.isFrozen(FIRST_PARTY_SOURCES))
for (const name of ['read', 'write', 'edit', 'bash', 'pwsh', 'glob', 'grep',
'web_search', 'web_fetch', 'job_kill', 'ask_user_question', 'plan', 'skill',
'todo_write', 'subagent', 'send_message', 'ralph', 'workflow', 'run_code']) {
assert.ok(name in FIRST_PARTY_SOURCES, `expected ${name} in the first-party map`)
}
assert.equal(MCP_PREFIX, 'mcp__')
})
})