ability to override core system prompt (via .gemini/system.md) and specify core tools via coreTools setting (e.g. coreTools:["ls", "GrepTool", ...]) ; added tests, but did not update docs for now (#413)
This commit is contained in:
parent
76cf5e9fc1
commit
3bf0304e31
|
@ -399,6 +399,7 @@ export async function loadCliConfig(settings: Settings): Promise<Config> {
|
|||
debugMode,
|
||||
argv.prompt || '',
|
||||
argv.all_files || false,
|
||||
settings.coreTools || undefined,
|
||||
settings.toolDiscoveryCommand,
|
||||
settings.toolCallCommand,
|
||||
settings.mcpServerCommand,
|
||||
|
|
|
@ -21,6 +21,7 @@ export enum SettingScope {
|
|||
export interface Settings {
|
||||
theme?: string;
|
||||
sandbox?: boolean | string;
|
||||
coreTools?: string[];
|
||||
toolDiscoveryCommand?: string;
|
||||
toolCallCommand?: string;
|
||||
mcpServerCommand?: string;
|
||||
|
|
|
@ -56,6 +56,7 @@ describe('Server Config (config.ts)', () => {
|
|||
DEBUG_MODE,
|
||||
QUESTION,
|
||||
FULL_CONTEXT,
|
||||
undefined, // coreTools
|
||||
undefined, // toolDiscoveryCommand
|
||||
undefined, // toolCallCommand
|
||||
undefined, // mcpServerCommand
|
||||
|
@ -85,6 +86,7 @@ describe('Server Config (config.ts)', () => {
|
|||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
USER_AGENT,
|
||||
// No userMemory argument
|
||||
);
|
||||
|
@ -101,10 +103,11 @@ describe('Server Config (config.ts)', () => {
|
|||
DEBUG_MODE,
|
||||
QUESTION,
|
||||
FULL_CONTEXT,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined, // coreTools
|
||||
undefined, // toolDiscoveryCommand
|
||||
undefined, // toolCallCommand
|
||||
undefined, // mcpServerCommand
|
||||
undefined, // mcpServers
|
||||
USER_AGENT,
|
||||
USER_MEMORY, // Pass memory here
|
||||
);
|
||||
|
@ -125,10 +128,11 @@ describe('Server Config (config.ts)', () => {
|
|||
DEBUG_MODE,
|
||||
QUESTION,
|
||||
FULL_CONTEXT,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined, // coreTools
|
||||
undefined, // toolDiscoveryCommand
|
||||
undefined, // toolCallCommand
|
||||
undefined, // mcpServerCommand
|
||||
undefined, // mcpServers
|
||||
USER_AGENT,
|
||||
// No userMemory argument
|
||||
);
|
||||
|
@ -148,10 +152,11 @@ describe('Server Config (config.ts)', () => {
|
|||
DEBUG_MODE,
|
||||
QUESTION,
|
||||
FULL_CONTEXT,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined, // coreTools
|
||||
undefined, // toolDiscoveryCommand
|
||||
undefined, // toolCallCommand
|
||||
undefined, // mcpServerCommand
|
||||
undefined, // mcpServers
|
||||
USER_AGENT,
|
||||
USER_MEMORY,
|
||||
);
|
||||
|
|
|
@ -19,7 +19,6 @@ import { ShellTool } from '../tools/shell.js';
|
|||
import { WriteFileTool } from '../tools/write-file.js';
|
||||
import { WebFetchTool } from '../tools/web-fetch.js';
|
||||
import { ReadManyFilesTool } from '../tools/read-many-files.js';
|
||||
import { BaseTool, ToolResult } from '../tools/tools.js';
|
||||
import { MemoryTool } from '../tools/memoryTool.js';
|
||||
|
||||
export class MCPServerConfig {
|
||||
|
@ -43,6 +42,7 @@ export class Config {
|
|||
private readonly debugMode: boolean,
|
||||
private readonly question: string | undefined, // Keep undefined possibility
|
||||
private readonly fullContext: boolean = false, // Default value here
|
||||
private readonly coreTools: string[] | undefined,
|
||||
private readonly toolDiscoveryCommand: string | undefined,
|
||||
private readonly toolCallCommand: string | undefined,
|
||||
private readonly mcpServerCommand: string | undefined,
|
||||
|
@ -87,6 +87,10 @@ export class Config {
|
|||
return this.fullContext;
|
||||
}
|
||||
|
||||
getCoreTools(): string[] | undefined {
|
||||
return this.coreTools;
|
||||
}
|
||||
|
||||
getToolDiscoveryCommand(): string | undefined {
|
||||
return this.toolDiscoveryCommand;
|
||||
}
|
||||
|
@ -168,6 +172,7 @@ export function createServerConfig(
|
|||
debugMode: boolean,
|
||||
question: string,
|
||||
fullContext?: boolean,
|
||||
coreTools?: string[],
|
||||
toolDiscoveryCommand?: string,
|
||||
toolCallCommand?: string,
|
||||
mcpServerCommand?: string,
|
||||
|
@ -185,6 +190,7 @@ export function createServerConfig(
|
|||
debugMode,
|
||||
question,
|
||||
fullContext,
|
||||
coreTools,
|
||||
toolDiscoveryCommand,
|
||||
toolCallCommand,
|
||||
mcpServerCommand,
|
||||
|
@ -199,23 +205,30 @@ export function createServerConfig(
|
|||
function createToolRegistry(config: Config): ToolRegistry {
|
||||
const registry = new ToolRegistry(config);
|
||||
const targetDir = config.getTargetDir();
|
||||
const tools = config.getCoreTools()
|
||||
? new Set(config.getCoreTools())
|
||||
: undefined;
|
||||
|
||||
const tools: Array<BaseTool<unknown, ToolResult>> = [
|
||||
new LSTool(targetDir),
|
||||
new ReadFileTool(targetDir),
|
||||
new GrepTool(targetDir),
|
||||
new GlobTool(targetDir),
|
||||
new EditTool(config),
|
||||
new WriteFileTool(config),
|
||||
new WebFetchTool(),
|
||||
new ReadManyFilesTool(targetDir),
|
||||
new ShellTool(config),
|
||||
new MemoryTool(),
|
||||
];
|
||||
// helper to create & register core tools that are enabled
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const registerCoreTool = (ToolClass: any, ...args: unknown[]) => {
|
||||
// check both the tool name (.Name) and the class name (.name)
|
||||
if (!tools || tools.has(ToolClass.Name) || tools.has(ToolClass.name)) {
|
||||
registry.registerTool(new ToolClass(...args));
|
||||
}
|
||||
};
|
||||
|
||||
registerCoreTool(LSTool, targetDir);
|
||||
registerCoreTool(ReadFileTool, targetDir);
|
||||
registerCoreTool(GrepTool, targetDir);
|
||||
registerCoreTool(GlobTool, targetDir);
|
||||
registerCoreTool(EditTool, config);
|
||||
registerCoreTool(WriteFileTool, config);
|
||||
registerCoreTool(WebFetchTool);
|
||||
registerCoreTool(ReadManyFilesTool, targetDir);
|
||||
registerCoreTool(ShellTool, config);
|
||||
registerCoreTool(MemoryTool);
|
||||
|
||||
for (const tool of tools) {
|
||||
registry.registerTool(tool);
|
||||
}
|
||||
registry.discoverTools();
|
||||
return registry;
|
||||
}
|
||||
|
|
|
@ -65,7 +65,7 @@ Rigorously adhere to existing project conventions when reading or modifying code
|
|||
- **Command Execution:** Use the 'execute_bash_command' tool for running shell commands, remembering the safety rule to explain modifying commands first.
|
||||
- **Background Processes:** Use background processes (via \`&\`) for commands that are unlikely to stop on their own, e.g. \`node server.js &\`. If unsure, ask the user.
|
||||
- **Interactive Commands:** Try to avoid shell commands that are likely to require user interaction (e.g. \`git rebase -i\`). Use non-interactive versions of commands (e.g. \`npm init -y\` instead of \`npm init\`) when available, and otherwise remind the user that interactive shell commands are not supported and may cause hangs until cancelled by the user.
|
||||
- **Remembering Facts:** Use the 'saveMemory' tool to remember specific, *user-related* facts or preferences when the user explicitly asks, or when they state a clear, concise piece of information that would help personalize or streamline *your future interactions with them* (e.g., preferred coding style, common project paths they use, personal tool aliases). This tool is for user-specific information that should persist across sessions. Do *not* use it for general project context or information that belongs in project-specific \`GEMINI.md\` files. If unsure whether to save something, you can ask the user, "Should I remember that for you?"
|
||||
- **Remembering Facts:** Use the 'save_memory' tool to remember specific, *user-related* facts or preferences when the user explicitly asks, or when they state a clear, concise piece of information that would help personalize or streamline *your future interactions with them* (e.g., preferred coding style, common project paths they use, personal tool aliases). This tool is for user-specific information that should persist across sessions. Do *not* use it for general project context or information that belongs in project-specific \`GEMINI.md\` files. If unsure whether to save something, you can ask the user, "Should I remember that for you?"
|
||||
|
||||
## Interaction Details
|
||||
- **Help Command:** The user can use '/help' to display help information.
|
||||
|
@ -219,7 +219,7 @@ Rigorously adhere to existing project conventions when reading or modifying code
|
|||
- **Command Execution:** Use the 'execute_bash_command' tool for running shell commands, remembering the safety rule to explain modifying commands first.
|
||||
- **Background Processes:** Use background processes (via \`&\`) for commands that are unlikely to stop on their own, e.g. \`node server.js &\`. If unsure, ask the user.
|
||||
- **Interactive Commands:** Try to avoid shell commands that are likely to require user interaction (e.g. \`git rebase -i\`). Use non-interactive versions of commands (e.g. \`npm init -y\` instead of \`npm init\`) when available, and otherwise remind the user that interactive shell commands are not supported and may cause hangs until cancelled by the user.
|
||||
- **Remembering Facts:** Use the 'saveMemory' tool to remember specific, *user-related* facts or preferences when the user explicitly asks, or when they state a clear, concise piece of information that would help personalize or streamline *your future interactions with them* (e.g., preferred coding style, common project paths they use, personal tool aliases). This tool is for user-specific information that should persist across sessions. Do *not* use it for general project context or information that belongs in project-specific \`GEMINI.md\` files. If unsure whether to save something, you can ask the user, "Should I remember that for you?"
|
||||
- **Remembering Facts:** Use the 'save_memory' tool to remember specific, *user-related* facts or preferences when the user explicitly asks, or when they state a clear, concise piece of information that would help personalize or streamline *your future interactions with them* (e.g., preferred coding style, common project paths they use, personal tool aliases). This tool is for user-specific information that should persist across sessions. Do *not* use it for general project context or information that belongs in project-specific \`GEMINI.md\` files. If unsure whether to save something, you can ask the user, "Should I remember that for you?"
|
||||
|
||||
## Interaction Details
|
||||
- **Help Command:** The user can use '/help' to display help information.
|
||||
|
@ -368,7 +368,7 @@ Rigorously adhere to existing project conventions when reading or modifying code
|
|||
- **Command Execution:** Use the 'execute_bash_command' tool for running shell commands, remembering the safety rule to explain modifying commands first.
|
||||
- **Background Processes:** Use background processes (via \`&\`) for commands that are unlikely to stop on their own, e.g. \`node server.js &\`. If unsure, ask the user.
|
||||
- **Interactive Commands:** Try to avoid shell commands that are likely to require user interaction (e.g. \`git rebase -i\`). Use non-interactive versions of commands (e.g. \`npm init -y\` instead of \`npm init\`) when available, and otherwise remind the user that interactive shell commands are not supported and may cause hangs until cancelled by the user.
|
||||
- **Remembering Facts:** Use the 'saveMemory' tool to remember specific, *user-related* facts or preferences when the user explicitly asks, or when they state a clear, concise piece of information that would help personalize or streamline *your future interactions with them* (e.g., preferred coding style, common project paths they use, personal tool aliases). This tool is for user-specific information that should persist across sessions. Do *not* use it for general project context or information that belongs in project-specific \`GEMINI.md\` files. If unsure whether to save something, you can ask the user, "Should I remember that for you?"
|
||||
- **Remembering Facts:** Use the 'save_memory' tool to remember specific, *user-related* facts or preferences when the user explicitly asks, or when they state a clear, concise piece of information that would help personalize or streamline *your future interactions with them* (e.g., preferred coding style, common project paths they use, personal tool aliases). This tool is for user-specific information that should persist across sessions. Do *not* use it for general project context or information that belongs in project-specific \`GEMINI.md\` files. If unsure whether to save something, you can ask the user, "Should I remember that for you?"
|
||||
|
||||
## Interaction Details
|
||||
- **Help Command:** The user can use '/help' to display help information.
|
||||
|
@ -517,7 +517,7 @@ Rigorously adhere to existing project conventions when reading or modifying code
|
|||
- **Command Execution:** Use the 'execute_bash_command' tool for running shell commands, remembering the safety rule to explain modifying commands first.
|
||||
- **Background Processes:** Use background processes (via \`&\`) for commands that are unlikely to stop on their own, e.g. \`node server.js &\`. If unsure, ask the user.
|
||||
- **Interactive Commands:** Try to avoid shell commands that are likely to require user interaction (e.g. \`git rebase -i\`). Use non-interactive versions of commands (e.g. \`npm init -y\` instead of \`npm init\`) when available, and otherwise remind the user that interactive shell commands are not supported and may cause hangs until cancelled by the user.
|
||||
- **Remembering Facts:** Use the 'saveMemory' tool to remember specific, *user-related* facts or preferences when the user explicitly asks, or when they state a clear, concise piece of information that would help personalize or streamline *your future interactions with them* (e.g., preferred coding style, common project paths they use, personal tool aliases). This tool is for user-specific information that should persist across sessions. Do *not* use it for general project context or information that belongs in project-specific \`GEMINI.md\` files. If unsure whether to save something, you can ask the user, "Should I remember that for you?"
|
||||
- **Remembering Facts:** Use the 'save_memory' tool to remember specific, *user-related* facts or preferences when the user explicitly asks, or when they state a clear, concise piece of information that would help personalize or streamline *your future interactions with them* (e.g., preferred coding style, common project paths they use, personal tool aliases). This tool is for user-specific information that should persist across sessions. Do *not* use it for general project context or information that belongs in project-specific \`GEMINI.md\` files. If unsure whether to save something, you can ask the user, "Should I remember that for you?"
|
||||
|
||||
## Interaction Details
|
||||
- **Help Command:** The user can use '/help' to display help information.
|
||||
|
@ -666,7 +666,7 @@ Rigorously adhere to existing project conventions when reading or modifying code
|
|||
- **Command Execution:** Use the 'execute_bash_command' tool for running shell commands, remembering the safety rule to explain modifying commands first.
|
||||
- **Background Processes:** Use background processes (via \`&\`) for commands that are unlikely to stop on their own, e.g. \`node server.js &\`. If unsure, ask the user.
|
||||
- **Interactive Commands:** Try to avoid shell commands that are likely to require user interaction (e.g. \`git rebase -i\`). Use non-interactive versions of commands (e.g. \`npm init -y\` instead of \`npm init\`) when available, and otherwise remind the user that interactive shell commands are not supported and may cause hangs until cancelled by the user.
|
||||
- **Remembering Facts:** Use the 'saveMemory' tool to remember specific, *user-related* facts or preferences when the user explicitly asks, or when they state a clear, concise piece of information that would help personalize or streamline *your future interactions with them* (e.g., preferred coding style, common project paths they use, personal tool aliases). This tool is for user-specific information that should persist across sessions. Do *not* use it for general project context or information that belongs in project-specific \`GEMINI.md\` files. If unsure whether to save something, you can ask the user, "Should I remember that for you?"
|
||||
- **Remembering Facts:** Use the 'save_memory' tool to remember specific, *user-related* facts or preferences when the user explicitly asks, or when they state a clear, concise piece of information that would help personalize or streamline *your future interactions with them* (e.g., preferred coding style, common project paths they use, personal tool aliases). This tool is for user-specific information that should persist across sessions. Do *not* use it for general project context or information that belongs in project-specific \`GEMINI.md\` files. If unsure whether to save something, you can ask the user, "Should I remember that for you?"
|
||||
|
||||
## Interaction Details
|
||||
- **Help Command:** The user can use '/help' to display help information.
|
||||
|
@ -815,7 +815,7 @@ Rigorously adhere to existing project conventions when reading or modifying code
|
|||
- **Command Execution:** Use the 'execute_bash_command' tool for running shell commands, remembering the safety rule to explain modifying commands first.
|
||||
- **Background Processes:** Use background processes (via \`&\`) for commands that are unlikely to stop on their own, e.g. \`node server.js &\`. If unsure, ask the user.
|
||||
- **Interactive Commands:** Try to avoid shell commands that are likely to require user interaction (e.g. \`git rebase -i\`). Use non-interactive versions of commands (e.g. \`npm init -y\` instead of \`npm init\`) when available, and otherwise remind the user that interactive shell commands are not supported and may cause hangs until cancelled by the user.
|
||||
- **Remembering Facts:** Use the 'saveMemory' tool to remember specific, *user-related* facts or preferences when the user explicitly asks, or when they state a clear, concise piece of information that would help personalize or streamline *your future interactions with them* (e.g., preferred coding style, common project paths they use, personal tool aliases). This tool is for user-specific information that should persist across sessions. Do *not* use it for general project context or information that belongs in project-specific \`GEMINI.md\` files. If unsure whether to save something, you can ask the user, "Should I remember that for you?"
|
||||
- **Remembering Facts:** Use the 'save_memory' tool to remember specific, *user-related* facts or preferences when the user explicitly asks, or when they state a clear, concise piece of information that would help personalize or streamline *your future interactions with them* (e.g., preferred coding style, common project paths they use, personal tool aliases). This tool is for user-specific information that should persist across sessions. Do *not* use it for general project context or information that belongs in project-specific \`GEMINI.md\` files. If unsure whether to save something, you can ask the user, "Should I remember that for you?"
|
||||
|
||||
## Interaction Details
|
||||
- **Help Command:** The user can use '/help' to display help information.
|
||||
|
@ -964,7 +964,7 @@ Rigorously adhere to existing project conventions when reading or modifying code
|
|||
- **Command Execution:** Use the 'execute_bash_command' tool for running shell commands, remembering the safety rule to explain modifying commands first.
|
||||
- **Background Processes:** Use background processes (via \`&\`) for commands that are unlikely to stop on their own, e.g. \`node server.js &\`. If unsure, ask the user.
|
||||
- **Interactive Commands:** Try to avoid shell commands that are likely to require user interaction (e.g. \`git rebase -i\`). Use non-interactive versions of commands (e.g. \`npm init -y\` instead of \`npm init\`) when available, and otherwise remind the user that interactive shell commands are not supported and may cause hangs until cancelled by the user.
|
||||
- **Remembering Facts:** Use the 'saveMemory' tool to remember specific, *user-related* facts or preferences when the user explicitly asks, or when they state a clear, concise piece of information that would help personalize or streamline *your future interactions with them* (e.g., preferred coding style, common project paths they use, personal tool aliases). This tool is for user-specific information that should persist across sessions. Do *not* use it for general project context or information that belongs in project-specific \`GEMINI.md\` files. If unsure whether to save something, you can ask the user, "Should I remember that for you?"
|
||||
- **Remembering Facts:** Use the 'save_memory' tool to remember specific, *user-related* facts or preferences when the user explicitly asks, or when they state a clear, concise piece of information that would help personalize or streamline *your future interactions with them* (e.g., preferred coding style, common project paths they use, personal tool aliases). This tool is for user-specific information that should persist across sessions. Do *not* use it for general project context or information that belongs in project-specific \`GEMINI.md\` files. If unsure whether to save something, you can ask the user, "Should I remember that for you?"
|
||||
|
||||
## Interaction Details
|
||||
- **Help Command:** The user can use '/help' to display help information.
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import path from 'node:path';
|
||||
import fs from 'node:fs';
|
||||
import { LSTool } from '../tools/ls.js';
|
||||
import { EditTool } from '../tools/edit.js';
|
||||
import { GlobTool } from '../tools/glob.js';
|
||||
|
@ -12,14 +14,18 @@ import { ReadFileTool } from '../tools/read-file.js';
|
|||
import { ReadManyFilesTool } from '../tools/read-many-files.js';
|
||||
import { ShellTool } from '../tools/shell.js';
|
||||
import { WriteFileTool } from '../tools/write-file.js';
|
||||
import process from 'node:process'; // Import process
|
||||
import process from 'node:process';
|
||||
import { execSync } from 'node:child_process';
|
||||
import { MemoryTool } from '../tools/memoryTool.js';
|
||||
import { MemoryTool, GEMINI_CONFIG_DIR } from '../tools/memoryTool.js';
|
||||
|
||||
const contactEmail = 'gemini-code-dev@google.com';
|
||||
|
||||
export function getCoreSystemPrompt(userMemory?: string): string {
|
||||
const basePrompt = `
|
||||
// replace base prompt with system.md if it exists under GEMINI_CONFIG_DIR
|
||||
const systemMdPath = path.join(GEMINI_CONFIG_DIR, 'system.md');
|
||||
const basePrompt = fs.existsSync(systemMdPath)
|
||||
? fs.readFileSync(systemMdPath, 'utf8')
|
||||
: `
|
||||
You are an interactive CLI agent specializing in software engineering tasks. Your primary goal is to help users safely and efficiently, adhering strictly to the following instructions and utilizing your available tools.
|
||||
|
||||
# Primary Workflows
|
||||
|
|
|
@ -155,13 +155,13 @@ describe('MemoryTool', () => {
|
|||
});
|
||||
|
||||
it('should have correct name, displayName, description, and schema', () => {
|
||||
expect(memoryTool.name).toBe('saveMemory');
|
||||
expect(memoryTool.name).toBe('save_memory');
|
||||
expect(memoryTool.displayName).toBe('Save Memory');
|
||||
expect(memoryTool.description).toContain(
|
||||
'Saves a specific piece of information',
|
||||
);
|
||||
expect(memoryTool.schema).toBeDefined();
|
||||
expect(memoryTool.schema.name).toBe('saveMemory');
|
||||
expect(memoryTool.schema.name).toBe('save_memory');
|
||||
expect(memoryTool.schema.parameters?.properties?.fact).toBeDefined();
|
||||
});
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ import * as path from 'path';
|
|||
import { homedir } from 'os';
|
||||
|
||||
const memoryToolSchemaData = {
|
||||
name: 'saveMemory',
|
||||
name: 'save_memory',
|
||||
description:
|
||||
'Saves a specific piece of information or fact to your long-term memory. Use this when the user explicitly asks you to remember something, or when they state a clear, concise fact that seems important to retain for future interactions.',
|
||||
parameters: {
|
||||
|
@ -180,7 +180,7 @@ export class MemoryTool extends BaseTool<SaveMemoryParams, ToolResult> {
|
|||
const errorMessage =
|
||||
error instanceof Error ? error.message : String(error);
|
||||
console.error(
|
||||
`[MemoryTool] Error executing saveMemory for fact "${fact}": ${errorMessage}`,
|
||||
`[MemoryTool] Error executing save_memory for fact "${fact}": ${errorMessage}`,
|
||||
);
|
||||
return {
|
||||
llmContent: JSON.stringify({
|
||||
|
|
|
@ -87,6 +87,7 @@ describe('ToolRegistry', () => {
|
|||
false, // debugMode
|
||||
undefined, // question
|
||||
false, // fullContext
|
||||
undefined, // coreTools
|
||||
undefined, // toolDiscoveryCommand
|
||||
undefined, // toolCallCommand
|
||||
undefined, // mcpServerCommand
|
||||
|
@ -170,6 +171,163 @@ describe('ToolRegistry', () => {
|
|||
});
|
||||
});
|
||||
|
||||
// New describe block for coreTools testing
|
||||
describe('core tool registration based on config.coreTools', () => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const MOCK_TOOL_ALPHA_CLASS_NAME = 'MockCoreToolAlpha'; // Class.name
|
||||
const MOCK_TOOL_ALPHA_STATIC_NAME = 'ToolAlphaFromStatic'; // Tool.Name and registration name
|
||||
class MockCoreToolAlpha extends BaseTool<any, ToolResult> {
|
||||
static readonly Name = MOCK_TOOL_ALPHA_STATIC_NAME;
|
||||
constructor() {
|
||||
super(
|
||||
MockCoreToolAlpha.Name,
|
||||
MockCoreToolAlpha.Name,
|
||||
'Description for Alpha Tool',
|
||||
{},
|
||||
);
|
||||
}
|
||||
async execute(_params: any): Promise<ToolResult> {
|
||||
return { llmContent: 'AlphaExecuted', returnDisplay: 'AlphaExecuted' };
|
||||
}
|
||||
}
|
||||
|
||||
const MOCK_TOOL_BETA_CLASS_NAME = 'MockCoreToolBeta'; // Class.name
|
||||
const MOCK_TOOL_BETA_STATIC_NAME = 'ToolBetaFromStatic'; // Tool.Name and registration name
|
||||
class MockCoreToolBeta extends BaseTool<any, ToolResult> {
|
||||
static readonly Name = MOCK_TOOL_BETA_STATIC_NAME;
|
||||
constructor() {
|
||||
super(
|
||||
MockCoreToolBeta.Name,
|
||||
MockCoreToolBeta.Name,
|
||||
'Description for Beta Tool',
|
||||
{},
|
||||
);
|
||||
}
|
||||
async execute(_params: any): Promise<ToolResult> {
|
||||
return { llmContent: 'BetaExecuted', returnDisplay: 'BetaExecuted' };
|
||||
}
|
||||
}
|
||||
|
||||
const availableCoreToolClasses = [MockCoreToolAlpha, MockCoreToolBeta];
|
||||
let currentConfig: Config;
|
||||
let currentToolRegistry: ToolRegistry;
|
||||
const mockTargetDir = '/test/dir'; // As used in outer scope
|
||||
|
||||
// Helper to set up Config, ToolRegistry, and simulate core tool registration
|
||||
const setupRegistryAndSimulateRegistration = (
|
||||
coreToolsValueInConfig: string[] | undefined,
|
||||
) => {
|
||||
currentConfig = new Config(
|
||||
'test-api-key',
|
||||
'test-model',
|
||||
false, // sandbox
|
||||
mockTargetDir, // targetDir
|
||||
false, // debugMode
|
||||
undefined, // question
|
||||
false, // fullContext
|
||||
coreToolsValueInConfig, // coreTools setting being tested
|
||||
undefined, // toolDiscoveryCommand
|
||||
undefined, // toolCallCommand
|
||||
undefined, // mcpServerCommand
|
||||
undefined, // mcpServers
|
||||
'TestAgent/1.0', // userAgent
|
||||
);
|
||||
|
||||
// We assume Config has a getter like getCoreTools() or stores it publicly.
|
||||
// For this test, we'll directly use coreToolsValueInConfig for the simulation logic,
|
||||
// as that's what Config would provide.
|
||||
const coreToolsListFromConfig = coreToolsValueInConfig; // Simulating config.getCoreTools()
|
||||
|
||||
currentToolRegistry = new ToolRegistry(currentConfig);
|
||||
|
||||
// Simulate the external process that registers core tools based on config
|
||||
if (coreToolsListFromConfig === undefined) {
|
||||
// If coreTools is undefined, all available core tools are registered
|
||||
availableCoreToolClasses.forEach((ToolClass) => {
|
||||
currentToolRegistry.registerTool(new ToolClass());
|
||||
});
|
||||
} else {
|
||||
// If coreTools is an array, register tools if their static Name or class name is in the list
|
||||
availableCoreToolClasses.forEach((ToolClass) => {
|
||||
if (
|
||||
coreToolsListFromConfig.includes(ToolClass.Name) || // Check against static Name
|
||||
coreToolsListFromConfig.includes(ToolClass.name) // Check against class name
|
||||
) {
|
||||
currentToolRegistry.registerTool(new ToolClass());
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// beforeEach for this nested describe is not strictly needed if setup is per-test,
|
||||
// but ensure console.warn is mocked if any registration overwrites occur (though unlikely with this setup).
|
||||
beforeEach(() => {
|
||||
vi.spyOn(console, 'warn').mockImplementation(() => {});
|
||||
});
|
||||
|
||||
it('should register all core tools if coreTools config is undefined', () => {
|
||||
setupRegistryAndSimulateRegistration(undefined);
|
||||
expect(
|
||||
currentToolRegistry.getTool(MOCK_TOOL_ALPHA_STATIC_NAME),
|
||||
).toBeInstanceOf(MockCoreToolAlpha);
|
||||
expect(
|
||||
currentToolRegistry.getTool(MOCK_TOOL_BETA_STATIC_NAME),
|
||||
).toBeInstanceOf(MockCoreToolBeta);
|
||||
expect(currentToolRegistry.getAllTools()).toHaveLength(2);
|
||||
});
|
||||
|
||||
it('should register no core tools if coreTools config is an empty array []', () => {
|
||||
setupRegistryAndSimulateRegistration([]);
|
||||
expect(currentToolRegistry.getAllTools()).toHaveLength(0);
|
||||
expect(
|
||||
currentToolRegistry.getTool(MOCK_TOOL_ALPHA_STATIC_NAME),
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
currentToolRegistry.getTool(MOCK_TOOL_BETA_STATIC_NAME),
|
||||
).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should register only tools specified by their static Name (ToolClass.Name) in coreTools config', () => {
|
||||
setupRegistryAndSimulateRegistration([MOCK_TOOL_ALPHA_STATIC_NAME]); // e.g., ["ToolAlphaFromStatic"]
|
||||
expect(
|
||||
currentToolRegistry.getTool(MOCK_TOOL_ALPHA_STATIC_NAME),
|
||||
).toBeInstanceOf(MockCoreToolAlpha);
|
||||
expect(
|
||||
currentToolRegistry.getTool(MOCK_TOOL_BETA_STATIC_NAME),
|
||||
).toBeUndefined();
|
||||
expect(currentToolRegistry.getAllTools()).toHaveLength(1);
|
||||
});
|
||||
|
||||
it('should register only tools specified by their class name (ToolClass.name) in coreTools config', () => {
|
||||
// ToolBeta is registered under MOCK_TOOL_BETA_STATIC_NAME ('ToolBetaFromStatic')
|
||||
// We configure coreTools with its class name: MOCK_TOOL_BETA_CLASS_NAME ('MockCoreToolBeta')
|
||||
setupRegistryAndSimulateRegistration([MOCK_TOOL_BETA_CLASS_NAME]);
|
||||
expect(
|
||||
currentToolRegistry.getTool(MOCK_TOOL_BETA_STATIC_NAME),
|
||||
).toBeInstanceOf(MockCoreToolBeta);
|
||||
expect(
|
||||
currentToolRegistry.getTool(MOCK_TOOL_ALPHA_STATIC_NAME),
|
||||
).toBeUndefined();
|
||||
expect(currentToolRegistry.getAllTools()).toHaveLength(1);
|
||||
});
|
||||
|
||||
it('should register tools if specified by either static Name or class name in a mixed coreTools config', () => {
|
||||
// Config: ["ToolAlphaFromStatic", "MockCoreToolBeta"]
|
||||
// ToolAlpha matches by static Name. ToolBeta matches by class name.
|
||||
setupRegistryAndSimulateRegistration([
|
||||
MOCK_TOOL_ALPHA_STATIC_NAME, // Matches MockCoreToolAlpha.Name
|
||||
MOCK_TOOL_BETA_CLASS_NAME, // Matches MockCoreToolBeta.name
|
||||
]);
|
||||
expect(
|
||||
currentToolRegistry.getTool(MOCK_TOOL_ALPHA_STATIC_NAME),
|
||||
).toBeInstanceOf(MockCoreToolAlpha);
|
||||
expect(
|
||||
currentToolRegistry.getTool(MOCK_TOOL_BETA_STATIC_NAME),
|
||||
).toBeInstanceOf(MockCoreToolBeta); // Registered under its static Name
|
||||
expect(currentToolRegistry.getAllTools()).toHaveLength(2);
|
||||
});
|
||||
});
|
||||
|
||||
describe('discoverTools', () => {
|
||||
let mockConfigGetToolDiscoveryCommand: ReturnType<typeof vi.spyOn>;
|
||||
let mockConfigGetMcpServers: ReturnType<typeof vi.spyOn>;
|
||||
|
@ -417,6 +575,7 @@ describe('DiscoveredTool', () => {
|
|||
false, // debugMode
|
||||
undefined, // question
|
||||
false, // fullContext
|
||||
undefined, // coreTools
|
||||
undefined, // toolDiscoveryCommand
|
||||
undefined, // toolCallCommand
|
||||
undefined, // mcpServerCommand
|
||||
|
|
Loading…
Reference in New Issue