Multi-agent audit + aggressive cleanup across server/web/coder/booterm, delivered behind a DEFER discipline so none of the in-flight files were touched. Removes dead code/deps/columns, dedups server + coder helpers, and splits the oversized modules (tools.ts, opencode-server.ts, sentinel-summaries, turn.ts, TerminalPane.tsx) behind stable contracts. Adds 78 parity/unit tests (server 587, coder 323); fixes two latent bugs (ChatPane queue keys, FileViewerOverlay blank-line parity). Intended tag: v2.7.12-audit-cleanup. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
69 lines
2.6 KiB
TypeScript
69 lines
2.6 KiB
TypeScript
import { describe, it, expect } from 'vitest';
|
|
import { z } from 'zod';
|
|
import {
|
|
ALL_TOOLS,
|
|
TOOLS_BY_NAME,
|
|
appendMcpTools,
|
|
toolJsonSchemas,
|
|
type ToolDef,
|
|
} from '../tools.js';
|
|
|
|
// Parity test for the register-through MCP-discovery contract (Phase 6 split).
|
|
// `ALL_TOOLS` / `TOOLS_BY_NAME` are `let`-bound in tools/registry.ts and
|
|
// reassigned by appendMcpTools() at startup; this barrel re-exports them.
|
|
// apps/coder relies on this exact behavior: it imports `appendMcpTools` + the
|
|
// live `ALL_TOOLS` binding from @boocode/server/tools, calls appendMcpTools()
|
|
// once, then reads ALL_TOOLS. ESM live bindings must carry the mutation
|
|
// through the barrel re-export — if the split ever snapshots the array instead
|
|
// of re-exporting the live binding, these assertions fail. Each test file gets
|
|
// an isolated module instance (vitest default), so mutating the registry here
|
|
// does not leak into tools.test.ts.
|
|
function makeFakeMcpTool(name: string): ToolDef<unknown> {
|
|
return {
|
|
name,
|
|
description: `fake mcp tool ${name}`,
|
|
inputSchema: z.object({}) as z.ZodType<unknown>,
|
|
jsonSchema: {
|
|
type: 'function',
|
|
function: {
|
|
name,
|
|
description: `fake mcp tool ${name}`,
|
|
parameters: { type: 'object', properties: {}, additionalProperties: false },
|
|
},
|
|
},
|
|
async execute() {
|
|
return { ok: true };
|
|
},
|
|
};
|
|
}
|
|
|
|
describe('appendMcpTools register-through contract', () => {
|
|
it('is a no-op for an empty array', () => {
|
|
const before = ALL_TOOLS.length;
|
|
appendMcpTools([]);
|
|
expect(ALL_TOOLS.length).toBe(before);
|
|
});
|
|
|
|
it('mutates the live ALL_TOOLS / TOOLS_BY_NAME bindings observable through the barrel', () => {
|
|
const before = ALL_TOOLS.length;
|
|
// Names chosen so insertion lands away from the array ends, proving the
|
|
// re-sort runs (a naive concat would leave them at the tail).
|
|
const a = makeFakeMcpTool('mcp__alpha__probe');
|
|
const z2 = makeFakeMcpTool('mcp__zeta__probe');
|
|
appendMcpTools([z2, a]);
|
|
|
|
expect(ALL_TOOLS.length).toBe(before + 2);
|
|
expect(TOOLS_BY_NAME['mcp__alpha__probe']).toBe(a);
|
|
expect(TOOLS_BY_NAME['mcp__zeta__probe']).toBe(z2);
|
|
|
|
// Still alpha-sorted after the append (prompt-cache stability invariant).
|
|
const names = ALL_TOOLS.map((t) => t.name);
|
|
expect(names).toEqual([...names].sort((x, y) => x.localeCompare(y)));
|
|
|
|
// toolJsonSchemas() reads through the same live binding.
|
|
const schemaNames = toolJsonSchemas().map((s) => s.function.name);
|
|
expect(schemaNames).toContain('mcp__alpha__probe');
|
|
expect(schemaNames).toContain('mcp__zeta__probe');
|
|
});
|
|
});
|