-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathnativeToolCapabilities.ts
More file actions
56 lines (51 loc) · 2.9 KB
/
Copy pathnativeToolCapabilities.ts
File metadata and controls
56 lines (51 loc) · 2.9 KB
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
import type { ToolDefinition } from "../toolhub/toolsSchema.js";
import type { VerifiedToolsConfigSnapshot } from "../toolhub/toolhubValidators.js";
/** Supported implementation identity, supplied by composition rather than policy alone. */
export interface NativeToolCapability {
readonly name: string;
readonly actionClass: ToolDefinition["actionClass"];
readonly context?: ToolDefinition["context"];
}
export const NATIVE_BUILTIN_CAPABILITIES: readonly NativeToolCapability[] = Object.freeze([
{ name: "fs.read", actionClass: "READ_ONLY" },
{ name: "fs.write", actionClass: "WRITE_LOW" },
{ name: "fs.edit", actionClass: "WRITE_LOW" },
{ name: "glob", actionClass: "READ_ONLY" },
{ name: "grep", actionClass: "READ_ONLY" },
{ name: "bash", actionClass: "WRITE_HIGH" }
].map(capability => Object.freeze(capability as NativeToolCapability)));
/** These become executable only when a caller also supplies the delegation capability. */
export const NATIVE_DELEGATION_CAPABILITIES: readonly NativeToolCapability[] = Object.freeze([
Object.freeze({ name: "delegate", actionClass: "READ_ONLY" as const }),
Object.freeze({ name: "workflow", actionClass: "READ_ONLY" as const })
]);
export function nativeToolMatchesCapability(tool: ToolDefinition, capability: NativeToolCapability): boolean {
if (tool.name !== capability.name || tool.actionClass !== capability.actionClass) return false;
const actual = tool.context;
const expected = capability.context;
if (expected?.kind !== "mcp") return actual === undefined || actual.kind === "native";
return actual?.kind === "mcp" && actual.server.id === expected.server.id
&& actual.server.name === expected.server.name && actual.server.version === expected.server.version
&& actual.server.transport === expected.server.transport;
}
/**
* Readiness and scope presentation share ONE authenticated snapshot. A policy
* name alone cannot claim an implementation exists. Additional capabilities
* must come from an explicitly reviewed composition (for example pinned MCP).
*/
export function selectSupportedNativeTools(snapshot: VerifiedToolsConfigSnapshot,
additionalCapabilities: readonly NativeToolCapability[] = []): readonly ToolDefinition[] {
if (!snapshot.signatureValid || !snapshot.config) return [];
const tools = snapshot.config.tools.allowedTools;
const names = tools.map(tool => tool.name.trim().toLowerCase());
if (new Set(names).size !== names.length) return [];
const supported = new Map(NATIVE_BUILTIN_CAPABILITIES.map(capability => [capability.name, capability]));
for (const capability of additionalCapabilities) {
// A caller cannot redefine the identity of a built-in implementation.
if (!supported.has(capability.name)) supported.set(capability.name, capability);
}
return tools.filter(tool => {
const capability = supported.get(tool.name);
return capability !== undefined && nativeToolMatchesCapability(tool, capability);
});
}