feat(ai): extensible agent tool registry
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
17
lib/ai/agent/registry.js
Normal file
17
lib/ai/agent/registry.js
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
export function createRegistry() {
|
||||||
|
const tools = new Map();
|
||||||
|
return {
|
||||||
|
registerTool(def) {
|
||||||
|
if (!def?.name) throw new Error('tool def needs a name');
|
||||||
|
if (tools.has(def.name)) throw new Error(`tool "${def.name}" already registered`);
|
||||||
|
tools.set(def.name, def);
|
||||||
|
},
|
||||||
|
getTool(name) { return tools.get(name); },
|
||||||
|
listTools() { return [...tools.values()]; },
|
||||||
|
// Anthropic tool-use schema — handlers are intentionally stripped.
|
||||||
|
toAnthropicTools() {
|
||||||
|
return [...tools.values()].map(({ name, description, input_schema }) =>
|
||||||
|
({ name, description, input_schema }));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
32
tests/ai/agent/registry.test.js
Normal file
32
tests/ai/agent/registry.test.js
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
import { describe, it, expect } from 'vitest';
|
||||||
|
import { createRegistry } from '../../../lib/ai/agent/registry.js';
|
||||||
|
|
||||||
|
describe('tool registry', () => {
|
||||||
|
const def = {
|
||||||
|
name: 'echo',
|
||||||
|
description: 'echo back',
|
||||||
|
input_schema: { type: 'object', properties: { x: { type: 'string' } }, required: ['x'] },
|
||||||
|
handler: async ({ x }) => ({ ok: true, x })
|
||||||
|
};
|
||||||
|
|
||||||
|
it('registers and retrieves a tool', () => {
|
||||||
|
const r = createRegistry();
|
||||||
|
r.registerTool(def);
|
||||||
|
expect(r.getTool('echo')).toBe(def);
|
||||||
|
expect(r.listTools().map(t => t.name)).toEqual(['echo']);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('rejects duplicate names', () => {
|
||||||
|
const r = createRegistry();
|
||||||
|
r.registerTool(def);
|
||||||
|
expect(() => r.registerTool(def)).toThrow(/already registered/);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('serialises to the Anthropic tools shape (no handler leak)', () => {
|
||||||
|
const r = createRegistry();
|
||||||
|
r.registerTool(def);
|
||||||
|
expect(r.toAnthropicTools()).toEqual([
|
||||||
|
{ name: 'echo', description: 'echo back', input_schema: def.input_schema }
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user