File size: 3,358 Bytes
f0634fb | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 | import { describe, expect, it } from 'vitest';
import {
findInactiveToolPatterns,
isToolActive,
isToolActiveComposed,
literalToolNames,
} from '#/agent/toolPolicy/evaluate';
describe('findInactiveToolPatterns', () => {
const known = new Set(['Read', 'Bash', 'Skill']);
const isKnown = (name: string): boolean => known.has(name);
it('passes literal known tool names and MCP globs', () => {
expect(
findInactiveToolPatterns(['Read', 'Bash', 'mcp__github__*', 'mcp__*'], isKnown),
).toEqual([]);
});
it('flags a name that matches no known tool (typo, wrong case)', () => {
expect(findInactiveToolPatterns(['Bashh', 'read'], isKnown)).toEqual([
{ pattern: 'Bashh', kind: 'unknown-tool' },
{ pattern: 'read', kind: 'unknown-tool' },
]);
});
it('flags a bare * as never matching, and the evaluator agrees', () => {
expect(findInactiveToolPatterns(['*'])).toEqual([{ pattern: '*', kind: 'wildcard-not-mcp' }]);
expect(isToolActive({ tools: ['*'] }, 'Read')).toBe(false);
expect(isToolActive({ tools: ['*'] }, 'mcp__github__create_pr', 'mcp')).toBe(false);
expect(isToolActive({ disallowedTools: ['*'] }, 'Read')).toBe(true);
});
it('flags wildcards without the mcp__ prefix', () => {
expect(findInactiveToolPatterns(['Bash*'])).toEqual([
{ pattern: 'Bash*', kind: 'wildcard-not-mcp' },
]);
});
it('flags an mcp__ literal that is not a full server__tool name', () => {
expect(findInactiveToolPatterns(['mcp__github', 'mcp__'])).toEqual([
{ pattern: 'mcp__github', kind: 'incomplete-mcp-name' },
{ pattern: 'mcp__', kind: 'incomplete-mcp-name' },
]);
});
it('passes a full mcp__server__tool literal', () => {
expect(findInactiveToolPatterns(['mcp__github__create_issue'], isKnown)).toEqual([]);
});
it('skips the unknown-tool check when no vocabulary is provided', () => {
expect(findInactiveToolPatterns(['AnythingGoes'])).toEqual([]);
});
});
describe('literalToolNames', () => {
it('keeps only literal non-MCP names', () => {
expect(
literalToolNames(['Read', 'mcp__*', 'Bash*', 'mcp__github__create_issue']),
).toEqual(['Read']);
});
});
describe('isToolActiveComposed workspace veto', () => {
it('lets the workspace layer veto a tool every other layer allows', () => {
expect(
isToolActiveComposed(
{
workspaceDisabledTools: ['Bash'],
profile: { tools: ['Bash', 'Read'] },
global: { enabled: ['Bash', 'Read'] },
sessionDisabledTools: [],
},
'Bash',
),
).toBe(false);
expect(
isToolActiveComposed(
{
workspaceDisabledTools: ['Bash'],
profile: { tools: ['Bash', 'Read'] },
},
'Read',
),
).toBe(true);
});
it('applies the workspace veto to MCP tools by glob', () => {
expect(
isToolActiveComposed(
{ workspaceDisabledTools: ['mcp__blocked__*'], profile: {} },
'mcp__blocked__write',
'mcp',
),
).toBe(false);
});
it('stays inactive when any classic layer also denies', () => {
expect(
isToolActiveComposed(
{
workspaceDisabledTools: ['Bash'],
profile: {},
sessionDisabledTools: ['Bash'],
},
'Bash',
),
).toBe(false);
});
});
|