summaryrefslogtreecommitdiff
path: root/packages/server/src/tools
diff options
context:
space:
mode:
Diffstat (limited to 'packages/server/src/tools')
-rw-r--r--packages/server/src/tools/memoryTool.test.ts4
-rw-r--r--packages/server/src/tools/memoryTool.ts4
-rw-r--r--packages/server/src/tools/tool-registry.test.ts159
3 files changed, 163 insertions, 4 deletions
diff --git a/packages/server/src/tools/memoryTool.test.ts b/packages/server/src/tools/memoryTool.test.ts
index efbbb025..42b1329d 100644
--- a/packages/server/src/tools/memoryTool.test.ts
+++ b/packages/server/src/tools/memoryTool.test.ts
@@ -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();
});
diff --git a/packages/server/src/tools/memoryTool.ts b/packages/server/src/tools/memoryTool.ts
index 177072fe..49dce59d 100644
--- a/packages/server/src/tools/memoryTool.ts
+++ b/packages/server/src/tools/memoryTool.ts
@@ -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({
diff --git a/packages/server/src/tools/tool-registry.test.ts b/packages/server/src/tools/tool-registry.test.ts
index 7f3c2e86..4c2bff38 100644
--- a/packages/server/src/tools/tool-registry.test.ts
+++ b/packages/server/src/tools/tool-registry.test.ts
@@ -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