poe-code 1.2.1 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -20
- package/dist/cli/bootstrap.d.ts +4 -0
- package/dist/cli/bootstrap.js +75 -0
- package/dist/cli/bootstrap.js.map +1 -0
- package/dist/cli/commands/configure.d.ts +2 -1
- package/dist/cli/commands/configure.js +7 -7
- package/dist/cli/commands/configure.js.map +1 -1
- package/dist/cli/container.d.ts +0 -5
- package/dist/cli/container.js +0 -8
- package/dist/cli/container.js.map +1 -1
- package/dist/cli/error-logger.d.ts +17 -2
- package/dist/cli/error-logger.js.map +1 -1
- package/dist/cli/errors.d.ts +6 -0
- package/dist/cli/errors.js +8 -0
- package/dist/cli/errors.js.map +1 -1
- package/dist/cli/program.js +6 -26
- package/dist/cli/program.js.map +1 -1
- package/dist/cli/prompt-runner.d.ts +3 -0
- package/dist/cli/prompt-runner.js +9 -0
- package/dist/cli/prompt-runner.js.map +1 -0
- package/dist/cli/service-registry.d.ts +8 -0
- package/dist/cli/service-registry.js.map +1 -1
- package/dist/cli/ui/service-menu.d.ts +6 -0
- package/dist/cli/ui/service-menu.js +37 -0
- package/dist/cli/ui/service-menu.js.map +1 -0
- package/dist/cli/ui/theme.d.ts +16 -0
- package/dist/cli/ui/theme.js +78 -0
- package/dist/cli/ui/theme.js.map +1 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -74
- package/dist/index.js.map +1 -1
- package/dist/providers/claude-code-adapter.js +6 -0
- package/dist/providers/claude-code-adapter.js.map +1 -1
- package/dist/providers/codex-adapter.js +6 -0
- package/dist/providers/codex-adapter.js.map +1 -1
- package/dist/providers/opencode-adapter.js +6 -0
- package/dist/providers/opencode-adapter.js.map +1 -1
- package/package.json +13 -34
- package/dist/cli/api-client.d.ts +0 -14
- package/dist/cli/api-client.js +0 -140
- package/dist/cli/api-client.js.map +0 -1
- package/dist/cli/chat.d.ts +0 -32
- package/dist/cli/chat.js +0 -2
- package/dist/cli/chat.js.map +0 -1
- package/dist/cli/commands/agent.d.ts +0 -18
- package/dist/cli/commands/agent.js +0 -84
- package/dist/cli/commands/agent.js.map +0 -1
- package/dist/cli/commands/configure-agents.d.ts +0 -3
- package/dist/cli/commands/configure-agents.js +0 -72
- package/dist/cli/commands/configure-agents.js.map +0 -1
- package/dist/cli/commands/init.d.ts +0 -8
- package/dist/cli/commands/init.js +0 -45
- package/dist/cli/commands/init.js.map +0 -1
- package/dist/cli/commands/interactive.d.ts +0 -3
- package/dist/cli/commands/interactive.js +0 -17
- package/dist/cli/commands/interactive.js.map +0 -1
- package/dist/cli/commands/login.d.ts +0 -6
- package/dist/cli/commands/login.js +0 -51
- package/dist/cli/commands/login.js.map +0 -1
- package/dist/cli/commands/logout.d.ts +0 -3
- package/dist/cli/commands/logout.js +0 -31
- package/dist/cli/commands/logout.js.map +0 -1
- package/dist/cli/commands/prerequisites.d.ts +0 -3
- package/dist/cli/commands/prerequisites.js +0 -23
- package/dist/cli/commands/prerequisites.js.map +0 -1
- package/dist/cli/commands/query.d.ts +0 -7
- package/dist/cli/commands/query.js +0 -46
- package/dist/cli/commands/query.js.map +0 -1
- package/dist/cli/commands/remove.d.ts +0 -6
- package/dist/cli/commands/remove.js +0 -80
- package/dist/cli/commands/remove.js.map +0 -1
- package/dist/cli/commands/root.d.ts +0 -3
- package/dist/cli/commands/root.js +0 -7
- package/dist/cli/commands/root.js.map +0 -1
- package/dist/cli/commands/spawn-worktree.d.ts +0 -6
- package/dist/cli/commands/spawn-worktree.js +0 -91
- package/dist/cli/commands/spawn-worktree.js.map +0 -1
- package/dist/cli/commands/spawn.d.ts +0 -7
- package/dist/cli/commands/spawn.js +0 -112
- package/dist/cli/commands/spawn.js.map +0 -1
- package/dist/cli/commands/test.d.ts +0 -6
- package/dist/cli/commands/test.js +0 -26
- package/dist/cli/commands/test.js.map +0 -1
- package/dist/cli/file-mentions.d.ts +0 -13
- package/dist/cli/file-mentions.js +0 -87
- package/dist/cli/file-mentions.js.map +0 -1
- package/dist/cli/file-picker-state.d.ts +0 -14
- package/dist/cli/file-picker-state.js +0 -23
- package/dist/cli/file-picker-state.js.map +0 -1
- package/dist/cli/interactive-command-runner.d.ts +0 -11
- package/dist/cli/interactive-command-runner.js +0 -142
- package/dist/cli/interactive-command-runner.js.map +0 -1
- package/dist/cli/interactive-launcher.d.ts +0 -2
- package/dist/cli/interactive-launcher.js +0 -404
- package/dist/cli/interactive-launcher.js.map +0 -1
- package/dist/cli/interactive-tasks.d.ts +0 -7
- package/dist/cli/interactive-tasks.js +0 -199
- package/dist/cli/interactive-tasks.js.map +0 -1
- package/dist/cli/interactive.d.ts +0 -19
- package/dist/cli/interactive.js +0 -479
- package/dist/cli/interactive.js.map +0 -1
- package/dist/cli/markdown-renderer.d.ts +0 -27
- package/dist/cli/markdown-renderer.js +0 -178
- package/dist/cli/markdown-renderer.js.map +0 -1
- package/dist/cli/markdown-renderer.test.d.ts +0 -1
- package/dist/cli/markdown-renderer.test.js +0 -105
- package/dist/cli/markdown-renderer.test.js.map +0 -1
- package/dist/commands/init.d.ts +0 -9
- package/dist/commands/init.js +0 -43
- package/dist/commands/init.js.map +0 -1
- package/dist/commands/spawn-worktree.d.ts +0 -25
- package/dist/commands/spawn-worktree.js +0 -139
- package/dist/commands/spawn-worktree.js.map +0 -1
- package/dist/services/agent-config-manager.d.ts +0 -32
- package/dist/services/agent-config-manager.js +0 -130
- package/dist/services/agent-config-manager.js.map +0 -1
- package/dist/services/agent-registry.d.ts +0 -27
- package/dist/services/agent-registry.js +0 -89
- package/dist/services/agent-registry.js.map +0 -1
- package/dist/services/agent-session.d.ts +0 -24
- package/dist/services/agent-session.js +0 -107
- package/dist/services/agent-session.js.map +0 -1
- package/dist/services/agent-task-registry.d.ts +0 -131
- package/dist/services/agent-task-registry.js +0 -491
- package/dist/services/agent-task-registry.js.map +0 -1
- package/dist/services/chat.d.ts +0 -94
- package/dist/services/chat.js +0 -241
- package/dist/services/chat.js.map +0 -1
- package/dist/services/mcp-client.d.ts +0 -38
- package/dist/services/mcp-client.js +0 -170
- package/dist/services/mcp-client.js.map +0 -1
- package/dist/services/mcp-manager.d.ts +0 -28
- package/dist/services/mcp-manager.js +0 -157
- package/dist/services/mcp-manager.js.map +0 -1
- package/dist/services/poe-code.d.ts +0 -7
- package/dist/services/poe-code.js +0 -5
- package/dist/services/poe-code.js.map +0 -1
- package/dist/services/task-logger.d.ts +0 -24
- package/dist/services/task-logger.js +0 -73
- package/dist/services/task-logger.js.map +0 -1
- package/dist/services/task-runner.d.ts +0 -19
- package/dist/services/task-runner.js +0 -157
- package/dist/services/task-runner.js.map +0 -1
- package/dist/services/tools.d.ts +0 -76
- package/dist/services/tools.js +0 -870
- package/dist/services/tools.js.map +0 -1
- package/dist/utils/e2e-flags.d.ts +0 -1
- package/dist/utils/e2e-flags.js +0 -9
- package/dist/utils/e2e-flags.js.map +0 -1
- package/dist/utils/worktree.d.ts +0 -40
- package/dist/utils/worktree.js +0 -179
- package/dist/utils/worktree.js.map +0 -1
- package/shared/conversation-layout.cjs +0 -11
- package/shared/conversation-layout.d.ts +0 -7
- package/shared/conversation-layout.js +0 -11
- package/shared/package.json +0 -13
package/dist/services/tools.js
DELETED
|
@@ -1,870 +0,0 @@
|
|
|
1
|
-
import { spawn } from "node:child_process";
|
|
2
|
-
import path from "node:path";
|
|
3
|
-
import { fileURLToPath } from "node:url";
|
|
4
|
-
import { spawnGitWorktree } from "../commands/spawn-worktree.js";
|
|
5
|
-
import { spawnClaudeCode } from "./claude-code.js";
|
|
6
|
-
import { simpleGit as createSimpleGit } from "simple-git";
|
|
7
|
-
import { tokenizeCommandLine } from "../utils/command-line.js";
|
|
8
|
-
import { createDefaultAgentRegistry, LEGACY_DEFAULT_AGENTS } from "./agent-registry.js";
|
|
9
|
-
export class DefaultToolExecutor {
|
|
10
|
-
constructor(dependencies) {
|
|
11
|
-
this.fs = dependencies.fs;
|
|
12
|
-
this.cwd = dependencies.cwd;
|
|
13
|
-
this.allowedPaths = dependencies.allowedPaths || [dependencies.cwd];
|
|
14
|
-
this.mcpManager = dependencies.mcpManager;
|
|
15
|
-
this.onWriteFile = dependencies.onWriteFile;
|
|
16
|
-
this.taskRegistry = dependencies.taskRegistry;
|
|
17
|
-
this.eventLogger = dependencies.logger ?? (() => { });
|
|
18
|
-
this.now = dependencies.now ?? Date.now;
|
|
19
|
-
this.spawnTask =
|
|
20
|
-
dependencies.spawnBackgroundTask ??
|
|
21
|
-
(this.taskRegistry ? this.createBackgroundSpawner() : undefined);
|
|
22
|
-
this.agentRegistry =
|
|
23
|
-
dependencies.agentRegistry ?? createDefaultAgentRegistry();
|
|
24
|
-
this.agentConfigManager = dependencies.agentConfigManager;
|
|
25
|
-
this.homeDir = dependencies.homeDir;
|
|
26
|
-
}
|
|
27
|
-
async executeTool(name, args) {
|
|
28
|
-
// Check if it's an MCP tool
|
|
29
|
-
if (name.startsWith("mcp__") && this.mcpManager) {
|
|
30
|
-
return await this.mcpManager.executeTool(name, args);
|
|
31
|
-
}
|
|
32
|
-
switch (name) {
|
|
33
|
-
case "read_file":
|
|
34
|
-
return await this.readFile(args);
|
|
35
|
-
case "write_file":
|
|
36
|
-
return await this.writeFile(args);
|
|
37
|
-
case "list_files":
|
|
38
|
-
return await this.listFiles(args);
|
|
39
|
-
case "run_command":
|
|
40
|
-
return await this.runCommand(args);
|
|
41
|
-
case "search_web":
|
|
42
|
-
return await this.searchWeb(args);
|
|
43
|
-
case "spawn_git_worktree":
|
|
44
|
-
return await this.spawnGitWorktreeTool(args);
|
|
45
|
-
default:
|
|
46
|
-
throw new Error(`Unknown tool: ${name}`);
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
isPathAllowed(filePath) {
|
|
50
|
-
const absolutePath = path.isAbsolute(filePath)
|
|
51
|
-
? filePath
|
|
52
|
-
: path.join(this.cwd, filePath);
|
|
53
|
-
return this.allowedPaths.some((allowedPath) => absolutePath.startsWith(allowedPath));
|
|
54
|
-
}
|
|
55
|
-
async readFile(args) {
|
|
56
|
-
const filePath = args.path;
|
|
57
|
-
if (!filePath) {
|
|
58
|
-
throw new Error("Missing required parameter: path");
|
|
59
|
-
}
|
|
60
|
-
if (!this.isPathAllowed(filePath)) {
|
|
61
|
-
throw new Error(`Access denied: ${filePath}`);
|
|
62
|
-
}
|
|
63
|
-
const absolutePath = path.isAbsolute(filePath)
|
|
64
|
-
? filePath
|
|
65
|
-
: path.join(this.cwd, filePath);
|
|
66
|
-
try {
|
|
67
|
-
const content = await this.fs.readFile(absolutePath, "utf8");
|
|
68
|
-
return content;
|
|
69
|
-
}
|
|
70
|
-
catch (error) {
|
|
71
|
-
throw new Error(`Failed to read file: ${error instanceof Error ? error.message : String(error)}`);
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
async writeFile(args) {
|
|
75
|
-
const filePath = args.path;
|
|
76
|
-
const content = args.content;
|
|
77
|
-
if (!filePath || content === undefined) {
|
|
78
|
-
throw new Error("Missing required parameters: path, content");
|
|
79
|
-
}
|
|
80
|
-
if (!this.isPathAllowed(filePath)) {
|
|
81
|
-
throw new Error(`Access denied: ${filePath}`);
|
|
82
|
-
}
|
|
83
|
-
const absolutePath = path.isAbsolute(filePath)
|
|
84
|
-
? filePath
|
|
85
|
-
: path.join(this.cwd, filePath);
|
|
86
|
-
const previousContent = await this.tryReadFile(absolutePath);
|
|
87
|
-
try {
|
|
88
|
-
await this.fs.writeFile(absolutePath, content, { encoding: "utf8" });
|
|
89
|
-
if (this.onWriteFile) {
|
|
90
|
-
await this.onWriteFile({
|
|
91
|
-
absolutePath,
|
|
92
|
-
relativePath: path.relative(this.cwd, absolutePath),
|
|
93
|
-
previousContent,
|
|
94
|
-
nextContent: content
|
|
95
|
-
});
|
|
96
|
-
}
|
|
97
|
-
return `Successfully wrote to ${filePath}`;
|
|
98
|
-
}
|
|
99
|
-
catch (error) {
|
|
100
|
-
throw new Error(`Failed to write file: ${error instanceof Error ? error.message : String(error)}`);
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
async listFiles(args) {
|
|
104
|
-
const dirPath = args.path || ".";
|
|
105
|
-
if (!this.isPathAllowed(dirPath)) {
|
|
106
|
-
throw new Error(`Access denied: ${dirPath}`);
|
|
107
|
-
}
|
|
108
|
-
const absolutePath = path.isAbsolute(dirPath)
|
|
109
|
-
? dirPath
|
|
110
|
-
: path.join(this.cwd, dirPath);
|
|
111
|
-
try {
|
|
112
|
-
const files = await this.fs.readdir(absolutePath);
|
|
113
|
-
return JSON.stringify(files, null, 2);
|
|
114
|
-
}
|
|
115
|
-
catch (error) {
|
|
116
|
-
throw new Error(`Failed to list files: ${error instanceof Error ? error.message : String(error)}`);
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
async runCommand(args) {
|
|
120
|
-
const commandValue = args.command;
|
|
121
|
-
if (typeof commandValue !== "string" || commandValue.trim().length === 0) {
|
|
122
|
-
throw new Error("Missing required parameter: command");
|
|
123
|
-
}
|
|
124
|
-
const tokens = tokenizeCommandLine(commandValue);
|
|
125
|
-
if (tokens.length === 0) {
|
|
126
|
-
throw new Error("Missing required parameter: command");
|
|
127
|
-
}
|
|
128
|
-
const [executable, ...commandArgs] = tokens;
|
|
129
|
-
if (this.isManagedCommand(executable)) {
|
|
130
|
-
return await this.runManagedCommand(executable, commandArgs);
|
|
131
|
-
}
|
|
132
|
-
return await this.executeExternalCommand(executable, commandArgs);
|
|
133
|
-
}
|
|
134
|
-
isManagedCommand(command) {
|
|
135
|
-
return command === "claude-code" || command === "claude";
|
|
136
|
-
}
|
|
137
|
-
async runManagedCommand(command, args) {
|
|
138
|
-
if (command === "claude-code" || command === "claude") {
|
|
139
|
-
return await this.executeClaudeCodeCommand(args);
|
|
140
|
-
}
|
|
141
|
-
throw new Error(`Unsupported managed command "${command}".`);
|
|
142
|
-
}
|
|
143
|
-
async executeClaudeCodeCommand(args) {
|
|
144
|
-
if (args.length === 0) {
|
|
145
|
-
throw new Error("Claude Code requires a prompt argument (e.g. claude-code \"Write hello world\").");
|
|
146
|
-
}
|
|
147
|
-
const [firstArg, ...rest] = args;
|
|
148
|
-
const promptParts = [firstArg];
|
|
149
|
-
let forwardedArgs = [];
|
|
150
|
-
if (rest.length > 0) {
|
|
151
|
-
const optionIndex = rest.findIndex((value) => value.startsWith("--"));
|
|
152
|
-
if (optionIndex === -1) {
|
|
153
|
-
promptParts.push(...rest);
|
|
154
|
-
}
|
|
155
|
-
else {
|
|
156
|
-
promptParts.push(...rest.slice(0, optionIndex));
|
|
157
|
-
forwardedArgs = rest.slice(optionIndex);
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
const prompt = promptParts.join(" ").trim();
|
|
161
|
-
if (prompt.length === 0) {
|
|
162
|
-
throw new Error("Claude Code requires a prompt argument (e.g. claude-code \"Write hello world\").");
|
|
163
|
-
}
|
|
164
|
-
const result = await spawnClaudeCode({
|
|
165
|
-
prompt,
|
|
166
|
-
args: forwardedArgs,
|
|
167
|
-
runCommand: (cmd, commandArgs) => this.runProcess(cmd, commandArgs)
|
|
168
|
-
});
|
|
169
|
-
if (result.exitCode !== 0) {
|
|
170
|
-
if (this.isNotFoundError(result)) {
|
|
171
|
-
throw new Error("Claude Code CLI is not installed or not available in the PATH. Run `poe-code configure claude-code` to install it.");
|
|
172
|
-
}
|
|
173
|
-
const detail = this.formatProcessOutput(result);
|
|
174
|
-
const suffix = detail.length > 0 ? ` Details: ${detail}` : "";
|
|
175
|
-
throw new Error(`Claude Code failed with exit code ${result.exitCode}.${suffix}`);
|
|
176
|
-
}
|
|
177
|
-
const output = this.formatProcessOutput(result);
|
|
178
|
-
return output.length > 0 ? output : "Claude Code command completed successfully";
|
|
179
|
-
}
|
|
180
|
-
async executeExternalCommand(executable, args) {
|
|
181
|
-
const result = await this.runProcess(executable, args);
|
|
182
|
-
if (result.exitCode !== 0) {
|
|
183
|
-
if (this.isNotFoundError(result)) {
|
|
184
|
-
throw new Error(`Command "${executable}" is not installed or not available in the PATH.`);
|
|
185
|
-
}
|
|
186
|
-
const detail = this.formatProcessOutput(result);
|
|
187
|
-
if (detail.length > 0) {
|
|
188
|
-
throw new Error(`Command "${executable}" exited with code ${result.exitCode}.\n${detail}`);
|
|
189
|
-
}
|
|
190
|
-
throw new Error(`Command "${executable}" exited with code ${result.exitCode}.`);
|
|
191
|
-
}
|
|
192
|
-
const output = this.formatProcessOutput(result);
|
|
193
|
-
return output.length > 0 ? output : "Command completed successfully";
|
|
194
|
-
}
|
|
195
|
-
async runProcess(command, args) {
|
|
196
|
-
return await new Promise((resolve) => {
|
|
197
|
-
let settled = false;
|
|
198
|
-
let stdout = "";
|
|
199
|
-
let stderr = "";
|
|
200
|
-
const child = spawn(command, args, {
|
|
201
|
-
cwd: this.cwd,
|
|
202
|
-
stdio: ["ignore", "pipe", "pipe"]
|
|
203
|
-
});
|
|
204
|
-
child.stdout?.setEncoding("utf8");
|
|
205
|
-
child.stdout?.on("data", (chunk) => {
|
|
206
|
-
stdout += chunk.toString();
|
|
207
|
-
});
|
|
208
|
-
child.stderr?.setEncoding("utf8");
|
|
209
|
-
child.stderr?.on("data", (chunk) => {
|
|
210
|
-
stderr += chunk.toString();
|
|
211
|
-
});
|
|
212
|
-
const finish = (result) => {
|
|
213
|
-
if (settled) {
|
|
214
|
-
return;
|
|
215
|
-
}
|
|
216
|
-
settled = true;
|
|
217
|
-
resolve(result);
|
|
218
|
-
};
|
|
219
|
-
child.on("error", (error) => {
|
|
220
|
-
const exitCode = typeof error.code === "number"
|
|
221
|
-
? error.code
|
|
222
|
-
: typeof error.errno === "number"
|
|
223
|
-
? error.errno
|
|
224
|
-
: 127;
|
|
225
|
-
const message = error instanceof Error ? error.message : String(error ?? "error");
|
|
226
|
-
const combinedStderr = stderr.length > 0 ? `${stderr}${stderr.endsWith("\n") ? "" : "\n"}${message}` : message;
|
|
227
|
-
finish({
|
|
228
|
-
stdout,
|
|
229
|
-
stderr: combinedStderr,
|
|
230
|
-
exitCode
|
|
231
|
-
});
|
|
232
|
-
});
|
|
233
|
-
child.on("close", (code) => {
|
|
234
|
-
finish({
|
|
235
|
-
stdout,
|
|
236
|
-
stderr,
|
|
237
|
-
exitCode: code ?? 0
|
|
238
|
-
});
|
|
239
|
-
});
|
|
240
|
-
});
|
|
241
|
-
}
|
|
242
|
-
formatProcessOutput(result) {
|
|
243
|
-
const stdout = result.stdout.trim();
|
|
244
|
-
const stderr = result.stderr.trim();
|
|
245
|
-
if (stdout.length > 0 && stderr.length > 0) {
|
|
246
|
-
return `${stdout}\n${stderr}`;
|
|
247
|
-
}
|
|
248
|
-
if (stdout.length > 0) {
|
|
249
|
-
return stdout;
|
|
250
|
-
}
|
|
251
|
-
if (stderr.length > 0) {
|
|
252
|
-
return stderr;
|
|
253
|
-
}
|
|
254
|
-
return "";
|
|
255
|
-
}
|
|
256
|
-
isNotFoundError(result) {
|
|
257
|
-
const stderrLower = result.stderr.toLowerCase();
|
|
258
|
-
if (stderrLower.includes("enoent")) {
|
|
259
|
-
return true;
|
|
260
|
-
}
|
|
261
|
-
if (stderrLower.includes("not found")) {
|
|
262
|
-
return true;
|
|
263
|
-
}
|
|
264
|
-
return result.exitCode === 127;
|
|
265
|
-
}
|
|
266
|
-
async searchWeb(args) {
|
|
267
|
-
const query = args.query;
|
|
268
|
-
if (!query) {
|
|
269
|
-
throw new Error("Missing required parameter: query");
|
|
270
|
-
}
|
|
271
|
-
// Placeholder for web search - in a real implementation, you'd integrate with a search API
|
|
272
|
-
return `Web search functionality not yet implemented. Query: ${query}`;
|
|
273
|
-
}
|
|
274
|
-
async spawnGitWorktreeTool(args) {
|
|
275
|
-
const parsed = this.parseWorktreeArgs(args);
|
|
276
|
-
const adapter = await this.resolveAgent(parsed.agent);
|
|
277
|
-
const serializableArgs = {
|
|
278
|
-
agent: parsed.agent,
|
|
279
|
-
prompt: parsed.prompt,
|
|
280
|
-
agentArgs: parsed.agentArgs
|
|
281
|
-
};
|
|
282
|
-
if (parsed.branch) {
|
|
283
|
-
serializableArgs.branch = parsed.branch;
|
|
284
|
-
}
|
|
285
|
-
if (parsed.runAsync) {
|
|
286
|
-
serializableArgs.async = true;
|
|
287
|
-
}
|
|
288
|
-
if (parsed.runAsync && this.taskRegistry && this.spawnTask) {
|
|
289
|
-
const taskId = this.taskRegistry.registerTask({
|
|
290
|
-
toolName: "spawn_git_worktree",
|
|
291
|
-
args: serializableArgs
|
|
292
|
-
});
|
|
293
|
-
await Promise.resolve(this.spawnTask({
|
|
294
|
-
taskId,
|
|
295
|
-
toolName: "spawn_git_worktree",
|
|
296
|
-
args: serializableArgs,
|
|
297
|
-
context: { cwd: this.cwd }
|
|
298
|
-
}));
|
|
299
|
-
this.eventLogger("task_queued", {
|
|
300
|
-
id: taskId,
|
|
301
|
-
tool: "spawn_git_worktree"
|
|
302
|
-
});
|
|
303
|
-
return `Started background task ${taskId}`;
|
|
304
|
-
}
|
|
305
|
-
return await this.executeWorktreeSynchronously(parsed, adapter);
|
|
306
|
-
}
|
|
307
|
-
createBackgroundSpawner() {
|
|
308
|
-
return (request) => {
|
|
309
|
-
if (!this.taskRegistry) {
|
|
310
|
-
return;
|
|
311
|
-
}
|
|
312
|
-
// Build human-readable CLI command
|
|
313
|
-
const commandParts = ["spawn-git-worktree"];
|
|
314
|
-
if (request.args.agent) {
|
|
315
|
-
commandParts.push(String(request.args.agent));
|
|
316
|
-
}
|
|
317
|
-
if (request.args.prompt) {
|
|
318
|
-
commandParts.push(`"${request.args.prompt}"`);
|
|
319
|
-
}
|
|
320
|
-
if (Array.isArray(request.args.agentArgs) && request.args.agentArgs.length > 0) {
|
|
321
|
-
commandParts.push(...request.args.agentArgs.map(String));
|
|
322
|
-
}
|
|
323
|
-
if (request.args.branch) {
|
|
324
|
-
commandParts.push(`--branch ${request.args.branch}`);
|
|
325
|
-
}
|
|
326
|
-
const commandString = commandParts.join(" ");
|
|
327
|
-
// Create inline script that imports and runs the task
|
|
328
|
-
const taskData = JSON.stringify({
|
|
329
|
-
taskId: request.taskId,
|
|
330
|
-
toolName: request.toolName,
|
|
331
|
-
args: request.args,
|
|
332
|
-
cwd: request.context.cwd,
|
|
333
|
-
tasksDir: this.taskRegistry.getTasksDirectory(),
|
|
334
|
-
logsDir: this.taskRegistry.getLogsDirectory(),
|
|
335
|
-
agentConfigPath: this.agentConfigManager?.getConfigPath() ?? null,
|
|
336
|
-
homeDir: this.homeDir ?? null
|
|
337
|
-
});
|
|
338
|
-
const inlineScript = `
|
|
339
|
-
import { spawnGitWorktree } from './commands/spawn-worktree.js';
|
|
340
|
-
import { createDefaultAgentRegistry } from './services/agent-registry.js';
|
|
341
|
-
import { AgentConfigManager } from './services/agent-config-manager.js';
|
|
342
|
-
import { AgentTaskRegistry } from './services/agent-task-registry.js';
|
|
343
|
-
import { TaskLogger } from './services/task-logger.js';
|
|
344
|
-
import { simpleGit } from 'simple-git';
|
|
345
|
-
import { spawn } from 'node:child_process';
|
|
346
|
-
import * as fs from 'node:fs';
|
|
347
|
-
import path from 'node:path';
|
|
348
|
-
|
|
349
|
-
const data = ${taskData};
|
|
350
|
-
const fsLike = fs;
|
|
351
|
-
|
|
352
|
-
const taskRegistry = new AgentTaskRegistry({
|
|
353
|
-
fs: fsLike,
|
|
354
|
-
tasksDir: data.tasksDir,
|
|
355
|
-
logsDir: data.logsDir
|
|
356
|
-
});
|
|
357
|
-
|
|
358
|
-
const logger = new TaskLogger({
|
|
359
|
-
fs: fsLike,
|
|
360
|
-
filePath: path.join(data.logsDir, data.taskId + '.log'),
|
|
361
|
-
now: () => new Date()
|
|
362
|
-
});
|
|
363
|
-
|
|
364
|
-
const progressFile = path.join(data.tasksDir, data.taskId + '.progress.jsonl');
|
|
365
|
-
const writeProgress = (update) => {
|
|
366
|
-
fs.appendFileSync(progressFile, JSON.stringify(update) + '\\n');
|
|
367
|
-
};
|
|
368
|
-
|
|
369
|
-
const agentRegistry = createDefaultAgentRegistry();
|
|
370
|
-
let agentConfigManager = null;
|
|
371
|
-
if (data.agentConfigPath && data.homeDir) {
|
|
372
|
-
agentConfigManager = new AgentConfigManager({
|
|
373
|
-
fs: fs.promises,
|
|
374
|
-
homeDir: data.homeDir,
|
|
375
|
-
registry: agentRegistry
|
|
376
|
-
});
|
|
377
|
-
await agentConfigManager.loadConfig();
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
async function resolveAgent(adapterId) {
|
|
381
|
-
const adapter = agentRegistry.get(adapterId);
|
|
382
|
-
if (!adapter) {
|
|
383
|
-
throw new Error('Unsupported agent "' + adapterId + '".');
|
|
384
|
-
}
|
|
385
|
-
if (agentConfigManager) {
|
|
386
|
-
const enabled = await agentConfigManager.getEnabledAgents();
|
|
387
|
-
if (!enabled.some((entry) => entry.id === adapterId)) {
|
|
388
|
-
throw new Error('Agent "' + adapterId + '" is disabled in configuration.');
|
|
389
|
-
}
|
|
390
|
-
}
|
|
391
|
-
return adapter;
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
async function runCommand(cmd, args, cwd) {
|
|
395
|
-
return new Promise((resolve) => {
|
|
396
|
-
const child = spawn(cmd, args, { cwd, stdio: ['ignore', 'pipe', 'pipe'] });
|
|
397
|
-
let stdout = '', stderr = '';
|
|
398
|
-
child.stdout?.on('data', (d) => stdout += d);
|
|
399
|
-
child.stderr?.on('data', (d) => stderr += d);
|
|
400
|
-
child.on('close', (code) => resolve({ stdout, stderr, exitCode: code || 0 }));
|
|
401
|
-
});
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
let agentAdapter;
|
|
405
|
-
|
|
406
|
-
async function runAgent(details) {
|
|
407
|
-
if (!agentAdapter) {
|
|
408
|
-
agentAdapter = await resolveAgent(details.agent);
|
|
409
|
-
}
|
|
410
|
-
if (details.agent !== data.args.agent) {
|
|
411
|
-
throw new Error('Mismatched agent "' + details.agent + '" (expected "' + data.args.agent + '").');
|
|
412
|
-
}
|
|
413
|
-
return await agentAdapter.spawn({
|
|
414
|
-
prompt: details.prompt,
|
|
415
|
-
args: details.args,
|
|
416
|
-
runCommand: (c, a) => runCommand(c, a, details.cwd)
|
|
417
|
-
});
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
(async () => {
|
|
421
|
-
try {
|
|
422
|
-
logger.info('Starting ' + data.toolName);
|
|
423
|
-
writeProgress({ type: 'progress', message: 'Starting ' + data.toolName, timestamp: Date.now() });
|
|
424
|
-
|
|
425
|
-
agentAdapter = await resolveAgent(data.args.agent);
|
|
426
|
-
|
|
427
|
-
const git = simpleGit({ baseDir: data.cwd });
|
|
428
|
-
const branch = data.args.branch || (await git.revparse(['--abbrev-ref', 'HEAD'])).trim();
|
|
429
|
-
|
|
430
|
-
await spawnGitWorktree({
|
|
431
|
-
agent: data.args.agent,
|
|
432
|
-
prompt: data.args.prompt,
|
|
433
|
-
agentArgs: data.args.agentArgs || [],
|
|
434
|
-
basePath: data.cwd,
|
|
435
|
-
targetBranch: branch,
|
|
436
|
-
runAgent,
|
|
437
|
-
logger: (msg) => {
|
|
438
|
-
logger.info(msg);
|
|
439
|
-
writeProgress({ type: 'progress', message: msg, timestamp: Date.now() });
|
|
440
|
-
}
|
|
441
|
-
});
|
|
442
|
-
|
|
443
|
-
const result = 'Worktree workflow completed successfully';
|
|
444
|
-
taskRegistry.updateTask(data.taskId, { status: 'completed', result, endTime: Date.now() });
|
|
445
|
-
writeProgress({ type: 'complete', result, timestamp: Date.now() });
|
|
446
|
-
logger.info('Task completed');
|
|
447
|
-
} catch (error) {
|
|
448
|
-
const message = error?.message || String(error);
|
|
449
|
-
taskRegistry.updateTask(data.taskId, { status: 'failed', error: message, endTime: Date.now() });
|
|
450
|
-
writeProgress({ type: 'error', error: message, timestamp: Date.now() });
|
|
451
|
-
logger.error('Task failed: ' + message);
|
|
452
|
-
process.exit(1);
|
|
453
|
-
} finally {
|
|
454
|
-
taskRegistry.dispose();
|
|
455
|
-
}
|
|
456
|
-
})();
|
|
457
|
-
`.trim();
|
|
458
|
-
try {
|
|
459
|
-
// Spawn node with inline script
|
|
460
|
-
const child = spawn(process.execPath, ['--input-type=module', '-e', inlineScript], {
|
|
461
|
-
cwd: path.join(fileURLToPath(new URL('.', import.meta.url)), '..'),
|
|
462
|
-
detached: true,
|
|
463
|
-
stdio: ["ignore", "pipe", "pipe"], // Capture stdout/stderr for streaming
|
|
464
|
-
env: {
|
|
465
|
-
...process.env
|
|
466
|
-
}
|
|
467
|
-
});
|
|
468
|
-
// Capture stdout/stderr for logging and streaming
|
|
469
|
-
let stdoutData = "";
|
|
470
|
-
let stderrData = "";
|
|
471
|
-
if (child.stdout) {
|
|
472
|
-
child.stdout.on("data", (data) => {
|
|
473
|
-
const chunk = data.toString();
|
|
474
|
-
stdoutData += chunk;
|
|
475
|
-
this.eventLogger("task_stdout", {
|
|
476
|
-
id: request.taskId,
|
|
477
|
-
tool: request.toolName,
|
|
478
|
-
chunk
|
|
479
|
-
});
|
|
480
|
-
});
|
|
481
|
-
}
|
|
482
|
-
if (child.stderr) {
|
|
483
|
-
child.stderr.on("data", (data) => {
|
|
484
|
-
const chunk = data.toString();
|
|
485
|
-
stderrData += chunk;
|
|
486
|
-
this.eventLogger("task_stderr", {
|
|
487
|
-
id: request.taskId,
|
|
488
|
-
tool: request.toolName,
|
|
489
|
-
chunk
|
|
490
|
-
});
|
|
491
|
-
});
|
|
492
|
-
}
|
|
493
|
-
// Register error handler BEFORE unref to catch early errors
|
|
494
|
-
child.once("error", (error) => {
|
|
495
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
496
|
-
const parts = [message];
|
|
497
|
-
if (stdoutData) {
|
|
498
|
-
parts.push(`Stdout: ${stdoutData}`);
|
|
499
|
-
}
|
|
500
|
-
if (stderrData) {
|
|
501
|
-
parts.push(`Stderr: ${stderrData}`);
|
|
502
|
-
}
|
|
503
|
-
const fullError = parts.join("\n");
|
|
504
|
-
this.eventLogger("task_spawn_failed", {
|
|
505
|
-
id: request.taskId,
|
|
506
|
-
message: fullError
|
|
507
|
-
});
|
|
508
|
-
this.taskRegistry?.updateTask(request.taskId, {
|
|
509
|
-
status: "failed",
|
|
510
|
-
error: `Process error: ${fullError}`,
|
|
511
|
-
endTime: this.now()
|
|
512
|
-
});
|
|
513
|
-
});
|
|
514
|
-
// Also capture exit with non-zero code
|
|
515
|
-
child.once("exit", (code, signal) => {
|
|
516
|
-
if (code !== null && code !== 0) {
|
|
517
|
-
const details = [`Process exited with code ${code}`];
|
|
518
|
-
if (stdoutData) {
|
|
519
|
-
details.push(`Stdout: ${stdoutData}`);
|
|
520
|
-
}
|
|
521
|
-
if (stderrData) {
|
|
522
|
-
details.push(`Stderr: ${stderrData}`);
|
|
523
|
-
}
|
|
524
|
-
const exitError = details.join("\n");
|
|
525
|
-
this.eventLogger("task_exit_error", {
|
|
526
|
-
id: request.taskId,
|
|
527
|
-
code,
|
|
528
|
-
signal,
|
|
529
|
-
stdout: stdoutData,
|
|
530
|
-
stderr: stderrData
|
|
531
|
-
});
|
|
532
|
-
this.taskRegistry?.updateTask(request.taskId, {
|
|
533
|
-
status: "failed",
|
|
534
|
-
error: exitError,
|
|
535
|
-
endTime: this.now()
|
|
536
|
-
});
|
|
537
|
-
}
|
|
538
|
-
});
|
|
539
|
-
child.unref();
|
|
540
|
-
if (typeof child.pid === "number") {
|
|
541
|
-
this.taskRegistry.updateTask(request.taskId, {
|
|
542
|
-
pid: child.pid,
|
|
543
|
-
command: commandString
|
|
544
|
-
});
|
|
545
|
-
this.eventLogger("task_spawned", {
|
|
546
|
-
id: request.taskId,
|
|
547
|
-
tool: request.toolName,
|
|
548
|
-
pid: child.pid,
|
|
549
|
-
command: commandString
|
|
550
|
-
});
|
|
551
|
-
}
|
|
552
|
-
else {
|
|
553
|
-
// No PID means spawn failed
|
|
554
|
-
this.eventLogger("task_spawn_no_pid", {
|
|
555
|
-
id: request.taskId
|
|
556
|
-
});
|
|
557
|
-
this.taskRegistry.updateTask(request.taskId, {
|
|
558
|
-
status: "failed",
|
|
559
|
-
error: "Failed to spawn process (no PID)",
|
|
560
|
-
endTime: this.now()
|
|
561
|
-
});
|
|
562
|
-
}
|
|
563
|
-
}
|
|
564
|
-
catch (error) {
|
|
565
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
566
|
-
this.eventLogger("task_spawn_error", {
|
|
567
|
-
id: request.taskId,
|
|
568
|
-
message
|
|
569
|
-
});
|
|
570
|
-
this.taskRegistry.updateTask(request.taskId, {
|
|
571
|
-
status: "failed",
|
|
572
|
-
error: `Spawn error: ${message}`,
|
|
573
|
-
endTime: this.now()
|
|
574
|
-
});
|
|
575
|
-
}
|
|
576
|
-
};
|
|
577
|
-
}
|
|
578
|
-
async executeWorktreeSynchronously(input, adapter) {
|
|
579
|
-
const git = createSimpleGit({ baseDir: this.cwd });
|
|
580
|
-
const branch = input.branch
|
|
581
|
-
? input.branch
|
|
582
|
-
: (await git.revparse(["--abbrev-ref", "HEAD"])).trim();
|
|
583
|
-
const logs = [];
|
|
584
|
-
const runner = async (command, commandArgs) => runCommandInCwd(command, commandArgs, this.cwd);
|
|
585
|
-
const runAgent = async (details) => {
|
|
586
|
-
if (details.agent !== input.agent) {
|
|
587
|
-
throw new Error(`Mismatched agent "${details.agent}" (expected "${input.agent}").`);
|
|
588
|
-
}
|
|
589
|
-
return await adapter.spawn({
|
|
590
|
-
prompt: details.prompt,
|
|
591
|
-
args: details.args,
|
|
592
|
-
runCommand: runner
|
|
593
|
-
});
|
|
594
|
-
};
|
|
595
|
-
await spawnGitWorktree({
|
|
596
|
-
agent: input.agent,
|
|
597
|
-
prompt: input.prompt,
|
|
598
|
-
agentArgs: input.agentArgs,
|
|
599
|
-
basePath: this.cwd,
|
|
600
|
-
targetBranch: branch,
|
|
601
|
-
runAgent,
|
|
602
|
-
logger: (message) => {
|
|
603
|
-
logs.push(message);
|
|
604
|
-
}
|
|
605
|
-
});
|
|
606
|
-
if (logs.length === 0) {
|
|
607
|
-
logs.push("Worktree workflow completed.");
|
|
608
|
-
}
|
|
609
|
-
return logs.join("\n");
|
|
610
|
-
}
|
|
611
|
-
async resolveAgent(agentId) {
|
|
612
|
-
const adapter = this.agentRegistry.get(agentId);
|
|
613
|
-
if (!adapter) {
|
|
614
|
-
throw new Error(`Unsupported agent "${agentId}".`);
|
|
615
|
-
}
|
|
616
|
-
if (this.agentConfigManager) {
|
|
617
|
-
const enabled = await this.agentConfigManager.getEnabledAgents();
|
|
618
|
-
if (!enabled.some((entry) => entry.id === agentId)) {
|
|
619
|
-
throw new Error(`Agent "${agentId}" is disabled in configuration.`);
|
|
620
|
-
}
|
|
621
|
-
}
|
|
622
|
-
else if (!LEGACY_DEFAULT_AGENTS.some((legacy) => legacy === agentId)) {
|
|
623
|
-
throw new Error(`Unsupported agent "${agentId}".`);
|
|
624
|
-
}
|
|
625
|
-
return adapter;
|
|
626
|
-
}
|
|
627
|
-
parseWorktreeArgs(args) {
|
|
628
|
-
const agentValue = args.agent;
|
|
629
|
-
if (typeof agentValue !== "string" || agentValue.length === 0) {
|
|
630
|
-
throw new Error("Missing required parameter: agent");
|
|
631
|
-
}
|
|
632
|
-
const promptValue = args.prompt;
|
|
633
|
-
if (typeof promptValue !== "string" || promptValue.length === 0) {
|
|
634
|
-
throw new Error("Missing required parameter: prompt");
|
|
635
|
-
}
|
|
636
|
-
const agentArgsValue = args.agentArgs;
|
|
637
|
-
const agentArgs = Array.isArray(agentArgsValue)
|
|
638
|
-
? agentArgsValue.map((entry) => String(entry))
|
|
639
|
-
: [];
|
|
640
|
-
const branchValue = typeof args.branch === "string" && args.branch.length > 0
|
|
641
|
-
? args.branch
|
|
642
|
-
: undefined;
|
|
643
|
-
const asyncValue = args.async;
|
|
644
|
-
let runAsync = false;
|
|
645
|
-
if (typeof asyncValue === "boolean") {
|
|
646
|
-
runAsync = asyncValue;
|
|
647
|
-
}
|
|
648
|
-
else if (typeof asyncValue === "string") {
|
|
649
|
-
const normalized = asyncValue.trim().toLowerCase();
|
|
650
|
-
if (normalized === "true") {
|
|
651
|
-
runAsync = true;
|
|
652
|
-
}
|
|
653
|
-
else if (normalized === "false" || normalized.length === 0) {
|
|
654
|
-
runAsync = false;
|
|
655
|
-
}
|
|
656
|
-
else {
|
|
657
|
-
throw new Error(`Invalid async option "${asyncValue}". Expected boolean, "true", or "false".`);
|
|
658
|
-
}
|
|
659
|
-
}
|
|
660
|
-
else if (asyncValue !== undefined) {
|
|
661
|
-
throw new Error(`Invalid async option type "${typeof asyncValue}". Expected boolean or string.`);
|
|
662
|
-
}
|
|
663
|
-
return {
|
|
664
|
-
agent: agentValue,
|
|
665
|
-
prompt: promptValue,
|
|
666
|
-
agentArgs,
|
|
667
|
-
branch: branchValue,
|
|
668
|
-
runAsync
|
|
669
|
-
};
|
|
670
|
-
}
|
|
671
|
-
async tryReadFile(targetPath) {
|
|
672
|
-
try {
|
|
673
|
-
return await this.fs.readFile(targetPath, "utf8");
|
|
674
|
-
}
|
|
675
|
-
catch (error) {
|
|
676
|
-
if (error &&
|
|
677
|
-
typeof error === "object" &&
|
|
678
|
-
"code" in error &&
|
|
679
|
-
error.code === "ENOENT") {
|
|
680
|
-
return null;
|
|
681
|
-
}
|
|
682
|
-
throw error;
|
|
683
|
-
}
|
|
684
|
-
}
|
|
685
|
-
}
|
|
686
|
-
function runCommandInCwd(command, args, cwd) {
|
|
687
|
-
return new Promise((resolve) => {
|
|
688
|
-
const child = spawn(command, args, {
|
|
689
|
-
cwd,
|
|
690
|
-
stdio: ["ignore", "pipe", "pipe"]
|
|
691
|
-
});
|
|
692
|
-
let stdout = "";
|
|
693
|
-
let stderr = "";
|
|
694
|
-
child.stdout?.setEncoding("utf8");
|
|
695
|
-
child.stdout?.on("data", (chunk) => {
|
|
696
|
-
stdout += chunk.toString();
|
|
697
|
-
});
|
|
698
|
-
child.stderr?.setEncoding("utf8");
|
|
699
|
-
child.stderr?.on("data", (chunk) => {
|
|
700
|
-
stderr += chunk.toString();
|
|
701
|
-
});
|
|
702
|
-
child.once("error", (error) => {
|
|
703
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
704
|
-
const exitCode = typeof error.code === "number"
|
|
705
|
-
? error.code
|
|
706
|
-
: Number.isInteger(Number(error.code))
|
|
707
|
-
? Number(error.code)
|
|
708
|
-
: 127;
|
|
709
|
-
resolve({
|
|
710
|
-
stdout,
|
|
711
|
-
stderr: stderr ? `${stderr}${message}` : message,
|
|
712
|
-
exitCode
|
|
713
|
-
});
|
|
714
|
-
});
|
|
715
|
-
child.once("close", (code) => {
|
|
716
|
-
resolve({
|
|
717
|
-
stdout,
|
|
718
|
-
stderr,
|
|
719
|
-
exitCode: typeof code === "number" ? code : 0
|
|
720
|
-
});
|
|
721
|
-
});
|
|
722
|
-
});
|
|
723
|
-
}
|
|
724
|
-
export async function getAvailableTools(options = {}) {
|
|
725
|
-
const registry = options.agentRegistry ?? createDefaultAgentRegistry();
|
|
726
|
-
let enabledAgents = registry
|
|
727
|
-
.list()
|
|
728
|
-
.filter((adapter) => adapter.defaultEnabled ?? LEGACY_DEFAULT_AGENTS.some((legacy) => legacy === adapter.id))
|
|
729
|
-
.map((adapter) => ({ id: adapter.id }));
|
|
730
|
-
if (options.agentConfigManager) {
|
|
731
|
-
enabledAgents = await options.agentConfigManager.getEnabledAgents();
|
|
732
|
-
}
|
|
733
|
-
const enabledIds = enabledAgents.map((entry) => entry.id);
|
|
734
|
-
const fallbackIds = registry.list().map((adapter) => adapter.id);
|
|
735
|
-
const enumValues = enabledIds.length > 0 ? enabledIds : fallbackIds;
|
|
736
|
-
const agentDescription = enumValues.length > 0
|
|
737
|
-
? `Agent identifier (${enumValues.join(" | ")}).`
|
|
738
|
-
: "Agent identifier.";
|
|
739
|
-
const builtInTools = [
|
|
740
|
-
{
|
|
741
|
-
type: "function",
|
|
742
|
-
function: {
|
|
743
|
-
name: "read_file",
|
|
744
|
-
description: "Read the contents of a file in the current working directory. Use this for reading project files. Supports relative paths (e.g., 'package.json', 'src/index.ts') and absolute paths.",
|
|
745
|
-
parameters: {
|
|
746
|
-
type: "object",
|
|
747
|
-
properties: {
|
|
748
|
-
path: {
|
|
749
|
-
type: "string",
|
|
750
|
-
description: "The file path to read. Can be relative to the current working directory or absolute."
|
|
751
|
-
}
|
|
752
|
-
},
|
|
753
|
-
required: ["path"]
|
|
754
|
-
}
|
|
755
|
-
}
|
|
756
|
-
},
|
|
757
|
-
{
|
|
758
|
-
type: "function",
|
|
759
|
-
function: {
|
|
760
|
-
name: "write_file",
|
|
761
|
-
description: "Write or create a file in the current working directory. Use this for creating or updating project files. Supports relative and absolute paths.",
|
|
762
|
-
parameters: {
|
|
763
|
-
type: "object",
|
|
764
|
-
properties: {
|
|
765
|
-
path: {
|
|
766
|
-
type: "string",
|
|
767
|
-
description: "The file path to write. Can be relative to the current working directory or absolute."
|
|
768
|
-
},
|
|
769
|
-
content: {
|
|
770
|
-
type: "string",
|
|
771
|
-
description: "The content to write to the file"
|
|
772
|
-
}
|
|
773
|
-
},
|
|
774
|
-
required: ["path", "content"]
|
|
775
|
-
}
|
|
776
|
-
}
|
|
777
|
-
},
|
|
778
|
-
{
|
|
779
|
-
type: "function",
|
|
780
|
-
function: {
|
|
781
|
-
name: "list_files",
|
|
782
|
-
description: "List files and directories in the current working directory or a specified directory. Use this to explore the project structure.",
|
|
783
|
-
parameters: {
|
|
784
|
-
type: "object",
|
|
785
|
-
properties: {
|
|
786
|
-
path: {
|
|
787
|
-
type: "string",
|
|
788
|
-
description: "The directory path to list. Defaults to current working directory if not specified. Can be relative or absolute."
|
|
789
|
-
}
|
|
790
|
-
}
|
|
791
|
-
}
|
|
792
|
-
}
|
|
793
|
-
},
|
|
794
|
-
{
|
|
795
|
-
type: "function",
|
|
796
|
-
function: {
|
|
797
|
-
name: "run_command",
|
|
798
|
-
description: "Run a shell command in the current directory",
|
|
799
|
-
parameters: {
|
|
800
|
-
type: "object",
|
|
801
|
-
properties: {
|
|
802
|
-
command: {
|
|
803
|
-
type: "string",
|
|
804
|
-
description: "The shell command to run"
|
|
805
|
-
}
|
|
806
|
-
},
|
|
807
|
-
required: ["command"]
|
|
808
|
-
}
|
|
809
|
-
}
|
|
810
|
-
},
|
|
811
|
-
{
|
|
812
|
-
type: "function",
|
|
813
|
-
function: {
|
|
814
|
-
name: "spawn_git_worktree",
|
|
815
|
-
description: "Create a git worktree, run an agent, and attempt to merge the resulting changes.",
|
|
816
|
-
parameters: {
|
|
817
|
-
type: "object",
|
|
818
|
-
properties: {
|
|
819
|
-
agent: {
|
|
820
|
-
type: "string",
|
|
821
|
-
description: agentDescription,
|
|
822
|
-
enum: enumValues
|
|
823
|
-
},
|
|
824
|
-
prompt: {
|
|
825
|
-
type: "string",
|
|
826
|
-
description: "Prompt text to provide to the agent."
|
|
827
|
-
},
|
|
828
|
-
agentArgs: {
|
|
829
|
-
type: "array",
|
|
830
|
-
description: "Additional arguments forwarded to the agent CLI.",
|
|
831
|
-
items: {
|
|
832
|
-
type: "string"
|
|
833
|
-
},
|
|
834
|
-
default: []
|
|
835
|
-
},
|
|
836
|
-
branch: {
|
|
837
|
-
type: "string",
|
|
838
|
-
description: "Target branch to merge into. Defaults to the current branch."
|
|
839
|
-
}
|
|
840
|
-
},
|
|
841
|
-
required: ["agent", "prompt"]
|
|
842
|
-
}
|
|
843
|
-
}
|
|
844
|
-
},
|
|
845
|
-
{
|
|
846
|
-
type: "function",
|
|
847
|
-
function: {
|
|
848
|
-
name: "search_web",
|
|
849
|
-
description: "Search the web for information",
|
|
850
|
-
parameters: {
|
|
851
|
-
type: "object",
|
|
852
|
-
properties: {
|
|
853
|
-
query: {
|
|
854
|
-
type: "string",
|
|
855
|
-
description: "The search query"
|
|
856
|
-
}
|
|
857
|
-
},
|
|
858
|
-
required: ["query"]
|
|
859
|
-
}
|
|
860
|
-
}
|
|
861
|
-
}
|
|
862
|
-
];
|
|
863
|
-
// Add MCP tools if manager is provided
|
|
864
|
-
if (options.mcpManager) {
|
|
865
|
-
const mcpTools = options.mcpManager.getAllTools();
|
|
866
|
-
return [...builtInTools, ...mcpTools];
|
|
867
|
-
}
|
|
868
|
-
return builtInTools;
|
|
869
|
-
}
|
|
870
|
-
//# sourceMappingURL=tools.js.map
|