Skip to content

Commit 7c4f378

Browse files
committed
fix(js/ai): fixed dynamic tools becoming non-dynamic once registered
test case in question ```ts it('should remain dynamic after registration', () => { const dynamic = tool({ name: 'dynamic', description: 'test' }); assert.strictEqual(isDynamicTool(dynamic), true); registry.registerAction('tool', dynamic); assert.strictEqual(isDynamicTool(dynamic), true); }); ```
1 parent f639667 commit 7c4f378

File tree

2 files changed

+54
-3
lines changed

2 files changed

+54
-3
lines changed

js/ai/src/tool.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,7 @@ export function isToolResponse(part: Part): part is ToolResponsePart {
384384
}
385385

386386
export function isDynamicTool(t: unknown): t is ToolAction {
387-
return isAction(t) && !t.__registry;
387+
return isAction(t) && t.__action?.metadata?.dynamic === true;
388388
}
389389

390390
export function interrupt<I extends z.ZodTypeAny, O extends z.ZodTypeAny>(

js/ai/tests/tool_test.ts

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,17 @@
1414
* limitations under the License.
1515
*/
1616

17-
import { z } from '@genkit-ai/core';
17+
import { action, z } from '@genkit-ai/core';
1818
import { initNodeFeatures } from '@genkit-ai/core/node';
1919
import { Registry } from '@genkit-ai/core/registry';
2020
import * as assert from 'assert';
2121
import { afterEach, describe, it } from 'node:test';
22-
import { defineInterrupt, defineTool } from '../src/tool.js';
22+
import {
23+
defineInterrupt,
24+
defineTool,
25+
isDynamicTool,
26+
tool,
27+
} from '../src/tool.js';
2328

2429
initNodeFeatures();
2530

@@ -109,6 +114,52 @@ describe('defineInterrupt', () => {
109114
});
110115
});
111116

117+
describe('isDynamicTool', () => {
118+
let registry = new Registry();
119+
registry.apiStability = 'beta';
120+
afterEach(() => {
121+
registry = new Registry();
122+
registry.apiStability = 'beta';
123+
});
124+
125+
it('should return true for a dynamic tool', () => {
126+
const dynamic = tool({ name: 'dynamic', description: 'test' });
127+
assert.strictEqual(isDynamicTool(dynamic), true);
128+
});
129+
130+
it('should remain dynamic after registration', () => {
131+
const dynamic = tool({ name: 'dynamic', description: 'test' });
132+
assert.strictEqual(isDynamicTool(dynamic), true);
133+
134+
registry.registerAction('tool', dynamic);
135+
136+
assert.strictEqual(isDynamicTool(dynamic), true);
137+
});
138+
139+
it('should return false for a registered tool', () => {
140+
const regular = defineTool(
141+
registry,
142+
{ name: 'regular', description: 'test' },
143+
async () => {}
144+
);
145+
assert.strictEqual(isDynamicTool(regular), false);
146+
});
147+
148+
it('should return false for a non-tool action', () => {
149+
const regularAction = action(
150+
{ actionType: 'util', name: 'regularAction', description: 'test' },
151+
async () => {}
152+
);
153+
assert.strictEqual(isDynamicTool(regularAction), false);
154+
});
155+
156+
it('should return false for a non-action', () => {
157+
assert.strictEqual(isDynamicTool({}), false);
158+
assert.strictEqual(isDynamicTool('tool'), false);
159+
assert.strictEqual(isDynamicTool(123), false);
160+
});
161+
});
162+
112163
describe('defineTool', () => {
113164
let registry = new Registry();
114165
registry.apiStability = 'beta';

0 commit comments

Comments
 (0)