mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-05-14 22:02:59 -07:00
feat: add agent toml parser (#15112)
This commit is contained in:
@@ -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,
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -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';
|
||||
|
||||
@@ -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>;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user