feat: add agent tools and sanitize tool names for Anthropic API
Add 8 new agent-callable tools (sessions.list/history/create/delete,
agents.list, message.send, cron.list/trigger) and sanitize tool names
at the API boundary (dots → underscores) to comply with Anthropic's
`^[a-zA-Z0-9_-]{1,128}` requirement. Reverse-maps sanitized names
back to internal names for hook callbacks and tool execution.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
+14
-4
@@ -20,6 +20,11 @@ export class ToolRegistry {
|
||||
private tools: Map<string, Tool> = new Map();
|
||||
private _policy?: ToolPolicy;
|
||||
|
||||
/** Sanitize a tool name for API compatibility (dots → underscores). */
|
||||
static sanitizeToolName(name: string): string {
|
||||
return name.replace(/\./g, '_');
|
||||
}
|
||||
|
||||
register(tool: Tool): void {
|
||||
if (this.tools.has(tool.name)) {
|
||||
throw new Error(`Tool '${tool.name}' is already registered`);
|
||||
@@ -55,6 +60,11 @@ export class ToolRegistry {
|
||||
return this.tools.get(name);
|
||||
}
|
||||
|
||||
/** Resolve a tool by its API-sanitized name (underscores → dots fallback). */
|
||||
getByApiName(name: string): Tool | undefined {
|
||||
return this.tools.get(name) ?? this.tools.get(name.replace(/_/g, '.'));
|
||||
}
|
||||
|
||||
list(): Tool[] {
|
||||
return Array.from(this.tools.values());
|
||||
}
|
||||
@@ -77,7 +87,7 @@ export class ToolRegistry {
|
||||
|
||||
toAnthropicFormat(): AnthropicToolDef[] {
|
||||
return this.list().map(t => ({
|
||||
name: t.name,
|
||||
name: ToolRegistry.sanitizeToolName(t.name),
|
||||
description: t.description,
|
||||
input_schema: t.inputSchema,
|
||||
}));
|
||||
@@ -86,7 +96,7 @@ export class ToolRegistry {
|
||||
/** Return Anthropic-format tools filtered by policy. */
|
||||
filteredToAnthropicFormat(context?: ToolPolicyContext): AnthropicToolDef[] {
|
||||
return this.filteredList(context).map(t => ({
|
||||
name: t.name,
|
||||
name: ToolRegistry.sanitizeToolName(t.name),
|
||||
description: t.description,
|
||||
input_schema: t.inputSchema,
|
||||
}));
|
||||
@@ -96,7 +106,7 @@ export class ToolRegistry {
|
||||
return this.list().map(t => ({
|
||||
type: 'function' as const,
|
||||
function: {
|
||||
name: t.name,
|
||||
name: ToolRegistry.sanitizeToolName(t.name),
|
||||
description: t.description,
|
||||
parameters: t.inputSchema,
|
||||
},
|
||||
@@ -108,7 +118,7 @@ export class ToolRegistry {
|
||||
return this.filteredList(context).map(t => ({
|
||||
type: 'function' as const,
|
||||
function: {
|
||||
name: t.name,
|
||||
name: ToolRegistry.sanitizeToolName(t.name),
|
||||
description: t.description,
|
||||
parameters: t.inputSchema,
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user