feat: add tool framework foundation (types, registry, executor, shell tool, model types, SOUL.md)

- Task 0: SOUL.md + loadSystemPrompt() in daemon
- Task 1: Tool type definitions (Tool, ToolCall, ToolResult, etc.)
- Task 2: ToolRegistry with Anthropic/OpenAI serialization
- Task 3: ToolExecutor with hooks, timeout, truncation
- Task 4: shell.exec builtin tool
- Task 8: Model types updated for tool use (ToolDefinition, ModelToolCall, etc.)
- Task 15: Model index exports for tool types
This commit is contained in:
William Valentin
2026-02-05 17:39:40 -08:00
parent 32dd3ad728
commit b00706325b
13 changed files with 691 additions and 7 deletions
+48
View File
@@ -0,0 +1,48 @@
import { execFile } from 'child_process';
import type { Tool, ToolResult } from '../types.js';
interface ShellExecArgs {
command: string;
cwd?: string;
timeout?: number;
}
export const shellExecTool: Tool = {
name: 'shell.exec',
description: 'Execute a shell command and return stdout/stderr. Use for running build commands, git operations, system tasks, etc.',
inputSchema: {
type: 'object',
properties: {
command: { type: 'string', description: 'The shell command to execute' },
cwd: { type: 'string', description: 'Working directory (optional)' },
timeout: { type: 'number', description: 'Timeout in milliseconds (default 30000)' },
},
required: ['command'],
},
execute: async (rawArgs: unknown): Promise<ToolResult> => {
const args = rawArgs as ShellExecArgs;
const timeout = args.timeout ?? 30_000;
return new Promise((resolve) => {
execFile('bash', ['-c', args.command], {
cwd: args.cwd,
timeout,
maxBuffer: 1024 * 1024,
}, (error, stdout, stderr) => {
if (error) {
if (error.killed || error.signal === 'SIGTERM') {
resolve({ success: false, output: stdout, error: `Command timed out after ${timeout}ms` });
return;
}
resolve({
success: false,
output: stdout,
error: stderr || error.message,
});
return;
}
resolve({ success: true, output: stdout + (stderr ? `\nstderr: ${stderr}` : '') });
});
});
},
};