summaryrefslogtreecommitdiff
path: root/packages/core/src/tools/tool-registry.test.ts
diff options
context:
space:
mode:
authorWanlin Du <[email protected]>2025-08-11 16:12:41 -0700
committerGitHub <[email protected]>2025-08-11 23:12:41 +0000
commitd9fb08c9da3d2e8c501ec9badb2e2bd79eb15b93 (patch)
tree7d07e1586b736c1b6c44e28828aa29205af335ac /packages/core/src/tools/tool-registry.test.ts
parentf52d073dfbfa4d5091a74bf33ac1c66e51265247 (diff)
feat: migrate tools to use parametersJsonSchema. (#5330)
Diffstat (limited to 'packages/core/src/tools/tool-registry.test.ts')
-rw-r--r--packages/core/src/tools/tool-registry.test.ts222
1 files changed, 16 insertions, 206 deletions
diff --git a/packages/core/src/tools/tool-registry.test.ts b/packages/core/src/tools/tool-registry.test.ts
index d8e536b7..13dff08c 100644
--- a/packages/core/src/tools/tool-registry.test.ts
+++ b/packages/core/src/tools/tool-registry.test.ts
@@ -15,19 +15,9 @@ import {
Mocked,
} from 'vitest';
import { Config, ConfigParameters, ApprovalMode } from '../config/config.js';
-import {
- ToolRegistry,
- DiscoveredTool,
- sanitizeParameters,
-} from './tool-registry.js';
+import { ToolRegistry, DiscoveredTool } from './tool-registry.js';
import { DiscoveredMCPTool } from './mcp-tool.js';
-import {
- FunctionDeclaration,
- CallableTool,
- mcpToTool,
- Type,
- Schema,
-} from '@google/genai';
+import { FunctionDeclaration, CallableTool, mcpToTool } from '@google/genai';
import { spawn } from 'node:child_process';
import fs from 'node:fs';
@@ -254,18 +244,18 @@ describe('ToolRegistry', () => {
});
describe('discoverTools', () => {
- it('should sanitize tool parameters during discovery from command', async () => {
+ it('should will preserve tool parametersJsonSchema during discovery from command', async () => {
const discoveryCommand = 'my-discovery-command';
mockConfigGetToolDiscoveryCommand.mockReturnValue(discoveryCommand);
const unsanitizedToolDeclaration: FunctionDeclaration = {
name: 'tool-with-bad-format',
description: 'A tool with an invalid format property',
- parameters: {
- type: Type.OBJECT,
+ parametersJsonSchema: {
+ type: 'object',
properties: {
some_string: {
- type: Type.STRING,
+ type: 'string',
format: 'uuid', // This is an unsupported format
},
},
@@ -308,12 +298,16 @@ describe('ToolRegistry', () => {
expect(discoveredTool).toBeDefined();
const registeredParams = (discoveredTool as DiscoveredTool).schema
- .parameters as Schema;
- expect(registeredParams.properties?.['some_string']).toBeDefined();
- expect(registeredParams.properties?.['some_string']).toHaveProperty(
- 'format',
- undefined,
- );
+ .parametersJsonSchema;
+ expect(registeredParams).toStrictEqual({
+ type: 'object',
+ properties: {
+ some_string: {
+ type: 'string',
+ format: 'uuid',
+ },
+ },
+ });
});
it('should discover tools using MCP servers defined in getMcpServers', async () => {
@@ -365,187 +359,3 @@ describe('ToolRegistry', () => {
});
});
});
-
-describe('sanitizeParameters', () => {
- it('should remove default when anyOf is present', () => {
- const schema: Schema = {
- anyOf: [{ type: Type.STRING }, { type: Type.NUMBER }],
- default: 'hello',
- };
- sanitizeParameters(schema);
- expect(schema.default).toBeUndefined();
- });
-
- it('should recursively sanitize items in anyOf', () => {
- const schema: Schema = {
- anyOf: [
- {
- anyOf: [{ type: Type.STRING }],
- default: 'world',
- },
- { type: Type.NUMBER },
- ],
- };
- sanitizeParameters(schema);
- expect(schema.anyOf![0].default).toBeUndefined();
- });
-
- it('should recursively sanitize items in items', () => {
- const schema: Schema = {
- items: {
- anyOf: [{ type: Type.STRING }],
- default: 'world',
- },
- };
- sanitizeParameters(schema);
- expect(schema.items!.default).toBeUndefined();
- });
-
- it('should recursively sanitize items in properties', () => {
- const schema: Schema = {
- properties: {
- prop1: {
- anyOf: [{ type: Type.STRING }],
- default: 'world',
- },
- },
- };
- sanitizeParameters(schema);
- expect(schema.properties!.prop1.default).toBeUndefined();
- });
-
- it('should handle complex nested schemas', () => {
- const schema: Schema = {
- properties: {
- prop1: {
- items: {
- anyOf: [{ type: Type.STRING }],
- default: 'world',
- },
- },
- prop2: {
- anyOf: [
- {
- properties: {
- nestedProp: {
- anyOf: [{ type: Type.NUMBER }],
- default: 123,
- },
- },
- },
- ],
- },
- },
- };
- sanitizeParameters(schema);
- expect(schema.properties!.prop1.items!.default).toBeUndefined();
- const nestedProp =
- schema.properties!.prop2.anyOf![0].properties!.nestedProp;
- expect(nestedProp?.default).toBeUndefined();
- });
-
- it('should remove unsupported format from a simple string property', () => {
- const schema: Schema = {
- type: Type.OBJECT,
- properties: {
- name: { type: Type.STRING },
- id: { type: Type.STRING, format: 'uuid' },
- },
- };
- sanitizeParameters(schema);
- expect(schema.properties?.['id']).toHaveProperty('format', undefined);
- expect(schema.properties?.['name']).not.toHaveProperty('format');
- });
-
- it('should NOT remove supported format values', () => {
- const schema: Schema = {
- type: Type.OBJECT,
- properties: {
- date: { type: Type.STRING, format: 'date-time' },
- role: {
- type: Type.STRING,
- format: 'enum',
- enum: ['admin', 'user'],
- },
- },
- };
- const originalSchema = JSON.parse(JSON.stringify(schema));
- sanitizeParameters(schema);
- expect(schema).toEqual(originalSchema);
- });
-
- it('should handle arrays of objects', () => {
- const schema: Schema = {
- type: Type.OBJECT,
- properties: {
- items: {
- type: Type.ARRAY,
- items: {
- type: Type.OBJECT,
- properties: {
- itemId: { type: Type.STRING, format: 'uuid' },
- },
- },
- },
- },
- };
- sanitizeParameters(schema);
- expect(
- (schema.properties?.['items']?.items as Schema)?.properties?.['itemId'],
- ).toHaveProperty('format', undefined);
- });
-
- it('should handle schemas with no properties to sanitize', () => {
- const schema: Schema = {
- type: Type.OBJECT,
- properties: {
- count: { type: Type.NUMBER },
- isActive: { type: Type.BOOLEAN },
- },
- };
- const originalSchema = JSON.parse(JSON.stringify(schema));
- sanitizeParameters(schema);
- expect(schema).toEqual(originalSchema);
- });
-
- it('should not crash on an empty or undefined schema', () => {
- expect(() => sanitizeParameters({})).not.toThrow();
- expect(() => sanitizeParameters(undefined)).not.toThrow();
- });
-
- it('should handle complex nested schemas with cycles', () => {
- const userNode: any = {
- type: Type.OBJECT,
- properties: {
- id: { type: Type.STRING, format: 'uuid' },
- name: { type: Type.STRING },
- manager: {
- type: Type.OBJECT,
- properties: {
- id: { type: Type.STRING, format: 'uuid' },
- },
- },
- },
- };
- userNode.properties.reports = {
- type: Type.ARRAY,
- items: userNode,
- };
-
- const schema: Schema = {
- type: Type.OBJECT,
- properties: {
- ceo: userNode,
- },
- };
-
- expect(() => sanitizeParameters(schema)).not.toThrow();
- expect(schema.properties?.['ceo']?.properties?.['id']).toHaveProperty(
- 'format',
- undefined,
- );
- expect(
- schema.properties?.['ceo']?.properties?.['manager']?.properties?.['id'],
- ).toHaveProperty('format', undefined);
- });
-});