Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 19 additions & 1 deletion packages/agent/src/core/executeToolCall.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,25 @@ export const executeToolCall = async (
}

// TODO: validate JSON schema for input
const output = await tool.execute(toolCall.input, toolContext);
let output;
try {
output = await tool.execute(toolCall.input, toolContext);
} catch (err) {
if (err instanceof Error) {
logger.error(err.message);
return JSON.stringify({
error: true,
message: err.message,
stack: err.stack,
});
} else {
logger.error(err);
return JSON.stringify({
error: true,
message: err,
});
}
}

// for each result log it and its name
if (tool.logReturns) {
Expand Down
28 changes: 17 additions & 11 deletions packages/agent/src/core/toolAgent.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ const toolContext: ToolContext = {
userSession: false,
pageFilter: 'simple',
tokenTracker: new TokenTracker(),
githubMode: false,
};

// Mock tool for testing
Expand Down Expand Up @@ -98,16 +99,21 @@ describe('toolAgent', () => {
});

it('should handle tool execution errors', async () => {
await expect(
executeToolCall(
{
id: '1',
name: 'errorTool',
input: {},
},
[errorTool],
toolContext,
),
).rejects.toThrow('Deliberate failure');
const result = await executeToolCall(
{
id: '1',
name: 'errorTool',
input: {},
},
[errorTool],
toolContext,
);

// Parse the result as JSON
const parsedResult = JSON.parse(result);

// Check that it contains the expected error properties
expect(parsedResult.error).toBe(true);
expect(parsedResult.message).toContain('Deliberate failure');
});
});
10 changes: 5 additions & 5 deletions packages/agent/src/core/toolAgent/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ export function getModel(provider: ModelProvider, modelName: string) {
}
}

import { ToolContext } from '../types';

/**
* Default configuration for the tool agent
*/
Expand All @@ -44,9 +46,7 @@ export const DEFAULT_CONFIG = {
/**
* Gets the default system prompt with contextual information about the environment
*/
export function getDefaultSystemPrompt(options?: {
githubMode?: boolean;
}): string {
export function getDefaultSystemPrompt(toolContext: ToolContext): string {
// Gather context with error handling
const getCommandOutput = (command: string, label: string): string => {
try {
Expand All @@ -61,7 +61,7 @@ export function getDefaultSystemPrompt(options?: {
files: getCommandOutput('ls -la', 'file listing'),
system: getCommandOutput('uname -a', 'system information'),
datetime: new Date().toString(),
githubMode: options?.githubMode || false,
githubMode: toolContext.githubMode,
};

const githubModeInstructions = context.githubMode
Expand Down Expand Up @@ -110,7 +110,7 @@ export function getDefaultSystemPrompt(options?: {
'3. Update documentation as needed',
'4. Consider adding documentation if you encountered setup/understanding challenges',
'',
'Feel free to use Google and Bing via the browser tools to search for information or for ideas when you get stuck.',
'Feel free to use AI friendly search engines via the browser tools to search for information or for ideas when you get stuck.',
'',
'When you run into issues or unexpected results, take a step back and read the project documentation and configuration files and look at other source files in the project for examples of what works.',
'',
Expand Down
2 changes: 1 addition & 1 deletion packages/agent/src/core/toolAgent/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export const toolAgent = async (
logger.debug('User message:', initialPrompt);

// Get the system prompt once at the start
const systemPrompt = config.getSystemPrompt();
const systemPrompt = config.getSystemPrompt(context);

for (let i = 0; i < config.maxIterations; i++) {
logger.verbose(
Expand Down
17 changes: 12 additions & 5 deletions packages/agent/src/core/toolAgent/toolExecutor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,18 @@
...context,
tokenTracker: new TokenTracker(call.name, context.tokenTracker),
});
} catch (error: any) {
toolResult = JSON.stringify({
errorMessage: error.message,
errorType: error.constructor.name,
});
} catch (errorStr: any) {

Check warning on line 52 in packages/agent/src/core/toolAgent/toolExecutor.ts

View workflow job for this annotation

GitHub Actions / ci

Unexpected any. Specify a different type

Check warning on line 52 in packages/agent/src/core/toolAgent/toolExecutor.ts

View workflow job for this annotation

GitHub Actions / ci

Unexpected any. Specify a different type
if (errorStr instanceof Error) {
if (errorStr.stack) {
context.logger.error(`Tool error stack trace: ${errorStr.stack}`);
}
toolResult = JSON.stringify(errorStr);
} else {
toolResult = JSON.stringify({
errorMessage: errorStr.message,
errorType: errorStr.name,
});
}
}

return {
Expand Down
1 change: 1 addition & 0 deletions packages/agent/src/core/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@
userSession: boolean;
pageFilter: pageFilter;
tokenTracker: TokenTracker;
githubMode: boolean;
};

export type Tool<TParams = Record<string, any>, TReturn = any> = {

Check warning on line 22 in packages/agent/src/core/types.ts

View workflow job for this annotation

GitHub Actions / ci

Unexpected any. Specify a different type

Check warning on line 22 in packages/agent/src/core/types.ts

View workflow job for this annotation

GitHub Actions / ci

Unexpected any. Specify a different type

Check warning on line 22 in packages/agent/src/core/types.ts

View workflow job for this annotation

GitHub Actions / ci

Unexpected any. Specify a different type

Check warning on line 22 in packages/agent/src/core/types.ts

View workflow job for this annotation

GitHub Actions / ci

Unexpected any. Specify a different type
name: string;
description: string;
parameters: z.ZodType<TParams>;
Expand All @@ -38,7 +39,7 @@
export type ToolCall = {
id: string;
name: string;
input: any;

Check warning on line 42 in packages/agent/src/core/types.ts

View workflow job for this annotation

GitHub Actions / ci

Unexpected any. Specify a different type

Check warning on line 42 in packages/agent/src/core/types.ts

View workflow job for this annotation

GitHub Actions / ci

Unexpected any. Specify a different type
};

export type TextContent = {
Expand Down
6 changes: 4 additions & 2 deletions packages/agent/src/tools/interaction/subAgent.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { z } from 'zod';
import { zodToJsonSchema } from 'zod-to-json-schema';

import { getDefaultSystemPrompt } from '../../core/toolAgent/index.js';
import { getModel } from '../../core/toolAgent/config.js';
import { toolAgent } from '../../core/toolAgent.js';
import { Tool } from '../../core/types.js';
import { Tool, ToolContext } from '../../core/types.js';
import { getTools } from '../getTools.js';

const parameterSchema = z.object({
Expand Down Expand Up @@ -53,8 +54,9 @@ const subAgentConfig = {
model: getModel('anthropic', 'claude-3-7-sonnet-20250219'),
maxTokens: 4096,
temperature: 0.7,
getSystemPrompt: () => {
getSystemPrompt: (context: ToolContext) => {
return [
getDefaultSystemPrompt(context),
'You are a focused AI sub-agent handling a specific task.',
'You have access to the same tools as the main agent but should focus only on your assigned task.',
'When complete, call the sequenceComplete tool with your results.',
Expand Down
49 changes: 23 additions & 26 deletions packages/agent/src/tools/io/textEditor.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ const toolContext: ToolContext = {
userSession: false,
pageFilter: 'simple',
tokenTracker: new TokenTracker(),
githubMode: false,
};

describe('textEditor', () => {
Expand Down Expand Up @@ -259,18 +260,16 @@ describe('textEditor', () => {
const testPath = join(testDir, `${randomUUID()}.txt`);

// Try to view a non-existent file
const result = await textEditorTool.execute(
{
command: 'view',
path: testPath,
description: 'test',
},
toolContext,
);

// Verify return value
expect(result.success).toBe(false);
expect(result.message).toContain('not found');
await expect(async () => {
await textEditorTool.execute(
{
command: 'view',
path: testPath,
description: 'test',
},
toolContext,
);
}).rejects.toThrow(/not found/);
});

it('should handle errors for duplicate string replacements', async () => {
Expand All @@ -291,19 +290,17 @@ describe('textEditor', () => {
);

// Try to replace text with multiple occurrences
const result = await textEditorTool.execute(
{
command: 'str_replace',
path: testPath,
old_str: oldStr,
new_str: newStr,
description: 'test',
},
toolContext,
);

// Verify return value
expect(result.success).toBe(false);
expect(result.message).toContain('Found 2 occurrences');
await expect(async () => {
await textEditorTool.execute(
{
command: 'str_replace',
path: testPath,
old_str: oldStr,
new_str: newStr,
description: 'test',
},
toolContext,
);
}).rejects.toThrow(/Found 2 occurrences/);
});
});
Loading
Loading