SaylorTwift's picture
SaylorTwift HF Staff
Add files using upload-large-folder tool
68d7816 verified
Raw History Blame Contribute Delete
3.25 kB
import picomatch from 'picomatch';
import { isMcpToolName, type ToolSource } from '#/tool/toolContract';
export interface ToolActivationPolicy {
readonly tools?: readonly string[];
readonly disallowedTools?: readonly string[];
}
export function isToolActive(
policy: ToolActivationPolicy,
name: string,
source: ToolSource = 'builtin',
): boolean {
if (policy.tools !== undefined) {
const allowed =
source !== 'mcp'
? policy.tools.includes(name)
: policy.tools
.filter((pattern) => isMcpToolName(pattern))
.some((pattern) => picomatch.isMatch(name, pattern));
if (!allowed) return false;
}
if (policy.disallowedTools === undefined) return true;
if (source !== 'mcp') return !policy.disallowedTools.includes(name);
return !policy.disallowedTools
.filter((pattern) => isMcpToolName(pattern))
.some((pattern) => picomatch.isMatch(name, pattern));
}
export interface GlobalToolsPolicy {
readonly enabled?: readonly string[];
readonly disabled?: readonly string[];
}
export interface ToolPolicyLayers {
readonly workspaceDisabledTools?: readonly string[];
readonly profile: ToolActivationPolicy;
readonly global?: GlobalToolsPolicy;
readonly sessionDisabledTools?: readonly string[];
}
export function isToolActiveComposed(
layers: ToolPolicyLayers,
name: string,
source: ToolSource = 'builtin',
): boolean {
return (
isToolActive({ disallowedTools: layers.workspaceDisabledTools }, name, source) &&
isToolActive(layers.profile, name, source) &&
isToolActive(
{
tools: layers.global?.enabled?.length ? layers.global.enabled : undefined,
disallowedTools: layers.global?.disabled,
},
name,
source,
) &&
isToolActive({ disallowedTools: layers.sessionDisabledTools }, name, source)
);
}
export function resolveActiveToolNames(
policy: ToolActivationPolicy,
): readonly string[] | undefined {
if (policy.tools === undefined) return undefined;
return policy.tools.filter((name) =>
isToolActive(policy, name, isMcpToolName(name) ? 'mcp' : 'builtin'),
);
}
export type InactiveToolPatternKind = 'wildcard-not-mcp' | 'incomplete-mcp-name' | 'unknown-tool';
export interface InactiveToolPattern {
readonly pattern: string;
readonly kind: InactiveToolPatternKind;
}
const GLOB_MAGIC = /[*?[\]{}]/;
export function literalToolNames(patterns: readonly string[]): string[] {
return patterns.filter((pattern) => !isMcpToolName(pattern) && !GLOB_MAGIC.test(pattern));
}
export function findInactiveToolPatterns(
patterns: readonly string[],
isKnownToolName?: (name: string) => boolean,
): InactiveToolPattern[] {
const issues: InactiveToolPattern[] = [];
for (const pattern of patterns) {
if (isMcpToolName(pattern)) {
if (!GLOB_MAGIC.test(pattern) && !pattern.slice('mcp__'.length).includes('__')) {
issues.push({ pattern, kind: 'incomplete-mcp-name' });
}
continue;
}
if (GLOB_MAGIC.test(pattern)) {
issues.push({ pattern, kind: 'wildcard-not-mcp' });
continue;
}
if (isKnownToolName !== undefined && !isKnownToolName(pattern)) {
issues.push({ pattern, kind: 'unknown-tool' });
}
}
return issues;
}