feat: add agent toml parser (#15112)

This commit is contained in:
Abhi
2025-12-17 22:46:55 -05:00
committed by GitHub
parent bc168bbae4
commit 2b426c1d91
16 changed files with 918 additions and 93 deletions
@@ -0,0 +1,57 @@
/**
* @license
* Copyright 2025 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
import { describe, it, expect } from 'vitest';
import {
isValidToolName,
ALL_BUILTIN_TOOL_NAMES,
DISCOVERED_TOOL_PREFIX,
LS_TOOL_NAME,
} from './tool-names.js';
describe('tool-names', () => {
describe('isValidToolName', () => {
it('should validate built-in tool names', () => {
expect(isValidToolName(LS_TOOL_NAME)).toBe(true);
for (const name of ALL_BUILTIN_TOOL_NAMES) {
expect(isValidToolName(name)).toBe(true);
}
});
it('should validate discovered tool names', () => {
expect(isValidToolName(`${DISCOVERED_TOOL_PREFIX}my_tool`)).toBe(true);
});
it('should validate MCP tool names (server__tool)', () => {
expect(isValidToolName('server__tool')).toBe(true);
expect(isValidToolName('my-server__my-tool')).toBe(true);
});
it('should reject invalid tool names', () => {
expect(isValidToolName('')).toBe(false);
expect(isValidToolName('invalid-name')).toBe(false);
expect(isValidToolName('server__')).toBe(false);
expect(isValidToolName('__tool')).toBe(false);
expect(isValidToolName('server__tool__extra')).toBe(false);
});
it('should handle wildcards when allowed', () => {
// Default: not allowed
expect(isValidToolName('*')).toBe(false);
expect(isValidToolName('server__*')).toBe(false);
// Explicitly allowed
expect(isValidToolName('*', { allowWildcards: true })).toBe(true);
expect(isValidToolName('server__*', { allowWildcards: true })).toBe(true);
// Invalid wildcards
expect(isValidToolName('__*', { allowWildcards: true })).toBe(false);
expect(isValidToolName('server__tool*', { allowWildcards: true })).toBe(
false,
);
});
});
});
+67
View File
@@ -22,3 +22,70 @@ export const LS_TOOL_NAME = 'list_directory';
export const MEMORY_TOOL_NAME = 'save_memory';
export const EDIT_TOOL_NAMES = new Set([EDIT_TOOL_NAME, WRITE_FILE_TOOL_NAME]);
export const DELEGATE_TO_AGENT_TOOL_NAME = 'delegate_to_agent';
/** Prefix used for tools discovered via the toolDiscoveryCommand. */
export const DISCOVERED_TOOL_PREFIX = 'discovered_tool_';
/**
* List of all built-in tool names.
*/
export const ALL_BUILTIN_TOOL_NAMES = [
GLOB_TOOL_NAME,
WRITE_TODOS_TOOL_NAME,
WRITE_FILE_TOOL_NAME,
WEB_SEARCH_TOOL_NAME,
WEB_FETCH_TOOL_NAME,
EDIT_TOOL_NAME,
SHELL_TOOL_NAME,
GREP_TOOL_NAME,
READ_MANY_FILES_TOOL_NAME,
READ_FILE_TOOL_NAME,
LS_TOOL_NAME,
MEMORY_TOOL_NAME,
DELEGATE_TO_AGENT_TOOL_NAME,
] as const;
/**
* Validates if a tool name is syntactically valid.
* Checks against built-in tools, discovered tools, and MCP naming conventions.
*/
export function isValidToolName(
name: string,
options: { allowWildcards?: boolean } = {},
): boolean {
// Built-in tools
if ((ALL_BUILTIN_TOOL_NAMES as readonly string[]).includes(name)) {
return true;
}
// Discovered tools
if (name.startsWith(DISCOVERED_TOOL_PREFIX)) {
return true;
}
// Policy wildcards
if (options.allowWildcards && name === '*') {
return true;
}
// MCP tools (format: server__tool)
if (name.includes('__')) {
const parts = name.split('__');
if (parts.length !== 2 || parts[0].length === 0 || parts[1].length === 0) {
return false;
}
const server = parts[0];
const tool = parts[1];
if (tool === '*') {
return !!options.allowWildcards;
}
// Basic slug validation for server and tool names
const slugRegex = /^[a-z0-9-_]+$/i;
return slugRegex.test(server) && slugRegex.test(tool);
}
return false;
}
@@ -11,11 +11,8 @@ import type { ConfigParameters } from '../config/config.js';
import { Config } from '../config/config.js';
import { ApprovalMode } from '../policy/types.js';
import {
ToolRegistry,
DiscoveredTool,
DISCOVERED_TOOL_PREFIX,
} from './tool-registry.js';
import { ToolRegistry, DiscoveredTool } from './tool-registry.js';
import { DISCOVERED_TOOL_PREFIX } from './tool-names.js';
import { DiscoveredMCPTool } from './mcp-tool.js';
import type { FunctionDeclaration, CallableTool } from '@google/genai';
import { mcpToTool } from '@google/genai';
+1 -2
View File
@@ -21,8 +21,7 @@ import { safeJsonStringify } from '../utils/safeJsonStringify.js';
import type { MessageBus } from '../confirmation-bus/message-bus.js';
import { debugLogger } from '../utils/debugLogger.js';
import { coreEvents } from '../utils/events.js';
export const DISCOVERED_TOOL_PREFIX = 'discovered_tool_';
import { DISCOVERED_TOOL_PREFIX } from './tool-names.js';
type ToolParams = Record<string, unknown>;