ai-code-agents 0.1.0 → 0.2.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 +15 -16
- package/dist/index.cjs +687 -633
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +256 -575
- package/dist/index.d.ts +256 -575
- package/dist/index.js +751 -648
- package/dist/index.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +21 -6
package/dist/index.js
CHANGED
|
@@ -1,13 +1,9 @@
|
|
|
1
1
|
// src/environments/docker-environment.ts
|
|
2
2
|
import { exec } from "child_process";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
return "''";
|
|
8
|
-
}
|
|
9
|
-
return `'${arg.replace(/'/g, "'\\''")}'`;
|
|
10
|
-
}
|
|
3
|
+
import {
|
|
4
|
+
UnixEnvironmentBase,
|
|
5
|
+
escapeCommandArg
|
|
6
|
+
} from "@ai-code-agents/environment-utils";
|
|
11
7
|
|
|
12
8
|
// src/util/escape-command.ts
|
|
13
9
|
function escapeCommand(command) {
|
|
@@ -15,278 +11,6 @@ function escapeCommand(command) {
|
|
|
15
11
|
return `"${escaped}"`;
|
|
16
12
|
}
|
|
17
13
|
|
|
18
|
-
// src/util/validate-relative-path.ts
|
|
19
|
-
import * as path from "path";
|
|
20
|
-
function validateRelativePath(filePath) {
|
|
21
|
-
if (path.isAbsolute(filePath)) {
|
|
22
|
-
throw new Error("Absolute paths are not allowed.");
|
|
23
|
-
}
|
|
24
|
-
if (filePath.startsWith("~")) {
|
|
25
|
-
throw new Error('Paths starting with "~" are not allowed.');
|
|
26
|
-
}
|
|
27
|
-
if (filePath.includes("\0")) {
|
|
28
|
-
throw new Error("Paths must not contain null bytes.");
|
|
29
|
-
}
|
|
30
|
-
const normalizedPath = path.normalize(filePath);
|
|
31
|
-
if (normalizedPath.startsWith("..")) {
|
|
32
|
-
throw new Error("Path traversal is not allowed.");
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
// src/environments/filesystem-environment-base.ts
|
|
37
|
-
var FilesystemEnvironmentBase = class {
|
|
38
|
-
_envConfig;
|
|
39
|
-
/**
|
|
40
|
-
* Constructs a new environment instance.
|
|
41
|
-
*
|
|
42
|
-
* @param config - Environment configuration.
|
|
43
|
-
*/
|
|
44
|
-
constructor(config) {
|
|
45
|
-
this._envConfig = config;
|
|
46
|
-
}
|
|
47
|
-
/**
|
|
48
|
-
* Reads the content of a file at the specified path.
|
|
49
|
-
*
|
|
50
|
-
* @param path - The path to the file to read, relative to the project directory.
|
|
51
|
-
* @returns A promise that resolves to a ReadFileResult.
|
|
52
|
-
*/
|
|
53
|
-
async readFile(path5) {
|
|
54
|
-
validateRelativePath(path5);
|
|
55
|
-
if (!await this.fileExists(path5)) {
|
|
56
|
-
throw new Error(`File not found: ${path5}`);
|
|
57
|
-
}
|
|
58
|
-
const content = await this.readFileContent(path5);
|
|
59
|
-
return {
|
|
60
|
-
path: path5,
|
|
61
|
-
content
|
|
62
|
-
};
|
|
63
|
-
}
|
|
64
|
-
/**
|
|
65
|
-
* Writes content to a file at the specified path.
|
|
66
|
-
*
|
|
67
|
-
* If a file is already present at the path, it will be overwritten.
|
|
68
|
-
*
|
|
69
|
-
* @param path - The path to the file to write, relative to the project directory.
|
|
70
|
-
* @param content - The content to write to the file.
|
|
71
|
-
* @returns A promise that resolves to a WriteFileResult.
|
|
72
|
-
*/
|
|
73
|
-
async writeFile(path5, content) {
|
|
74
|
-
validateRelativePath(path5);
|
|
75
|
-
await this.writeFileContent(path5, content);
|
|
76
|
-
return {
|
|
77
|
-
path: path5,
|
|
78
|
-
message: "File written successfully."
|
|
79
|
-
};
|
|
80
|
-
}
|
|
81
|
-
/**
|
|
82
|
-
* Deletes a file at the specified path.
|
|
83
|
-
*
|
|
84
|
-
* @param path - The path to the file to delete, relative to the project directory.
|
|
85
|
-
* @returns A promise that resolves to a DeleteFileResult.
|
|
86
|
-
*/
|
|
87
|
-
async deleteFile(path5) {
|
|
88
|
-
validateRelativePath(path5);
|
|
89
|
-
if (!await this.fileExists(path5)) {
|
|
90
|
-
return {
|
|
91
|
-
path: path5,
|
|
92
|
-
message: "File was already deleted."
|
|
93
|
-
};
|
|
94
|
-
}
|
|
95
|
-
await this.deleteFileContent(path5);
|
|
96
|
-
return {
|
|
97
|
-
path: path5,
|
|
98
|
-
message: "File deleted successfully."
|
|
99
|
-
};
|
|
100
|
-
}
|
|
101
|
-
/**
|
|
102
|
-
* Moves a file from a source path to a destination path.
|
|
103
|
-
*
|
|
104
|
-
* If a file is already present at the destination path, it will be overwritten.
|
|
105
|
-
*
|
|
106
|
-
* @param sourcePath - The path to the file to move.
|
|
107
|
-
* @param destinationPath - The path to move the file to.
|
|
108
|
-
* @returns A promise that resolves to a MoveFileResult.
|
|
109
|
-
*/
|
|
110
|
-
async moveFile(sourcePath, destinationPath) {
|
|
111
|
-
validateRelativePath(sourcePath);
|
|
112
|
-
validateRelativePath(destinationPath);
|
|
113
|
-
if (!await this.fileExists(sourcePath)) {
|
|
114
|
-
throw new Error(`File not found: ${sourcePath}`);
|
|
115
|
-
}
|
|
116
|
-
await this.moveFileContent(sourcePath, destinationPath);
|
|
117
|
-
return {
|
|
118
|
-
sourcePath,
|
|
119
|
-
destinationPath,
|
|
120
|
-
message: "File moved successfully."
|
|
121
|
-
};
|
|
122
|
-
}
|
|
123
|
-
/**
|
|
124
|
-
* Copies a file from a source path to a destination path.
|
|
125
|
-
*
|
|
126
|
-
* If a file is already present at the destination path, it will be overwritten.
|
|
127
|
-
*
|
|
128
|
-
* @param sourcePath - The path to the file to copy.
|
|
129
|
-
* @param destinationPath - The path to copy the file to.
|
|
130
|
-
* @returns A promise that resolves to a CopyFileResult.
|
|
131
|
-
*/
|
|
132
|
-
async copyFile(sourcePath, destinationPath) {
|
|
133
|
-
validateRelativePath(sourcePath);
|
|
134
|
-
validateRelativePath(destinationPath);
|
|
135
|
-
if (!await this.fileExists(sourcePath)) {
|
|
136
|
-
throw new Error(`File not found: ${sourcePath}`);
|
|
137
|
-
}
|
|
138
|
-
await this.copyFileContent(sourcePath, destinationPath);
|
|
139
|
-
return {
|
|
140
|
-
sourcePath,
|
|
141
|
-
destinationPath,
|
|
142
|
-
message: "File copied successfully."
|
|
143
|
-
};
|
|
144
|
-
}
|
|
145
|
-
/**
|
|
146
|
-
* Moves the content of a file from a source path to a destination path, relative to the project directory.
|
|
147
|
-
*
|
|
148
|
-
* When this method is called, it is guaranteed that the source file exists.
|
|
149
|
-
* This method unconditionally moves the content, even if a file already exists at the destination path.
|
|
150
|
-
*
|
|
151
|
-
* @param relativeSourcePath - The path to the file to move, relative to the project directory.
|
|
152
|
-
* @param relativeDestinationPath - The path to move the file to, relative to the project directory.
|
|
153
|
-
*/
|
|
154
|
-
async moveFileContent(relativeSourcePath, relativeDestinationPath) {
|
|
155
|
-
const content = await this.readFileContent(relativeSourcePath);
|
|
156
|
-
this.writeFileContent(relativeDestinationPath, content);
|
|
157
|
-
this.deleteFileContent(relativeSourcePath);
|
|
158
|
-
}
|
|
159
|
-
/**
|
|
160
|
-
* Copies the content of a file from a source path to a destination path, relative to the project directory.
|
|
161
|
-
*
|
|
162
|
-
* When this method is called, it is guaranteed that the source file exists.
|
|
163
|
-
* This method unconditionally copies the content, even if a file already exists at the destination path.
|
|
164
|
-
*
|
|
165
|
-
* @param relativeSourcePath - The path to the file to copy, relative to the project directory.
|
|
166
|
-
* @param relativeDestinationPath - The path to copy the file to, relative to the project directory.
|
|
167
|
-
*/
|
|
168
|
-
async copyFileContent(relativeSourcePath, relativeDestinationPath) {
|
|
169
|
-
const content = await this.readFileContent(relativeSourcePath);
|
|
170
|
-
this.writeFileContent(relativeDestinationPath, content);
|
|
171
|
-
}
|
|
172
|
-
};
|
|
173
|
-
|
|
174
|
-
// src/environments/command-line-environment-base.ts
|
|
175
|
-
var CommandLineEnvironmentBase = class extends FilesystemEnvironmentBase {
|
|
176
|
-
/**
|
|
177
|
-
* Runs a CLI command in environment.
|
|
178
|
-
*
|
|
179
|
-
* @param command - The command to run.
|
|
180
|
-
* @returns A promise that resolves to a RunCommandResult.
|
|
181
|
-
*/
|
|
182
|
-
async runCommand(command) {
|
|
183
|
-
const [exitCode, stdout, stderr] = await this.executeCommand(command);
|
|
184
|
-
return {
|
|
185
|
-
command,
|
|
186
|
-
exitCode,
|
|
187
|
-
stdout,
|
|
188
|
-
stderr
|
|
189
|
-
};
|
|
190
|
-
}
|
|
191
|
-
};
|
|
192
|
-
|
|
193
|
-
// src/environments/unix-environment-base.ts
|
|
194
|
-
var UnixEnvironmentBase = class extends CommandLineEnvironmentBase {
|
|
195
|
-
/**
|
|
196
|
-
* Checks whether a file exists at the specified path relative to the project directory.
|
|
197
|
-
*
|
|
198
|
-
* @param relativePath - The path to the file to check, relative to the project directory.
|
|
199
|
-
* @returns True if the file exists, false otherwise.
|
|
200
|
-
*/
|
|
201
|
-
async fileExists(relativePath) {
|
|
202
|
-
const command = `if [ -e ${escapeCommandArg(relativePath)} ]; then echo "yes"; else echo "no"; fi`;
|
|
203
|
-
const { exitCode, stdout } = await this.runCommand(command);
|
|
204
|
-
return exitCode === 0 && stdout.trim() === "yes";
|
|
205
|
-
}
|
|
206
|
-
/**
|
|
207
|
-
* Gets the content of a file at the specified path, relative to the project directory.
|
|
208
|
-
*
|
|
209
|
-
* When this method is called, it is guaranteed that the file exists.
|
|
210
|
-
*
|
|
211
|
-
* @param relativePath - The path to the file to read, relative to the project directory.
|
|
212
|
-
* @returns The content of the file.
|
|
213
|
-
*/
|
|
214
|
-
async readFileContent(relativePath) {
|
|
215
|
-
const command = `cat ${escapeCommandArg(relativePath)}`;
|
|
216
|
-
const { exitCode, stdout } = await this.runCommand(command);
|
|
217
|
-
return exitCode === 0 ? stdout : "";
|
|
218
|
-
}
|
|
219
|
-
/**
|
|
220
|
-
* Writes content to a file at the specified path, relative to the project directory.
|
|
221
|
-
*
|
|
222
|
-
* This method unconditionally writes the content, even if a file already exists at the path, or if the file is new.
|
|
223
|
-
*
|
|
224
|
-
* @param relativePath - The path to the file to write, relative to the project directory.
|
|
225
|
-
* @param content - The content to write to the file.
|
|
226
|
-
*/
|
|
227
|
-
async writeFileContent(relativePath, content) {
|
|
228
|
-
const command = `sh -c "echo ${escapeCommandArg(
|
|
229
|
-
content
|
|
230
|
-
)} > ${escapeCommandArg(relativePath)}"`;
|
|
231
|
-
const { exitCode, stderr } = await this.runCommand(command);
|
|
232
|
-
if (exitCode !== 0) {
|
|
233
|
-
throw new Error(`Failed to write file: ${stderr || "Unknown error"}`);
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
/**
|
|
237
|
-
* Deletes a file at the specified path, relative to the project directory.
|
|
238
|
-
*
|
|
239
|
-
* When this method is called, it is guaranteed that the file exists.
|
|
240
|
-
*
|
|
241
|
-
* @param relativePath - The path to the file to delete, relative to the project directory.
|
|
242
|
-
*/
|
|
243
|
-
async deleteFileContent(relativePath) {
|
|
244
|
-
const command = `rm ${escapeCommandArg(relativePath)}`;
|
|
245
|
-
const { exitCode, stderr } = await this.runCommand(command);
|
|
246
|
-
if (exitCode !== 0) {
|
|
247
|
-
throw new Error(`Failed to delete file: ${stderr || "Unknown error"}`);
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
/**
|
|
251
|
-
* Moves the content of a file from a source path to a destination path, relative to the project directory.
|
|
252
|
-
*
|
|
253
|
-
* When this method is called, it is guaranteed that the source file exists.
|
|
254
|
-
* This method unconditionally moves the content, even if a file already exists at the destination path.
|
|
255
|
-
*
|
|
256
|
-
* @param relativeSourcePath - The path to the file to move, relative to the project directory.
|
|
257
|
-
* @param relativeDestinationPath - The path to move the file to, relative to the project directory.
|
|
258
|
-
*/
|
|
259
|
-
async moveFileContent(relativeSourcePath, relativeDestinationPath) {
|
|
260
|
-
const command = `mv ${escapeCommandArg(relativeSourcePath)} ${escapeCommandArg(
|
|
261
|
-
relativeDestinationPath
|
|
262
|
-
)}`;
|
|
263
|
-
const { exitCode, stderr } = await this.runCommand(command);
|
|
264
|
-
if (exitCode !== 0) {
|
|
265
|
-
throw new Error(`Failed to move file: ${stderr || "Unknown error"}`);
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
/**
|
|
269
|
-
* Copies the content of a file from a source path to a destination path, relative to the project directory.
|
|
270
|
-
*
|
|
271
|
-
* When this method is called, it is guaranteed that the source file exists.
|
|
272
|
-
* This method unconditionally copies the content, even if a file already exists at the destination path.
|
|
273
|
-
*
|
|
274
|
-
* @param relativeSourcePath - The path to the file to copy, relative to the project directory.
|
|
275
|
-
* @param relativeDestinationPath - The path to copy the file to, relative to the project directory.
|
|
276
|
-
*/
|
|
277
|
-
async copyFileContent(relativeSourcePath, relativeDestinationPath) {
|
|
278
|
-
const command = `cp ${escapeCommandArg(relativeSourcePath)} ${escapeCommandArg(
|
|
279
|
-
relativeDestinationPath
|
|
280
|
-
)}`;
|
|
281
|
-
const result = await this.runCommand(command);
|
|
282
|
-
if (result.exitCode !== 0) {
|
|
283
|
-
throw new Error(
|
|
284
|
-
`Failed to copy file: ${result.stderr || "Unknown error"}`
|
|
285
|
-
);
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
};
|
|
289
|
-
|
|
290
14
|
// src/environments/docker-environment.ts
|
|
291
15
|
var DockerEnvironmentName = "docker";
|
|
292
16
|
var DockerEnvironment = class extends UnixEnvironmentBase {
|
|
@@ -329,7 +53,8 @@ var DockerEnvironment = class extends UnixEnvironmentBase {
|
|
|
329
53
|
};
|
|
330
54
|
|
|
331
55
|
// src/environments/mock-filesystem-environment.ts
|
|
332
|
-
import
|
|
56
|
+
import path from "path";
|
|
57
|
+
import { FilesystemEnvironmentBase } from "@ai-code-agents/environment-utils";
|
|
333
58
|
var MockFilesystemEnvironmentName = "mock-filesystem";
|
|
334
59
|
var MockFilesystemEnvironment = class extends FilesystemEnvironmentBase {
|
|
335
60
|
files;
|
|
@@ -342,8 +67,8 @@ var MockFilesystemEnvironment = class extends FilesystemEnvironmentBase {
|
|
|
342
67
|
constructor(config = {}) {
|
|
343
68
|
super(config);
|
|
344
69
|
const { initialFiles, directoryPath } = this._envConfig;
|
|
345
|
-
this.files = initialFiles
|
|
346
|
-
this._preparePath = directoryPath ? (filePath) =>
|
|
70
|
+
this.files = initialFiles ? new Map(Object.entries(initialFiles)) : /* @__PURE__ */ new Map();
|
|
71
|
+
this._preparePath = directoryPath ? (filePath) => path.join(directoryPath, filePath) : (filePath) => filePath;
|
|
347
72
|
}
|
|
348
73
|
/**
|
|
349
74
|
* Gets the environment name.
|
|
@@ -396,9 +121,10 @@ var MockFilesystemEnvironment = class extends FilesystemEnvironmentBase {
|
|
|
396
121
|
|
|
397
122
|
// src/environments/node-filesystem-environment.ts
|
|
398
123
|
import fs from "fs/promises";
|
|
399
|
-
import
|
|
124
|
+
import path2 from "path";
|
|
125
|
+
import { FilesystemEnvironmentBase as FilesystemEnvironmentBase2 } from "@ai-code-agents/environment-utils";
|
|
400
126
|
var NodeFilesystemEnvironmentName = "node-filesystem";
|
|
401
|
-
var NodeFilesystemEnvironment = class extends
|
|
127
|
+
var NodeFilesystemEnvironment = class extends FilesystemEnvironmentBase2 {
|
|
402
128
|
/**
|
|
403
129
|
* Constructs a new NodeFilesystemEnvironment instance.
|
|
404
130
|
*
|
|
@@ -425,7 +151,7 @@ var NodeFilesystemEnvironment = class extends FilesystemEnvironmentBase {
|
|
|
425
151
|
* @returns True if the file exists, false otherwise.
|
|
426
152
|
*/
|
|
427
153
|
async fileExists(relativePath) {
|
|
428
|
-
const absolutePath =
|
|
154
|
+
const absolutePath = path2.join(this._envConfig.directoryPath, relativePath);
|
|
429
155
|
try {
|
|
430
156
|
await fs.stat(absolutePath);
|
|
431
157
|
return true;
|
|
@@ -442,7 +168,7 @@ var NodeFilesystemEnvironment = class extends FilesystemEnvironmentBase {
|
|
|
442
168
|
* @returns The content of the file.
|
|
443
169
|
*/
|
|
444
170
|
async readFileContent(relativePath) {
|
|
445
|
-
const absolutePath =
|
|
171
|
+
const absolutePath = path2.join(this._envConfig.directoryPath, relativePath);
|
|
446
172
|
return fs.readFile(absolutePath, "utf-8");
|
|
447
173
|
}
|
|
448
174
|
/**
|
|
@@ -454,7 +180,7 @@ var NodeFilesystemEnvironment = class extends FilesystemEnvironmentBase {
|
|
|
454
180
|
* @param content - The content to write to the file.
|
|
455
181
|
*/
|
|
456
182
|
async writeFileContent(relativePath, content) {
|
|
457
|
-
const absolutePath =
|
|
183
|
+
const absolutePath = path2.join(this._envConfig.directoryPath, relativePath);
|
|
458
184
|
await fs.writeFile(absolutePath, content, "utf-8");
|
|
459
185
|
}
|
|
460
186
|
/**
|
|
@@ -465,7 +191,7 @@ var NodeFilesystemEnvironment = class extends FilesystemEnvironmentBase {
|
|
|
465
191
|
* @param relativePath - The path to the file to delete, relative to the project directory.
|
|
466
192
|
*/
|
|
467
193
|
async deleteFileContent(relativePath) {
|
|
468
|
-
const absolutePath =
|
|
194
|
+
const absolutePath = path2.join(this._envConfig.directoryPath, relativePath);
|
|
469
195
|
await fs.rm(absolutePath);
|
|
470
196
|
}
|
|
471
197
|
/**
|
|
@@ -478,11 +204,11 @@ var NodeFilesystemEnvironment = class extends FilesystemEnvironmentBase {
|
|
|
478
204
|
* @param relativeDestinationPath - The path to move the file to, relative to the project directory.
|
|
479
205
|
*/
|
|
480
206
|
async moveFileContent(relativeSourcePath, relativeDestinationPath) {
|
|
481
|
-
const sourcePath =
|
|
207
|
+
const sourcePath = path2.join(
|
|
482
208
|
this._envConfig.directoryPath,
|
|
483
209
|
relativeSourcePath
|
|
484
210
|
);
|
|
485
|
-
const destinationPath =
|
|
211
|
+
const destinationPath = path2.join(
|
|
486
212
|
this._envConfig.directoryPath,
|
|
487
213
|
relativeDestinationPath
|
|
488
214
|
);
|
|
@@ -492,8 +218,12 @@ var NodeFilesystemEnvironment = class extends FilesystemEnvironmentBase {
|
|
|
492
218
|
|
|
493
219
|
// src/environments/unsafe-local-environment.ts
|
|
494
220
|
import { exec as exec2 } from "child_process";
|
|
221
|
+
import {
|
|
222
|
+
UnixEnvironmentBase as UnixEnvironmentBase2,
|
|
223
|
+
escapeCommandArg as escapeCommandArg2
|
|
224
|
+
} from "@ai-code-agents/environment-utils";
|
|
495
225
|
var UnsafeLocalEnvironmentName = "unsafe-local";
|
|
496
|
-
var UnsafeLocalEnvironment = class extends
|
|
226
|
+
var UnsafeLocalEnvironment = class extends UnixEnvironmentBase2 {
|
|
497
227
|
_commandPrefix;
|
|
498
228
|
/**
|
|
499
229
|
* Constructs a new environment instance.
|
|
@@ -509,7 +239,7 @@ var UnsafeLocalEnvironment = class extends UnixEnvironmentBase {
|
|
|
509
239
|
throw new Error('The directory path must be absolute (start with "/")');
|
|
510
240
|
}
|
|
511
241
|
super(config);
|
|
512
|
-
this._commandPrefix = `cd ${
|
|
242
|
+
this._commandPrefix = `cd ${escapeCommandArg2(directoryPath)} && `;
|
|
513
243
|
}
|
|
514
244
|
/**
|
|
515
245
|
* Gets the environment name.
|
|
@@ -536,180 +266,17 @@ var UnsafeLocalEnvironment = class extends UnixEnvironmentBase {
|
|
|
536
266
|
};
|
|
537
267
|
|
|
538
268
|
// src/tools/copy-file-tool.ts
|
|
539
|
-
import { z
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
path: z.string().meta({
|
|
545
|
-
description: "The path to the file that was read."
|
|
546
|
-
}),
|
|
547
|
-
content: z.string().meta({
|
|
548
|
-
description: "The content of the file that was read."
|
|
549
|
-
})
|
|
550
|
-
});
|
|
551
|
-
var WriteFileResult = z.object({
|
|
552
|
-
path: z.string().meta({
|
|
553
|
-
description: "The path to the file that was written."
|
|
554
|
-
}),
|
|
555
|
-
message: z.string().meta({
|
|
556
|
-
description: "A message indicating the result of the write operation."
|
|
557
|
-
})
|
|
558
|
-
});
|
|
559
|
-
var DeleteFileResult = z.object({
|
|
560
|
-
path: z.string().meta({
|
|
561
|
-
description: "The path to the file that was deleted."
|
|
562
|
-
}),
|
|
563
|
-
message: z.string().meta({
|
|
564
|
-
description: "A message indicating the result of the delete operation."
|
|
565
|
-
})
|
|
566
|
-
});
|
|
567
|
-
var MoveFileResult = z.object({
|
|
568
|
-
sourcePath: z.string().meta({
|
|
569
|
-
description: "The original path of the file that was moved."
|
|
570
|
-
}),
|
|
571
|
-
destinationPath: z.string().meta({
|
|
572
|
-
description: "The new path of the file that was moved to."
|
|
573
|
-
}),
|
|
574
|
-
message: z.string().meta({
|
|
575
|
-
description: "A message indicating the result of the move operation."
|
|
576
|
-
})
|
|
577
|
-
});
|
|
578
|
-
var CopyFileResult = z.object({
|
|
579
|
-
sourcePath: z.string().meta({
|
|
580
|
-
description: "The original path of the file that was copied."
|
|
581
|
-
}),
|
|
582
|
-
destinationPath: z.string().meta({
|
|
583
|
-
description: "The new path of the file that was copied to."
|
|
584
|
-
}),
|
|
585
|
-
message: z.string().meta({
|
|
586
|
-
description: "A message indicating the result of the copy operation."
|
|
587
|
-
})
|
|
588
|
-
});
|
|
589
|
-
var RunCommandResult = z.object({
|
|
590
|
-
command: z.string().meta({
|
|
591
|
-
description: "The command that was executed."
|
|
592
|
-
}),
|
|
593
|
-
exitCode: z.number().meta({
|
|
594
|
-
description: "The exit code of the command."
|
|
595
|
-
}),
|
|
596
|
-
stdout: z.string().meta({
|
|
597
|
-
description: "The standard output of the command."
|
|
598
|
-
}),
|
|
599
|
-
stderr: z.string().meta({
|
|
600
|
-
description: "The standard error output of the command."
|
|
601
|
-
})
|
|
602
|
-
});
|
|
603
|
-
|
|
604
|
-
// src/tools/tool-base.ts
|
|
605
|
-
var ToolBase = class {
|
|
606
|
-
_toolConfig;
|
|
607
|
-
_name;
|
|
608
|
-
_description;
|
|
609
|
-
_inputSchema;
|
|
610
|
-
_outputSchema;
|
|
611
|
-
_needsApproval;
|
|
612
|
-
/**
|
|
613
|
-
* Constructs a new tool instance.
|
|
614
|
-
*
|
|
615
|
-
* @param toolConfig - Optional tool config, can be used to override some defaults.
|
|
616
|
-
*/
|
|
617
|
-
constructor(toolConfig) {
|
|
618
|
-
const {
|
|
619
|
-
name: defaultName,
|
|
620
|
-
description: defaultDescription,
|
|
621
|
-
inputSchema,
|
|
622
|
-
outputSchema,
|
|
623
|
-
needsApproval: defaultNeedsApproval
|
|
624
|
-
} = this.getMetadata();
|
|
625
|
-
this._name = toolConfig?.name || defaultName;
|
|
626
|
-
this._description = toolConfig?.description || defaultDescription;
|
|
627
|
-
this._inputSchema = inputSchema;
|
|
628
|
-
this._outputSchema = outputSchema;
|
|
629
|
-
this._needsApproval = toolConfig?.needsApproval !== void 0 ? toolConfig.needsApproval : defaultNeedsApproval;
|
|
630
|
-
}
|
|
631
|
-
/**
|
|
632
|
-
* Gets the tool name.
|
|
633
|
-
*
|
|
634
|
-
* @returns The tool name.
|
|
635
|
-
*/
|
|
636
|
-
get name() {
|
|
637
|
-
return this._name;
|
|
638
|
-
}
|
|
639
|
-
/**
|
|
640
|
-
* Gets the tool description.
|
|
641
|
-
*
|
|
642
|
-
* @returns The tool description.
|
|
643
|
-
*/
|
|
644
|
-
get description() {
|
|
645
|
-
return this._description;
|
|
646
|
-
}
|
|
647
|
-
/**
|
|
648
|
-
* Gets the input schema for the tool.
|
|
649
|
-
*
|
|
650
|
-
* @returns The input schema.
|
|
651
|
-
*/
|
|
652
|
-
get inputSchema() {
|
|
653
|
-
return this._inputSchema;
|
|
654
|
-
}
|
|
655
|
-
/**
|
|
656
|
-
* Gets the input schema for the tool.
|
|
657
|
-
*
|
|
658
|
-
* @returns The input schema.
|
|
659
|
-
*/
|
|
660
|
-
get outputSchema() {
|
|
661
|
-
return this._outputSchema;
|
|
662
|
-
}
|
|
663
|
-
/**
|
|
664
|
-
* Gets whether the tool needs approval before use.
|
|
665
|
-
*
|
|
666
|
-
* @returns True if the tool needs approval, false otherwise.
|
|
667
|
-
*/
|
|
668
|
-
get needsApproval() {
|
|
669
|
-
return this._needsApproval;
|
|
670
|
-
}
|
|
671
|
-
};
|
|
672
|
-
|
|
673
|
-
// src/tools/environment-tool-base.ts
|
|
674
|
-
var EnvironmentToolBase = class extends ToolBase {
|
|
675
|
-
_environment;
|
|
676
|
-
/**
|
|
677
|
-
* Constructs a new `EnvironmentToolBase` instance.
|
|
678
|
-
*
|
|
679
|
-
* @param environment - The execution environment to apply the tool in.
|
|
680
|
-
* @param toolConfig - Optional tool config, can be used to override some defaults.
|
|
681
|
-
*/
|
|
682
|
-
constructor(environment, toolConfig) {
|
|
683
|
-
super(toolConfig);
|
|
684
|
-
this._environment = environment;
|
|
685
|
-
}
|
|
686
|
-
/**
|
|
687
|
-
* Gets the current execution environment for the tool.
|
|
688
|
-
*
|
|
689
|
-
* @returns The current execution environment.
|
|
690
|
-
*/
|
|
691
|
-
get environment() {
|
|
692
|
-
return this._environment;
|
|
693
|
-
}
|
|
694
|
-
/**
|
|
695
|
-
* Executes the tool with the given input.
|
|
696
|
-
*
|
|
697
|
-
* @param input - The input for the tool.
|
|
698
|
-
* @param _options - Options from the tool call.
|
|
699
|
-
* @returns A promise that resolves to the tool execution result.
|
|
700
|
-
*/
|
|
701
|
-
execute(input, _options) {
|
|
702
|
-
return this.executeForEnvironment(this._environment, input);
|
|
703
|
-
}
|
|
704
|
-
};
|
|
705
|
-
|
|
706
|
-
// src/tools/copy-file-tool.ts
|
|
269
|
+
import { z } from "zod";
|
|
270
|
+
import {
|
|
271
|
+
EnvironmentToolBase,
|
|
272
|
+
CopyFileResult
|
|
273
|
+
} from "@ai-code-agents/environment-utils";
|
|
707
274
|
var CopyFileToolName = "copy_file";
|
|
708
|
-
var CopyFileToolInput =
|
|
709
|
-
sourcePath:
|
|
275
|
+
var CopyFileToolInput = z.object({
|
|
276
|
+
sourcePath: z.string().meta({
|
|
710
277
|
description: "The path to the file to copy, relative to the project directory."
|
|
711
278
|
}),
|
|
712
|
-
destinationPath:
|
|
279
|
+
destinationPath: z.string().meta({
|
|
713
280
|
description: "The path to the destination where the file should be copied, relative to the project directory. If the file already exists, it will be overwritten."
|
|
714
281
|
})
|
|
715
282
|
});
|
|
@@ -744,10 +311,11 @@ var CopyFileTool = class extends EnvironmentToolBase {
|
|
|
744
311
|
/**
|
|
745
312
|
* Converts the tool output to a format suitable for model consumption.
|
|
746
313
|
*
|
|
747
|
-
* @param
|
|
314
|
+
* @param options - The tool result, including the output from the tool execution.
|
|
748
315
|
* @returns The formatted tool result.
|
|
749
316
|
*/
|
|
750
|
-
toModelOutput(
|
|
317
|
+
toModelOutput(options) {
|
|
318
|
+
const { output } = options;
|
|
751
319
|
return {
|
|
752
320
|
type: "text",
|
|
753
321
|
value: `File \`${output.sourcePath}\` copied successfully to \`${output.destinationPath}\`.`
|
|
@@ -772,15 +340,19 @@ var CopyFileTool = class extends EnvironmentToolBase {
|
|
|
772
340
|
};
|
|
773
341
|
|
|
774
342
|
// src/tools/delete-file-tool.ts
|
|
775
|
-
import { z as
|
|
343
|
+
import { z as z2 } from "zod";
|
|
344
|
+
import {
|
|
345
|
+
EnvironmentToolBase as EnvironmentToolBase2,
|
|
346
|
+
DeleteFileResult
|
|
347
|
+
} from "@ai-code-agents/environment-utils";
|
|
776
348
|
var DeleteFileToolName = "delete_file";
|
|
777
|
-
var DeleteFileToolInput =
|
|
778
|
-
path:
|
|
349
|
+
var DeleteFileToolInput = z2.object({
|
|
350
|
+
path: z2.string().meta({
|
|
779
351
|
description: "The path to the file to delete, relative to the project directory."
|
|
780
352
|
})
|
|
781
353
|
});
|
|
782
354
|
var DeleteFileToolOutput = DeleteFileResult;
|
|
783
|
-
var DeleteFileTool = class extends
|
|
355
|
+
var DeleteFileTool = class extends EnvironmentToolBase2 {
|
|
784
356
|
/**
|
|
785
357
|
* Returns the metadata for the tool.
|
|
786
358
|
*
|
|
@@ -810,10 +382,11 @@ var DeleteFileTool = class extends EnvironmentToolBase {
|
|
|
810
382
|
/**
|
|
811
383
|
* Converts the tool output to a format suitable for model consumption.
|
|
812
384
|
*
|
|
813
|
-
* @param
|
|
385
|
+
* @param options - The tool result, including the output from the tool execution.
|
|
814
386
|
* @returns The formatted tool result.
|
|
815
387
|
*/
|
|
816
|
-
toModelOutput(
|
|
388
|
+
toModelOutput(options) {
|
|
389
|
+
const { output } = options;
|
|
817
390
|
return {
|
|
818
391
|
type: "text",
|
|
819
392
|
value: `File \`${output.path}\` deleted successfully.`
|
|
@@ -837,43 +410,46 @@ var DeleteFileTool = class extends EnvironmentToolBase {
|
|
|
837
410
|
};
|
|
838
411
|
|
|
839
412
|
// src/tools/edit-file-tool.ts
|
|
840
|
-
import { z as
|
|
413
|
+
import { z as z3 } from "zod";
|
|
414
|
+
import {
|
|
415
|
+
EnvironmentToolBase as EnvironmentToolBase3
|
|
416
|
+
} from "@ai-code-agents/environment-utils";
|
|
841
417
|
var EditFileToolName = "edit_file";
|
|
842
|
-
var EditFileToolInput =
|
|
843
|
-
path:
|
|
418
|
+
var EditFileToolInput = z3.object({
|
|
419
|
+
path: z3.string().meta({
|
|
844
420
|
description: "The path to the file to edit, relative to the project directory."
|
|
845
421
|
}),
|
|
846
|
-
oldString:
|
|
422
|
+
oldString: z3.string().meta({
|
|
847
423
|
description: "The exact string to replace in the file."
|
|
848
424
|
}),
|
|
849
|
-
newString:
|
|
425
|
+
newString: z3.string().meta({
|
|
850
426
|
description: "The string to replace the old string with."
|
|
851
427
|
}),
|
|
852
|
-
replaceAll:
|
|
428
|
+
replaceAll: z3.boolean().optional().meta({
|
|
853
429
|
description: "Whether to replace all occurrences of the old string. Defaults to false."
|
|
854
430
|
})
|
|
855
431
|
});
|
|
856
|
-
var EditFileToolOutput =
|
|
857
|
-
path:
|
|
432
|
+
var EditFileToolOutput = z3.object({
|
|
433
|
+
path: z3.string().meta({
|
|
858
434
|
description: "The path to the file that was edited."
|
|
859
435
|
}),
|
|
860
|
-
oldString:
|
|
436
|
+
oldString: z3.string().meta({
|
|
861
437
|
description: "The old string that was replaced."
|
|
862
438
|
}),
|
|
863
|
-
newString:
|
|
439
|
+
newString: z3.string().meta({
|
|
864
440
|
description: "The new string that replaced the old string."
|
|
865
441
|
}),
|
|
866
|
-
replacements:
|
|
442
|
+
replacements: z3.number().meta({
|
|
867
443
|
description: "The number of replacements made."
|
|
868
444
|
}),
|
|
869
|
-
message:
|
|
445
|
+
message: z3.string().meta({
|
|
870
446
|
description: "A message indicating the result of the edit operation."
|
|
871
447
|
})
|
|
872
448
|
});
|
|
873
|
-
function escapeRegExp(
|
|
874
|
-
return
|
|
449
|
+
function escapeRegExp(string) {
|
|
450
|
+
return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
875
451
|
}
|
|
876
|
-
var EditFileTool = class extends
|
|
452
|
+
var EditFileTool = class extends EnvironmentToolBase3 {
|
|
877
453
|
/**
|
|
878
454
|
* Returns the metadata for the tool.
|
|
879
455
|
*
|
|
@@ -928,10 +504,11 @@ var EditFileTool = class extends EnvironmentToolBase {
|
|
|
928
504
|
/**
|
|
929
505
|
* Converts the tool output to a format suitable for model consumption.
|
|
930
506
|
*
|
|
931
|
-
* @param
|
|
507
|
+
* @param options - The tool result, including the output from the tool execution.
|
|
932
508
|
* @returns The formatted tool result.
|
|
933
509
|
*/
|
|
934
|
-
toModelOutput(
|
|
510
|
+
toModelOutput(options) {
|
|
511
|
+
const { output } = options;
|
|
935
512
|
return {
|
|
936
513
|
type: "text",
|
|
937
514
|
value: `Edited file \`${output.path}\` with ${output.replacements} replacement(s).`
|
|
@@ -979,7 +556,11 @@ var EditFileTool = class extends EnvironmentToolBase {
|
|
|
979
556
|
};
|
|
980
557
|
|
|
981
558
|
// src/tools/get-project-file-structure-tool.ts
|
|
982
|
-
import { z as
|
|
559
|
+
import { z as z4 } from "zod";
|
|
560
|
+
import {
|
|
561
|
+
EnvironmentToolBase as EnvironmentToolBase4,
|
|
562
|
+
escapeCommandArg as escapeCommandArg4
|
|
563
|
+
} from "@ai-code-agents/environment-utils";
|
|
983
564
|
|
|
984
565
|
// src/util/build-tree-from-files.ts
|
|
985
566
|
function renderTree(node, prefix = "") {
|
|
@@ -995,46 +576,133 @@ function renderTree(node, prefix = "") {
|
|
|
995
576
|
result += renderTree(node[entry], nextPrefix);
|
|
996
577
|
}
|
|
997
578
|
}
|
|
998
|
-
return result;
|
|
579
|
+
return result;
|
|
580
|
+
}
|
|
581
|
+
function buildTreeFromFiles(files) {
|
|
582
|
+
if (files.length === 0) {
|
|
583
|
+
return "";
|
|
584
|
+
}
|
|
585
|
+
const sortedFiles = [...files].sort();
|
|
586
|
+
const tree = {};
|
|
587
|
+
for (const file of sortedFiles) {
|
|
588
|
+
const parts = file.split("/");
|
|
589
|
+
let current = tree;
|
|
590
|
+
for (const part of parts) {
|
|
591
|
+
if (!current[part]) {
|
|
592
|
+
current[part] = {};
|
|
593
|
+
}
|
|
594
|
+
current = current[part];
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
return renderTree(tree).trim();
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
// src/util/get-gitignored-paths.ts
|
|
601
|
+
import path3 from "path";
|
|
602
|
+
import {
|
|
603
|
+
escapeCommandArg as escapeCommandArg3
|
|
604
|
+
} from "@ai-code-agents/environment-utils";
|
|
605
|
+
async function getGitIgnoredPaths(env) {
|
|
606
|
+
const gitignorePath = await getClosestGitIgnorePath(env);
|
|
607
|
+
if (!gitignorePath) {
|
|
608
|
+
return [];
|
|
609
|
+
}
|
|
610
|
+
const { stdout: pwd } = await env.runCommand("pwd");
|
|
611
|
+
const currentDir = pwd.trim();
|
|
612
|
+
const gitignoreDir = path3.dirname(gitignorePath);
|
|
613
|
+
try {
|
|
614
|
+
const { stdout, exitCode } = await env.runCommand(
|
|
615
|
+
`cat ${escapeCommandArg3(gitignorePath)}`
|
|
616
|
+
);
|
|
617
|
+
if (exitCode !== 0) {
|
|
618
|
+
return [];
|
|
619
|
+
}
|
|
620
|
+
const rawRules = stdout.split("\n").map((line) => line.trim()).filter((line) => line && !line.startsWith("#"));
|
|
621
|
+
const relPath = path3.relative(gitignoreDir, currentDir);
|
|
622
|
+
if (relPath === "") {
|
|
623
|
+
return rawRules.map(
|
|
624
|
+
(rule) => rule.startsWith("/") ? rule.slice(1) : rule
|
|
625
|
+
);
|
|
626
|
+
}
|
|
627
|
+
const relPathSegments = relPath.split(path3.sep);
|
|
628
|
+
const sanitizedRules = [];
|
|
629
|
+
for (const rule of rawRules) {
|
|
630
|
+
const isAnchored = rule.startsWith("/") || rule.includes("/") && rule.indexOf("/") !== rule.length - 1;
|
|
631
|
+
if (!isAnchored || rule.startsWith("**/")) {
|
|
632
|
+
sanitizedRules.push(rule.startsWith("**/") ? rule.slice(3) : rule);
|
|
633
|
+
continue;
|
|
634
|
+
}
|
|
635
|
+
const normalizedRule = rule.startsWith("/") ? rule.slice(1) : rule;
|
|
636
|
+
const cleanRule = normalizedRule.endsWith("/") ? normalizedRule.slice(0, -1) : normalizedRule;
|
|
637
|
+
const ruleSegments = cleanRule.split("/");
|
|
638
|
+
let matches = true;
|
|
639
|
+
let i = 0;
|
|
640
|
+
for (; i < relPathSegments.length; i++) {
|
|
641
|
+
if (i >= ruleSegments.length) {
|
|
642
|
+
sanitizedRules.push(".");
|
|
643
|
+
matches = false;
|
|
644
|
+
break;
|
|
645
|
+
}
|
|
646
|
+
if (!matchSegment(ruleSegments[i], relPathSegments[i])) {
|
|
647
|
+
matches = false;
|
|
648
|
+
break;
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
if (matches) {
|
|
652
|
+
const remaining = ruleSegments.slice(i).join("/");
|
|
653
|
+
if (remaining) {
|
|
654
|
+
sanitizedRules.push(
|
|
655
|
+
normalizedRule.endsWith("/") && !remaining.endsWith("/") ? `${remaining}/` : remaining
|
|
656
|
+
);
|
|
657
|
+
} else {
|
|
658
|
+
sanitizedRules.push(".");
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
return [...new Set(sanitizedRules)];
|
|
663
|
+
} catch (_error) {
|
|
664
|
+
return [];
|
|
665
|
+
}
|
|
999
666
|
}
|
|
1000
|
-
function
|
|
1001
|
-
if (
|
|
1002
|
-
return
|
|
667
|
+
function matchSegment(pattern, segment) {
|
|
668
|
+
if (pattern === "*") {
|
|
669
|
+
return true;
|
|
1003
670
|
}
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
for (const file of sortedFiles) {
|
|
1007
|
-
const parts = file.split("/");
|
|
1008
|
-
let current = tree;
|
|
1009
|
-
for (const part of parts) {
|
|
1010
|
-
if (!current[part]) {
|
|
1011
|
-
current[part] = {};
|
|
1012
|
-
}
|
|
1013
|
-
current = current[part];
|
|
1014
|
-
}
|
|
671
|
+
if (pattern === segment) {
|
|
672
|
+
return true;
|
|
1015
673
|
}
|
|
1016
|
-
|
|
674
|
+
if (pattern.includes("*") || pattern.includes("?")) {
|
|
675
|
+
const regexStr = pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*").replace(/\?/g, ".");
|
|
676
|
+
const regex = new RegExp(`^${regexStr}$`);
|
|
677
|
+
return regex.test(segment);
|
|
678
|
+
}
|
|
679
|
+
return false;
|
|
680
|
+
}
|
|
681
|
+
async function getClosestGitIgnorePath(env) {
|
|
682
|
+
const command = 'd=$PWD; while [ -n "$d" ] && [ ! -f "$d/.gitignore" ]; do d=${d%/*}; done; [ -f "$d/.gitignore" ] && echo "$d/.gitignore"';
|
|
683
|
+
const { stdout } = await env.runCommand(command);
|
|
684
|
+
return stdout.trim();
|
|
1017
685
|
}
|
|
1018
686
|
|
|
1019
687
|
// src/tools/get-project-file-structure-tool.ts
|
|
1020
688
|
var GetProjectFileStructureToolName = "get_project_file_structure";
|
|
1021
|
-
var GetProjectFileStructureToolInput =
|
|
1022
|
-
path:
|
|
689
|
+
var GetProjectFileStructureToolInput = z4.object({
|
|
690
|
+
path: z4.string().optional().meta({
|
|
1023
691
|
description: 'Root path to list files from, relative to the project directory. Defaults to ".".'
|
|
1024
692
|
}),
|
|
1025
|
-
excludeGitIgnored:
|
|
693
|
+
excludeGitIgnored: z4.boolean().optional().meta({
|
|
1026
694
|
description: "Whether to exclude files ignored by Git. Defaults to true."
|
|
1027
695
|
})
|
|
1028
696
|
});
|
|
1029
|
-
var GetProjectFileStructureToolOutput =
|
|
1030
|
-
files:
|
|
697
|
+
var GetProjectFileStructureToolOutput = z4.object({
|
|
698
|
+
files: z4.array(z4.string()).meta({
|
|
1031
699
|
description: "List of all file paths found, relative to the root path."
|
|
1032
700
|
}),
|
|
1033
|
-
excludeGitIgnored:
|
|
701
|
+
excludeGitIgnored: z4.boolean().meta({
|
|
1034
702
|
description: "Whether files ignored by Git were excluded."
|
|
1035
703
|
})
|
|
1036
704
|
});
|
|
1037
|
-
var GetProjectFileStructureTool = class extends
|
|
705
|
+
var GetProjectFileStructureTool = class extends EnvironmentToolBase4 {
|
|
1038
706
|
/**
|
|
1039
707
|
* Returns the metadata for the tool.
|
|
1040
708
|
*
|
|
@@ -1060,21 +728,16 @@ var GetProjectFileStructureTool = class extends EnvironmentToolBase {
|
|
|
1060
728
|
*/
|
|
1061
729
|
async executeForEnvironment(env, input) {
|
|
1062
730
|
const { path: path5 = ".", excludeGitIgnored = true } = input;
|
|
1063
|
-
const escapedPath =
|
|
731
|
+
const escapedPath = escapeCommandArg4(path5);
|
|
1064
732
|
let command = `find ${escapedPath} -type f`;
|
|
1065
733
|
if (excludeGitIgnored) {
|
|
1066
|
-
|
|
1067
|
-
try {
|
|
1068
|
-
const { content: gitignoreContent } = await env.readFile(".gitignore");
|
|
1069
|
-
gitIgnoredPaths = gitignoreContent.split("\n").map((line) => line.trim()).filter((line) => line && !line.startsWith("#"));
|
|
1070
|
-
} catch (_error) {
|
|
1071
|
-
}
|
|
734
|
+
const gitIgnoredPaths = await getGitIgnoredPaths(env);
|
|
1072
735
|
for (const gitIgnoredPath of gitIgnoredPaths) {
|
|
1073
736
|
if (!gitIgnoredPath.endsWith("/")) {
|
|
1074
|
-
const escapedPath2 =
|
|
1075
|
-
command += ` -not -name ${
|
|
737
|
+
const escapedPath2 = escapeCommandArg4(`*/${gitIgnoredPath}/*`);
|
|
738
|
+
command += ` -not -name ${escapeCommandArg4(gitIgnoredPath)} -not -path ${escapedPath2}`;
|
|
1076
739
|
} else {
|
|
1077
|
-
const escapedPath2 =
|
|
740
|
+
const escapedPath2 = escapeCommandArg4(`*/${gitIgnoredPath}*`);
|
|
1078
741
|
command += ` -not -path ${escapedPath2}`;
|
|
1079
742
|
}
|
|
1080
743
|
}
|
|
@@ -1096,10 +759,11 @@ var GetProjectFileStructureTool = class extends EnvironmentToolBase {
|
|
|
1096
759
|
/**
|
|
1097
760
|
* Converts the tool output to a format suitable for model consumption.
|
|
1098
761
|
*
|
|
1099
|
-
* @param
|
|
762
|
+
* @param options - The tool result, including the output from the tool execution.
|
|
1100
763
|
* @returns The formatted tool result.
|
|
1101
764
|
*/
|
|
1102
|
-
toModelOutput(
|
|
765
|
+
toModelOutput(options) {
|
|
766
|
+
const { output } = options;
|
|
1103
767
|
const tree = buildTreeFromFiles(output.files);
|
|
1104
768
|
if (!tree) {
|
|
1105
769
|
return {
|
|
@@ -1137,7 +801,12 @@ var GetProjectFileStructureTool = class extends EnvironmentToolBase {
|
|
|
1137
801
|
};
|
|
1138
802
|
|
|
1139
803
|
// src/tools/glob-tool.ts
|
|
1140
|
-
import { z as
|
|
804
|
+
import { z as z5 } from "zod";
|
|
805
|
+
import {
|
|
806
|
+
EnvironmentToolBase as EnvironmentToolBase5,
|
|
807
|
+
escapeCommandArg as escapeCommandArg5,
|
|
808
|
+
validateRelativePath
|
|
809
|
+
} from "@ai-code-agents/environment-utils";
|
|
1141
810
|
|
|
1142
811
|
// src/util/glob-to-reg-exp.ts
|
|
1143
812
|
function globToRegExp(glob) {
|
|
@@ -1185,32 +854,32 @@ function globToRegExp(glob) {
|
|
|
1185
854
|
|
|
1186
855
|
// src/tools/glob-tool.ts
|
|
1187
856
|
var GlobToolName = "glob";
|
|
1188
|
-
var GlobToolInput =
|
|
1189
|
-
searchPattern:
|
|
857
|
+
var GlobToolInput = z5.object({
|
|
858
|
+
searchPattern: z5.string().meta({
|
|
1190
859
|
description: 'The glob pattern to search for, relative to the search path / project directory (e.g. "**/*.ts", "docs/*.md").'
|
|
1191
860
|
}),
|
|
1192
|
-
searchPath:
|
|
861
|
+
searchPath: z5.string().optional().meta({
|
|
1193
862
|
description: "The path to search within, relative to the project directory. Defaults to the project directory."
|
|
1194
863
|
}),
|
|
1195
|
-
excludeGitIgnored:
|
|
864
|
+
excludeGitIgnored: z5.boolean().optional().meta({
|
|
1196
865
|
description: "Whether to exclude files ignored by Git. Defaults to true."
|
|
1197
866
|
})
|
|
1198
867
|
});
|
|
1199
|
-
var GlobToolOutput =
|
|
1200
|
-
searchPattern:
|
|
868
|
+
var GlobToolOutput = z5.object({
|
|
869
|
+
searchPattern: z5.string().meta({
|
|
1201
870
|
description: "The glob pattern that was searched for."
|
|
1202
871
|
}),
|
|
1203
|
-
searchPath:
|
|
872
|
+
searchPath: z5.string().meta({
|
|
1204
873
|
description: "The path that was searched within."
|
|
1205
874
|
}),
|
|
1206
|
-
excludeGitIgnored:
|
|
875
|
+
excludeGitIgnored: z5.boolean().meta({
|
|
1207
876
|
description: "Whether files ignored by Git were excluded."
|
|
1208
877
|
}),
|
|
1209
|
-
matchingPaths:
|
|
878
|
+
matchingPaths: z5.array(z5.string()).meta({
|
|
1210
879
|
description: "The list of file paths that matched the glob search, relative to the project directory."
|
|
1211
880
|
})
|
|
1212
881
|
});
|
|
1213
|
-
var GlobTool = class extends
|
|
882
|
+
var GlobTool = class extends EnvironmentToolBase5 {
|
|
1214
883
|
/**
|
|
1215
884
|
* Returns the metadata for the tool.
|
|
1216
885
|
*
|
|
@@ -1245,21 +914,16 @@ var GlobTool = class extends EnvironmentToolBase {
|
|
|
1245
914
|
validateRelativePath(searchPath);
|
|
1246
915
|
}
|
|
1247
916
|
const untrailingslashedSearchPath = searchPath === "" ? "." : searchPath.replace(/\/+$/, "");
|
|
1248
|
-
const escapedSearchPath =
|
|
917
|
+
const escapedSearchPath = escapeCommandArg5(untrailingslashedSearchPath);
|
|
1249
918
|
let command = `find ${escapedSearchPath} -type f`;
|
|
1250
919
|
if (excludeGitIgnored) {
|
|
1251
|
-
|
|
1252
|
-
try {
|
|
1253
|
-
const { content: gitignoreContent } = await env.readFile(".gitignore");
|
|
1254
|
-
gitIgnoredPaths = gitignoreContent.split("\n").map((line) => line.trim()).filter((line) => line && !line.startsWith("#"));
|
|
1255
|
-
} catch (_error) {
|
|
1256
|
-
}
|
|
920
|
+
const gitIgnoredPaths = await getGitIgnoredPaths(env);
|
|
1257
921
|
for (const gitIgnoredPath of gitIgnoredPaths) {
|
|
1258
922
|
if (!gitIgnoredPath.endsWith("/")) {
|
|
1259
|
-
const escapedPath =
|
|
1260
|
-
command += ` -not -name ${
|
|
923
|
+
const escapedPath = escapeCommandArg5(`*/${gitIgnoredPath}/*`);
|
|
924
|
+
command += ` -not -name ${escapeCommandArg5(gitIgnoredPath)} -not -path ${escapedPath}`;
|
|
1261
925
|
} else {
|
|
1262
|
-
const escapedPath =
|
|
926
|
+
const escapedPath = escapeCommandArg5(`*/${gitIgnoredPath}*`);
|
|
1263
927
|
command += ` -not -path ${escapedPath}`;
|
|
1264
928
|
}
|
|
1265
929
|
}
|
|
@@ -1295,10 +959,11 @@ var GlobTool = class extends EnvironmentToolBase {
|
|
|
1295
959
|
/**
|
|
1296
960
|
* Converts the tool output to a format suitable for model consumption.
|
|
1297
961
|
*
|
|
1298
|
-
* @param
|
|
962
|
+
* @param options - The tool result, including the output from the tool execution.
|
|
1299
963
|
* @returns The formatted tool result.
|
|
1300
964
|
*/
|
|
1301
|
-
toModelOutput(
|
|
965
|
+
toModelOutput(options) {
|
|
966
|
+
const { output } = options;
|
|
1302
967
|
if (output.matchingPaths.length === 0) {
|
|
1303
968
|
return {
|
|
1304
969
|
type: "text",
|
|
@@ -1347,8 +1012,276 @@ ${bulletPoints}
|
|
|
1347
1012
|
}
|
|
1348
1013
|
};
|
|
1349
1014
|
|
|
1015
|
+
// src/tools/grep-tool.ts
|
|
1016
|
+
import { z as z6 } from "zod";
|
|
1017
|
+
import {
|
|
1018
|
+
EnvironmentToolBase as EnvironmentToolBase6,
|
|
1019
|
+
escapeCommandArg as escapeCommandArg6,
|
|
1020
|
+
validateRelativePath as validateRelativePath2
|
|
1021
|
+
} from "@ai-code-agents/environment-utils";
|
|
1022
|
+
var GrepToolName = "grep";
|
|
1023
|
+
var GrepToolInput = z6.object({
|
|
1024
|
+
regexpPattern: z6.string().meta({
|
|
1025
|
+
description: "The regular expression pattern to search for in file contents."
|
|
1026
|
+
}),
|
|
1027
|
+
searchPattern: z6.string().optional().meta({
|
|
1028
|
+
description: 'The glob pattern to filter which files are searched (e.g. "**/*.ts"). If omitted, searches all files.'
|
|
1029
|
+
}),
|
|
1030
|
+
searchPath: z6.string().optional().meta({
|
|
1031
|
+
description: "The path to search within, relative to the project directory. Defaults to the project directory."
|
|
1032
|
+
}),
|
|
1033
|
+
contextLines: z6.number().int().nonnegative().optional().meta({
|
|
1034
|
+
description: "The number of context lines to include before and after each match."
|
|
1035
|
+
})
|
|
1036
|
+
});
|
|
1037
|
+
var GrepMatch = z6.object({
|
|
1038
|
+
path: z6.string().meta({
|
|
1039
|
+
description: "The path to the file containing the match, relative to the project directory."
|
|
1040
|
+
}),
|
|
1041
|
+
lineNumber: z6.number().int().meta({
|
|
1042
|
+
description: "The line number of the match (1-based)."
|
|
1043
|
+
}),
|
|
1044
|
+
line: z6.string().meta({
|
|
1045
|
+
description: "The content of the matching line."
|
|
1046
|
+
}),
|
|
1047
|
+
beforeContext: z6.array(z6.string()).optional().meta({
|
|
1048
|
+
description: "Lines of context before the match."
|
|
1049
|
+
}),
|
|
1050
|
+
afterContext: z6.array(z6.string()).optional().meta({
|
|
1051
|
+
description: "Lines of context after the match."
|
|
1052
|
+
})
|
|
1053
|
+
});
|
|
1054
|
+
var GrepToolOutput = z6.object({
|
|
1055
|
+
regexpPattern: z6.string().meta({
|
|
1056
|
+
description: "The regular expression pattern that was searched for."
|
|
1057
|
+
}),
|
|
1058
|
+
searchPattern: z6.string().optional().meta({
|
|
1059
|
+
description: "The glob pattern used to filter files."
|
|
1060
|
+
}),
|
|
1061
|
+
searchPath: z6.string().optional().meta({
|
|
1062
|
+
description: "The path that was searched within."
|
|
1063
|
+
}),
|
|
1064
|
+
contextLines: z6.number().optional().meta({
|
|
1065
|
+
description: "The number of context lines included."
|
|
1066
|
+
}),
|
|
1067
|
+
matches: z6.array(GrepMatch).meta({
|
|
1068
|
+
description: "The list of matches found."
|
|
1069
|
+
})
|
|
1070
|
+
});
|
|
1071
|
+
var GrepTool = class extends EnvironmentToolBase6 {
|
|
1072
|
+
/**
|
|
1073
|
+
* Returns the metadata for the tool.
|
|
1074
|
+
*
|
|
1075
|
+
* The name, description, and needsApproval properties are defaults which can be overridden in the constructor.
|
|
1076
|
+
*
|
|
1077
|
+
* @returns The tool metadata.
|
|
1078
|
+
*/
|
|
1079
|
+
getMetadata() {
|
|
1080
|
+
return {
|
|
1081
|
+
name: GrepToolName,
|
|
1082
|
+
description: "Searches for a regular expression pattern within the content of files in the project.",
|
|
1083
|
+
inputSchema: GrepToolInput,
|
|
1084
|
+
outputSchema: GrepToolOutput,
|
|
1085
|
+
needsApproval: false
|
|
1086
|
+
};
|
|
1087
|
+
}
|
|
1088
|
+
/**
|
|
1089
|
+
* Executes the tool in the given execution environment with the given input.
|
|
1090
|
+
*
|
|
1091
|
+
* @param env - The execution environment to use.
|
|
1092
|
+
* @param input - The input for the tool.
|
|
1093
|
+
* @returns A promise that resolves to the tool execution result.
|
|
1094
|
+
*/
|
|
1095
|
+
async executeForEnvironment(env, input) {
|
|
1096
|
+
const {
|
|
1097
|
+
regexpPattern,
|
|
1098
|
+
searchPattern,
|
|
1099
|
+
searchPath = "",
|
|
1100
|
+
contextLines = 0
|
|
1101
|
+
} = input;
|
|
1102
|
+
if (searchPath) {
|
|
1103
|
+
validateRelativePath2(searchPath);
|
|
1104
|
+
}
|
|
1105
|
+
const globTool = new GlobTool(env);
|
|
1106
|
+
const globResult = await globTool.execute(
|
|
1107
|
+
{
|
|
1108
|
+
searchPattern: searchPattern || "**/*",
|
|
1109
|
+
searchPath
|
|
1110
|
+
},
|
|
1111
|
+
{}
|
|
1112
|
+
);
|
|
1113
|
+
const filesToSearch = globResult.matchingPaths;
|
|
1114
|
+
if (filesToSearch.length === 0) {
|
|
1115
|
+
return {
|
|
1116
|
+
regexpPattern,
|
|
1117
|
+
searchPattern,
|
|
1118
|
+
searchPath,
|
|
1119
|
+
contextLines,
|
|
1120
|
+
matches: []
|
|
1121
|
+
};
|
|
1122
|
+
}
|
|
1123
|
+
const BATCH_SIZE = 50;
|
|
1124
|
+
const matches = [];
|
|
1125
|
+
for (let i = 0; i < filesToSearch.length; i += BATCH_SIZE) {
|
|
1126
|
+
const batch = filesToSearch.slice(i, i + BATCH_SIZE);
|
|
1127
|
+
const escapedFilePaths = batch.map(escapeCommandArg6).join(" ");
|
|
1128
|
+
const command = `grep -n -H -I -E ${escapeCommandArg6(regexpPattern)} ${escapedFilePaths}`;
|
|
1129
|
+
const { stdout, exitCode } = await env.runCommand(command);
|
|
1130
|
+
if (exitCode > 1) {
|
|
1131
|
+
throw new Error(`Failed to execute grep command "${command}".`);
|
|
1132
|
+
}
|
|
1133
|
+
if (stdout) {
|
|
1134
|
+
const lines = stdout.split("\n");
|
|
1135
|
+
for (const line of lines) {
|
|
1136
|
+
if (!line.trim()) continue;
|
|
1137
|
+
const firstColonIndex = line.indexOf(":");
|
|
1138
|
+
if (firstColonIndex === -1) continue;
|
|
1139
|
+
const secondColonIndex = line.indexOf(":", firstColonIndex + 1);
|
|
1140
|
+
if (secondColonIndex === -1) continue;
|
|
1141
|
+
const filePath = line.substring(0, firstColonIndex);
|
|
1142
|
+
const lineNumberStr = line.substring(
|
|
1143
|
+
firstColonIndex + 1,
|
|
1144
|
+
secondColonIndex
|
|
1145
|
+
);
|
|
1146
|
+
const content = line.substring(secondColonIndex + 1);
|
|
1147
|
+
const lineNumber = parseInt(lineNumberStr, 10);
|
|
1148
|
+
if (isNaN(lineNumber)) continue;
|
|
1149
|
+
matches.push({
|
|
1150
|
+
path: filePath,
|
|
1151
|
+
lineNumber,
|
|
1152
|
+
line: content
|
|
1153
|
+
});
|
|
1154
|
+
}
|
|
1155
|
+
}
|
|
1156
|
+
}
|
|
1157
|
+
if (contextLines > 0 && matches.length > 0) {
|
|
1158
|
+
const matchesByFile = /* @__PURE__ */ new Map();
|
|
1159
|
+
for (const match of matches) {
|
|
1160
|
+
if (!matchesByFile.has(match.path)) {
|
|
1161
|
+
matchesByFile.set(match.path, []);
|
|
1162
|
+
}
|
|
1163
|
+
matchesByFile.get(match.path).push(match);
|
|
1164
|
+
}
|
|
1165
|
+
for (const [filePath, fileMatches] of matchesByFile) {
|
|
1166
|
+
try {
|
|
1167
|
+
const { content } = await env.readFile(filePath);
|
|
1168
|
+
const lines = content.split("\n");
|
|
1169
|
+
for (const match of fileMatches) {
|
|
1170
|
+
const lineIndex = match.lineNumber - 1;
|
|
1171
|
+
const start = Math.max(0, lineIndex - contextLines);
|
|
1172
|
+
const end = Math.min(lines.length, lineIndex + contextLines + 1);
|
|
1173
|
+
match.beforeContext = lines.slice(start, lineIndex);
|
|
1174
|
+
match.afterContext = lines.slice(lineIndex + 1, end);
|
|
1175
|
+
}
|
|
1176
|
+
} catch (_error) {
|
|
1177
|
+
}
|
|
1178
|
+
}
|
|
1179
|
+
}
|
|
1180
|
+
return {
|
|
1181
|
+
regexpPattern,
|
|
1182
|
+
searchPattern,
|
|
1183
|
+
searchPath,
|
|
1184
|
+
contextLines,
|
|
1185
|
+
matches
|
|
1186
|
+
};
|
|
1187
|
+
}
|
|
1188
|
+
/**
|
|
1189
|
+
* Converts the tool output to a format suitable for model consumption.
|
|
1190
|
+
*
|
|
1191
|
+
* @param options - The tool result, including the output from the tool execution.
|
|
1192
|
+
* @returns The formatted tool result.
|
|
1193
|
+
*/
|
|
1194
|
+
toModelOutput(options) {
|
|
1195
|
+
const { output } = options;
|
|
1196
|
+
if (output.matches.length === 0) {
|
|
1197
|
+
return {
|
|
1198
|
+
type: "text",
|
|
1199
|
+
value: "No matches found."
|
|
1200
|
+
};
|
|
1201
|
+
}
|
|
1202
|
+
let result = `Found ${output.matches.length} matches:
|
|
1203
|
+
`;
|
|
1204
|
+
const matchesByFile = /* @__PURE__ */ new Map();
|
|
1205
|
+
for (const match of output.matches) {
|
|
1206
|
+
if (!matchesByFile.has(match.path)) {
|
|
1207
|
+
matchesByFile.set(match.path, []);
|
|
1208
|
+
}
|
|
1209
|
+
matchesByFile.get(match.path).push(match);
|
|
1210
|
+
}
|
|
1211
|
+
for (const [filePath, matches] of matchesByFile) {
|
|
1212
|
+
result += `
|
|
1213
|
+
File: ${filePath}
|
|
1214
|
+
`;
|
|
1215
|
+
for (const match of matches) {
|
|
1216
|
+
if (match.beforeContext && match.beforeContext.length > 0) {
|
|
1217
|
+
match.beforeContext.forEach((line, idx) => {
|
|
1218
|
+
result += ` ${match.lineNumber - match.beforeContext.length + idx}: ${line}
|
|
1219
|
+
`;
|
|
1220
|
+
});
|
|
1221
|
+
}
|
|
1222
|
+
result += `> ${match.lineNumber}: ${match.line}
|
|
1223
|
+
`;
|
|
1224
|
+
if (match.afterContext && match.afterContext.length > 0) {
|
|
1225
|
+
match.afterContext.forEach((line, idx) => {
|
|
1226
|
+
result += ` ${match.lineNumber + 1 + idx}: ${line}
|
|
1227
|
+
`;
|
|
1228
|
+
});
|
|
1229
|
+
}
|
|
1230
|
+
if (output.contextLines && output.contextLines > 0) {
|
|
1231
|
+
result += "---\n";
|
|
1232
|
+
}
|
|
1233
|
+
}
|
|
1234
|
+
}
|
|
1235
|
+
return {
|
|
1236
|
+
type: "text",
|
|
1237
|
+
value: result
|
|
1238
|
+
};
|
|
1239
|
+
}
|
|
1240
|
+
/**
|
|
1241
|
+
* Gets the examples for the tool.
|
|
1242
|
+
*
|
|
1243
|
+
* @returns The tool examples.
|
|
1244
|
+
*/
|
|
1245
|
+
get examples() {
|
|
1246
|
+
return [
|
|
1247
|
+
{
|
|
1248
|
+
input: {
|
|
1249
|
+
regexpPattern: "interface.*Tool",
|
|
1250
|
+
searchPattern: "src/**/*.ts"
|
|
1251
|
+
},
|
|
1252
|
+
output: `Found 2 matches:
|
|
1253
|
+
|
|
1254
|
+
File: src/types.ts
|
|
1255
|
+
> 120: export interface ToolInterface<ToolInputType, ToolOutputType> {
|
|
1256
|
+
> 135: export interface EnvironmentToolInterface<
|
|
1257
|
+
|
|
1258
|
+
File: src/tools/tool-base.ts
|
|
1259
|
+
> 10: export abstract class ToolBase<
|
|
1260
|
+
`
|
|
1261
|
+
},
|
|
1262
|
+
{
|
|
1263
|
+
input: {
|
|
1264
|
+
regexpPattern: "TODO",
|
|
1265
|
+
contextLines: 1
|
|
1266
|
+
},
|
|
1267
|
+
output: `Found 1 matches:
|
|
1268
|
+
|
|
1269
|
+
File: src/index.ts
|
|
1270
|
+
10: // Some code before
|
|
1271
|
+
> 11: // TODO: Implement feature X
|
|
1272
|
+
12: // Some code after
|
|
1273
|
+
`
|
|
1274
|
+
}
|
|
1275
|
+
];
|
|
1276
|
+
}
|
|
1277
|
+
};
|
|
1278
|
+
|
|
1350
1279
|
// src/tools/list-directory-tool.ts
|
|
1351
1280
|
import { z as z7 } from "zod";
|
|
1281
|
+
import {
|
|
1282
|
+
EnvironmentToolBase as EnvironmentToolBase7,
|
|
1283
|
+
escapeCommandArg as escapeCommandArg7
|
|
1284
|
+
} from "@ai-code-agents/environment-utils";
|
|
1352
1285
|
var ListDirectoryToolName = "list_directory";
|
|
1353
1286
|
var ListDirectoryToolInput = z7.object({
|
|
1354
1287
|
path: z7.string().meta({
|
|
@@ -1366,7 +1299,7 @@ var ListDirectoryToolOutput = z7.object({
|
|
|
1366
1299
|
description: "List of subdirectories in the directory."
|
|
1367
1300
|
})
|
|
1368
1301
|
});
|
|
1369
|
-
var ListDirectoryTool = class extends
|
|
1302
|
+
var ListDirectoryTool = class extends EnvironmentToolBase7 {
|
|
1370
1303
|
/**
|
|
1371
1304
|
* Returns the metadata for the tool.
|
|
1372
1305
|
*
|
|
@@ -1391,7 +1324,7 @@ var ListDirectoryTool = class extends EnvironmentToolBase {
|
|
|
1391
1324
|
* @returns A promise that resolves to the tool execution result.
|
|
1392
1325
|
*/
|
|
1393
1326
|
async executeForEnvironment(env, input) {
|
|
1394
|
-
const escapedPath =
|
|
1327
|
+
const escapedPath = escapeCommandArg7(input.path);
|
|
1395
1328
|
const command = `ls -la ${escapedPath}`;
|
|
1396
1329
|
const { stdout, stderr, exitCode } = await env.runCommand(command);
|
|
1397
1330
|
if (exitCode !== 0) {
|
|
@@ -1424,10 +1357,11 @@ var ListDirectoryTool = class extends EnvironmentToolBase {
|
|
|
1424
1357
|
/**
|
|
1425
1358
|
* Converts the tool output to a format suitable for model consumption.
|
|
1426
1359
|
*
|
|
1427
|
-
* @param
|
|
1360
|
+
* @param options - The tool result, including the output from the tool execution.
|
|
1428
1361
|
* @returns The formatted tool result.
|
|
1429
1362
|
*/
|
|
1430
|
-
toModelOutput(
|
|
1363
|
+
toModelOutput(options) {
|
|
1364
|
+
const { output } = options;
|
|
1431
1365
|
const formatEntries = (entries, type) => {
|
|
1432
1366
|
if (entries.length === 0) {
|
|
1433
1367
|
return `No ${type} found.`;
|
|
@@ -1474,6 +1408,10 @@ Directories:
|
|
|
1474
1408
|
|
|
1475
1409
|
// src/tools/move-file-tool.ts
|
|
1476
1410
|
import { z as z8 } from "zod";
|
|
1411
|
+
import {
|
|
1412
|
+
EnvironmentToolBase as EnvironmentToolBase8,
|
|
1413
|
+
MoveFileResult
|
|
1414
|
+
} from "@ai-code-agents/environment-utils";
|
|
1477
1415
|
var MoveFileToolName = "move_file";
|
|
1478
1416
|
var MoveFileToolInput = z8.object({
|
|
1479
1417
|
sourcePath: z8.string().meta({
|
|
@@ -1484,7 +1422,7 @@ var MoveFileToolInput = z8.object({
|
|
|
1484
1422
|
})
|
|
1485
1423
|
});
|
|
1486
1424
|
var MoveFileToolOutput = MoveFileResult;
|
|
1487
|
-
var MoveFileTool = class extends
|
|
1425
|
+
var MoveFileTool = class extends EnvironmentToolBase8 {
|
|
1488
1426
|
/**
|
|
1489
1427
|
* Returns the metadata for the tool.
|
|
1490
1428
|
*
|
|
@@ -1514,10 +1452,11 @@ var MoveFileTool = class extends EnvironmentToolBase {
|
|
|
1514
1452
|
/**
|
|
1515
1453
|
* Converts the tool output to a format suitable for model consumption.
|
|
1516
1454
|
*
|
|
1517
|
-
* @param
|
|
1455
|
+
* @param options - The tool result, including the output from the tool execution.
|
|
1518
1456
|
* @returns The formatted tool result.
|
|
1519
1457
|
*/
|
|
1520
|
-
toModelOutput(
|
|
1458
|
+
toModelOutput(options) {
|
|
1459
|
+
const { output } = options;
|
|
1521
1460
|
return {
|
|
1522
1461
|
type: "text",
|
|
1523
1462
|
value: `File \`${output.sourcePath}\` moved successfully to \`${output.destinationPath}\`.`
|
|
@@ -1543,6 +1482,10 @@ var MoveFileTool = class extends EnvironmentToolBase {
|
|
|
1543
1482
|
|
|
1544
1483
|
// src/tools/read-file-tool.ts
|
|
1545
1484
|
import { z as z9 } from "zod";
|
|
1485
|
+
import {
|
|
1486
|
+
EnvironmentToolBase as EnvironmentToolBase9,
|
|
1487
|
+
ReadFileResult
|
|
1488
|
+
} from "@ai-code-agents/environment-utils";
|
|
1546
1489
|
|
|
1547
1490
|
// src/util/get-language-identifier-from-file-path.ts
|
|
1548
1491
|
import path4 from "path";
|
|
@@ -1720,7 +1663,7 @@ ${output.content}
|
|
|
1720
1663
|
\`\`\`
|
|
1721
1664
|
`;
|
|
1722
1665
|
};
|
|
1723
|
-
var ReadFileTool = class extends
|
|
1666
|
+
var ReadFileTool = class extends EnvironmentToolBase9 {
|
|
1724
1667
|
/**
|
|
1725
1668
|
* Returns the metadata for the tool.
|
|
1726
1669
|
*
|
|
@@ -1750,10 +1693,11 @@ var ReadFileTool = class extends EnvironmentToolBase {
|
|
|
1750
1693
|
/**
|
|
1751
1694
|
* Converts the tool output to a format suitable for model consumption.
|
|
1752
1695
|
*
|
|
1753
|
-
* @param
|
|
1696
|
+
* @param options - The tool result, including the output from the tool execution.
|
|
1754
1697
|
* @returns The formatted tool result.
|
|
1755
1698
|
*/
|
|
1756
|
-
toModelOutput(
|
|
1699
|
+
toModelOutput(options) {
|
|
1700
|
+
const { output } = options;
|
|
1757
1701
|
return {
|
|
1758
1702
|
type: "text",
|
|
1759
1703
|
value: formatModelResponse(output)
|
|
@@ -1797,13 +1741,17 @@ export function Loader(props: LoaderProps) {
|
|
|
1797
1741
|
|
|
1798
1742
|
// src/tools/read-many-files-tool.ts
|
|
1799
1743
|
import { z as z10 } from "zod";
|
|
1744
|
+
import {
|
|
1745
|
+
EnvironmentToolBase as EnvironmentToolBase10,
|
|
1746
|
+
ReadFileResult as ReadFileResult2
|
|
1747
|
+
} from "@ai-code-agents/environment-utils";
|
|
1800
1748
|
var ReadManyFilesToolName = "read_many_files";
|
|
1801
1749
|
var ReadManyFilesToolInput = z10.object({
|
|
1802
1750
|
paths: z10.array(z10.string()).meta({
|
|
1803
1751
|
description: "The paths to the files to read, relative to the project directory."
|
|
1804
1752
|
})
|
|
1805
1753
|
});
|
|
1806
|
-
var ReadManyFilesToolOutput = z10.record(z10.string(),
|
|
1754
|
+
var ReadManyFilesToolOutput = z10.record(z10.string(), ReadFileResult2);
|
|
1807
1755
|
var formatModelResponse2 = (output) => {
|
|
1808
1756
|
const language = getLanguageIdentifierFromFilePath(output.path);
|
|
1809
1757
|
return `File: \`${output.path}\`
|
|
@@ -1813,7 +1761,7 @@ ${output.content}
|
|
|
1813
1761
|
\`\`\`
|
|
1814
1762
|
`;
|
|
1815
1763
|
};
|
|
1816
|
-
var ReadManyFilesTool = class extends
|
|
1764
|
+
var ReadManyFilesTool = class extends EnvironmentToolBase10 {
|
|
1817
1765
|
/**
|
|
1818
1766
|
* Returns the metadata for the tool.
|
|
1819
1767
|
*
|
|
@@ -1849,10 +1797,11 @@ var ReadManyFilesTool = class extends EnvironmentToolBase {
|
|
|
1849
1797
|
/**
|
|
1850
1798
|
* Converts the tool output to a format suitable for model consumption.
|
|
1851
1799
|
*
|
|
1852
|
-
* @param
|
|
1800
|
+
* @param options - The tool result, including the output from the tool execution.
|
|
1853
1801
|
* @returns The formatted tool result.
|
|
1854
1802
|
*/
|
|
1855
|
-
toModelOutput(
|
|
1803
|
+
toModelOutput(options) {
|
|
1804
|
+
const { output } = options;
|
|
1856
1805
|
const fileContentResponses = Object.values(output).map(
|
|
1857
1806
|
(fileResult) => formatModelResponse2(fileResult)
|
|
1858
1807
|
);
|
|
@@ -1909,6 +1858,10 @@ export function Loader(props: LoaderProps) {
|
|
|
1909
1858
|
|
|
1910
1859
|
// src/tools/run-command-tool.ts
|
|
1911
1860
|
import { z as z11 } from "zod";
|
|
1861
|
+
import {
|
|
1862
|
+
EnvironmentToolBase as EnvironmentToolBase11,
|
|
1863
|
+
RunCommandResult
|
|
1864
|
+
} from "@ai-code-agents/environment-utils";
|
|
1912
1865
|
var RunCommandToolName = "run_command";
|
|
1913
1866
|
var RunCommandToolInput = z11.object({
|
|
1914
1867
|
command: z11.string().meta({ description: "The CLI command to run, including all arguments." })
|
|
@@ -1929,7 +1882,7 @@ Output (stdout): ${stdout}
|
|
|
1929
1882
|
Error Output (stderr): ${stderr}
|
|
1930
1883
|
`;
|
|
1931
1884
|
}
|
|
1932
|
-
var RunCommandTool = class extends
|
|
1885
|
+
var RunCommandTool = class extends EnvironmentToolBase11 {
|
|
1933
1886
|
/**
|
|
1934
1887
|
* Returns the metadata for the tool.
|
|
1935
1888
|
*
|
|
@@ -1959,10 +1912,11 @@ var RunCommandTool = class extends EnvironmentToolBase {
|
|
|
1959
1912
|
/**
|
|
1960
1913
|
* Converts the tool output to a format suitable for model consumption.
|
|
1961
1914
|
*
|
|
1962
|
-
* @param
|
|
1915
|
+
* @param options - The tool result, including the output from the tool execution.
|
|
1963
1916
|
* @returns The formatted tool result.
|
|
1964
1917
|
*/
|
|
1965
|
-
toModelOutput(
|
|
1918
|
+
toModelOutput(options) {
|
|
1919
|
+
const { output } = options;
|
|
1966
1920
|
return {
|
|
1967
1921
|
type: "text",
|
|
1968
1922
|
value: formatCommandResultToModelResponse(output)
|
|
@@ -2034,6 +1988,10 @@ added 1 package, and changed 1 package in 2s
|
|
|
2034
1988
|
|
|
2035
1989
|
// src/tools/write-file-tool.ts
|
|
2036
1990
|
import { z as z12 } from "zod";
|
|
1991
|
+
import {
|
|
1992
|
+
EnvironmentToolBase as EnvironmentToolBase12,
|
|
1993
|
+
WriteFileResult
|
|
1994
|
+
} from "@ai-code-agents/environment-utils";
|
|
2037
1995
|
var WriteFileToolName = "write_file";
|
|
2038
1996
|
var WriteFileToolInput = z12.object({
|
|
2039
1997
|
path: z12.string().meta({
|
|
@@ -2044,7 +2002,7 @@ var WriteFileToolInput = z12.object({
|
|
|
2044
2002
|
})
|
|
2045
2003
|
});
|
|
2046
2004
|
var WriteFileToolOutput = WriteFileResult;
|
|
2047
|
-
var WriteFileTool = class extends
|
|
2005
|
+
var WriteFileTool = class extends EnvironmentToolBase12 {
|
|
2048
2006
|
/**
|
|
2049
2007
|
* Returns the metadata for the tool.
|
|
2050
2008
|
*
|
|
@@ -2074,10 +2032,11 @@ var WriteFileTool = class extends EnvironmentToolBase {
|
|
|
2074
2032
|
/**
|
|
2075
2033
|
* Converts the tool output to a format suitable for model consumption.
|
|
2076
2034
|
*
|
|
2077
|
-
* @param
|
|
2035
|
+
* @param options - The tool result, including the output from the tool execution.
|
|
2078
2036
|
* @returns The formatted tool result.
|
|
2079
2037
|
*/
|
|
2080
|
-
toModelOutput(
|
|
2038
|
+
toModelOutput(options) {
|
|
2039
|
+
const { output } = options;
|
|
2081
2040
|
return {
|
|
2082
2041
|
type: "text",
|
|
2083
2042
|
value: `File \`${output.path}\` written successfully.`
|
|
@@ -2107,6 +2066,9 @@ var WriteFileTool = class extends EnvironmentToolBase {
|
|
|
2107
2066
|
|
|
2108
2067
|
// src/tools/submit-tool.ts
|
|
2109
2068
|
import { z as z13 } from "zod";
|
|
2069
|
+
import {
|
|
2070
|
+
ToolBase
|
|
2071
|
+
} from "@ai-code-agents/environment-utils";
|
|
2110
2072
|
var SubmitToolName = "submit";
|
|
2111
2073
|
var SubmitToolInput = z13.object({});
|
|
2112
2074
|
var SubmitToolOutput = z13.object({});
|
|
@@ -2131,7 +2093,7 @@ var SubmitTool = class extends ToolBase {
|
|
|
2131
2093
|
* Executes the tool with the given input.
|
|
2132
2094
|
*
|
|
2133
2095
|
* @param _ - The input for the tool. Unused.
|
|
2134
|
-
* @param __ - Options
|
|
2096
|
+
* @param __ - Options for the tool execution. Unused.
|
|
2135
2097
|
* @returns A promise that resolves to the tool execution result.
|
|
2136
2098
|
*/
|
|
2137
2099
|
async execute(_, __) {
|
|
@@ -2140,7 +2102,7 @@ var SubmitTool = class extends ToolBase {
|
|
|
2140
2102
|
/**
|
|
2141
2103
|
* Converts the tool output to a format suitable for model consumption.
|
|
2142
2104
|
*
|
|
2143
|
-
* @param _ - The output from the tool execution. Unused.
|
|
2105
|
+
* @param _ - The tool result, including the output from the tool execution. Unused.
|
|
2144
2106
|
* @returns The formatted tool result.
|
|
2145
2107
|
*/
|
|
2146
2108
|
toModelOutput(_) {
|
|
@@ -2161,7 +2123,7 @@ var SubmitTool = class extends ToolBase {
|
|
|
2161
2123
|
|
|
2162
2124
|
// src/agent-creators.ts
|
|
2163
2125
|
import {
|
|
2164
|
-
|
|
2126
|
+
ToolLoopAgent,
|
|
2165
2127
|
stepCountIs,
|
|
2166
2128
|
hasToolCall
|
|
2167
2129
|
} from "ai";
|
|
@@ -2169,10 +2131,13 @@ import {
|
|
|
2169
2131
|
// src/instructions.ts
|
|
2170
2132
|
function getAdditionalInstructions(config) {
|
|
2171
2133
|
const { maxSteps, allowSubmit, tools } = config;
|
|
2172
|
-
const exampleSections = [
|
|
2134
|
+
const exampleSections = [
|
|
2135
|
+
"# Tool Examples",
|
|
2136
|
+
"You have access to several tools to assist you in completing your task. Here are some examples of how to use them:"
|
|
2137
|
+
];
|
|
2173
2138
|
for (const [toolName, tool] of Object.entries(tools)) {
|
|
2174
2139
|
if ("examples" in tool && Array.isArray(tool.examples) && tool.examples.length > 0) {
|
|
2175
|
-
let toolSection =
|
|
2140
|
+
let toolSection = `## Tool: \`${toolName}\`
|
|
2176
2141
|
|
|
2177
2142
|
`;
|
|
2178
2143
|
for (const example of tool.examples) {
|
|
@@ -2181,40 +2146,48 @@ function getAdditionalInstructions(config) {
|
|
|
2181
2146
|
exampleSections.push(toolSection.trim());
|
|
2182
2147
|
}
|
|
2183
2148
|
}
|
|
2184
|
-
const
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
"You have access to several tools to assist you in completing your task."
|
|
2191
|
-
] : [],
|
|
2192
|
-
"You must issue tool calls to complete your task. Do not engage with the user directly.",
|
|
2193
|
-
...allowSubmit ? [
|
|
2194
|
-
`Once you think you have completed your task, call the \`${SubmitToolName}\` tool to submit your results.`
|
|
2195
|
-
] : [],
|
|
2196
|
-
`You have a maximum of ${maxSteps} steps to complete your task.`
|
|
2197
|
-
];
|
|
2198
|
-
const importantWorkflowGuidelines = `## Important Workflow Guidelines
|
|
2199
|
-
|
|
2200
|
-
${workflowGuidelines.map((line) => `- ${line}`).join("\n")}
|
|
2201
|
-
|
|
2202
|
-
Remember, you don't get to ask the user any clarifying questions, just use the tools available to complete your task. You're on your own now.
|
|
2149
|
+
const constraintSections = ["# Behavioral Guidelines"];
|
|
2150
|
+
const constraintsByType = getCodeAgentConstraints({ maxSteps, allowSubmit });
|
|
2151
|
+
if (constraintsByType.must && constraintsByType.must.length > 0) {
|
|
2152
|
+
let constraintSection = "## You MUST:\n\n";
|
|
2153
|
+
for (const constraint of constraintsByType.must) {
|
|
2154
|
+
constraintSection += `- ${constraint}
|
|
2203
2155
|
`;
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2156
|
+
}
|
|
2157
|
+
constraintSections.push(constraintSection.trim());
|
|
2158
|
+
}
|
|
2159
|
+
if (constraintsByType.must_not && constraintsByType.must_not.length > 0) {
|
|
2160
|
+
let constraintSection = "## You MUST NOT:\n\n";
|
|
2161
|
+
for (const constraint of constraintsByType.must_not) {
|
|
2162
|
+
constraintSection += `- ${constraint}
|
|
2163
|
+
`;
|
|
2164
|
+
}
|
|
2165
|
+
constraintSections.push(constraintSection.trim());
|
|
2166
|
+
}
|
|
2167
|
+
if (constraintsByType.should && constraintsByType.should.length > 0) {
|
|
2168
|
+
let constraintSection = "## You SHOULD:\n\n";
|
|
2169
|
+
for (const constraint of constraintsByType.should) {
|
|
2170
|
+
constraintSection += `- ${constraint}
|
|
2171
|
+
`;
|
|
2172
|
+
}
|
|
2173
|
+
constraintSections.push(constraintSection.trim());
|
|
2174
|
+
}
|
|
2175
|
+
if (constraintsByType.should_not && constraintsByType.should_not.length > 0) {
|
|
2176
|
+
let constraintSection = "## You SHOULD NOT:\n\n";
|
|
2177
|
+
for (const constraint of constraintsByType.should_not) {
|
|
2178
|
+
constraintSection += `- ${constraint}
|
|
2179
|
+
`;
|
|
2180
|
+
}
|
|
2181
|
+
constraintSections.push(constraintSection.trim());
|
|
2212
2182
|
}
|
|
2213
|
-
|
|
2183
|
+
const finalReminder = getCodeAgentFinalReminder();
|
|
2184
|
+
return [...exampleSections, ...constraintSections, finalReminder].join(
|
|
2185
|
+
"\n\n"
|
|
2186
|
+
);
|
|
2214
2187
|
}
|
|
2215
2188
|
function formatExampleForInstructions(toolName, example) {
|
|
2216
|
-
const input =
|
|
2217
|
-
const output =
|
|
2189
|
+
const input = formatValueForExample(example.input);
|
|
2190
|
+
const output = formatValueForExample(example.output);
|
|
2218
2191
|
if (output === "") {
|
|
2219
2192
|
return `<example>
|
|
2220
2193
|
<tool_call>
|
|
@@ -2231,8 +2204,42 @@ ${output}
|
|
|
2231
2204
|
</tool_response>
|
|
2232
2205
|
</example>`;
|
|
2233
2206
|
}
|
|
2207
|
+
function formatValueForExample(value) {
|
|
2208
|
+
if (typeof value === "undefined") {
|
|
2209
|
+
return "";
|
|
2210
|
+
}
|
|
2211
|
+
if (typeof value === "string") {
|
|
2212
|
+
return `"${value}"`;
|
|
2213
|
+
}
|
|
2214
|
+
if (typeof value === "number") {
|
|
2215
|
+
return value.toString();
|
|
2216
|
+
}
|
|
2217
|
+
if (typeof value === "boolean") {
|
|
2218
|
+
return value ? "true" : "false";
|
|
2219
|
+
}
|
|
2220
|
+
return JSON.stringify(value, null, 2);
|
|
2221
|
+
}
|
|
2222
|
+
function getCodeAgentConstraints(config) {
|
|
2223
|
+
const { maxSteps, allowSubmit } = config;
|
|
2224
|
+
return {
|
|
2225
|
+
must: [
|
|
2226
|
+
"Always issue tool calls to complete your task",
|
|
2227
|
+
...allowSubmit ? [
|
|
2228
|
+
`Call the \`${SubmitToolName}\` tool once you think you have completed your task, to submit your results`
|
|
2229
|
+
] : [],
|
|
2230
|
+
`Complete your task within ${maxSteps} steps`
|
|
2231
|
+
],
|
|
2232
|
+
must_not: ["Engage with the user directly"]
|
|
2233
|
+
};
|
|
2234
|
+
}
|
|
2235
|
+
function getCodeAgentFinalReminder() {
|
|
2236
|
+
return "Remember, you don't get to ask the user any clarifying questions, just use the tools available to complete your task. You're on your own now.";
|
|
2237
|
+
}
|
|
2234
2238
|
|
|
2235
2239
|
// src/tool-creators.ts
|
|
2240
|
+
import {
|
|
2241
|
+
isCommandLine
|
|
2242
|
+
} from "@ai-code-agents/environment-utils";
|
|
2236
2243
|
var availableEnvironmentTools = {
|
|
2237
2244
|
[ReadFileToolName]: ReadFileTool,
|
|
2238
2245
|
[WriteFileToolName]: WriteFileTool,
|
|
@@ -2243,12 +2250,14 @@ var availableEnvironmentTools = {
|
|
|
2243
2250
|
[ReadManyFilesToolName]: ReadManyFilesTool,
|
|
2244
2251
|
[GetProjectFileStructureToolName]: GetProjectFileStructureTool,
|
|
2245
2252
|
[GlobToolName]: GlobTool,
|
|
2253
|
+
[GrepToolName]: GrepTool,
|
|
2246
2254
|
[ListDirectoryToolName]: ListDirectoryTool,
|
|
2247
2255
|
[RunCommandToolName]: RunCommandTool
|
|
2248
2256
|
};
|
|
2249
2257
|
var cliOnlyTools = [
|
|
2250
2258
|
GetProjectFileStructureToolName,
|
|
2251
2259
|
GlobToolName,
|
|
2260
|
+
GrepToolName,
|
|
2252
2261
|
ListDirectoryToolName,
|
|
2253
2262
|
RunCommandToolName
|
|
2254
2263
|
];
|
|
@@ -2257,6 +2266,7 @@ var readonlyTools = [
|
|
|
2257
2266
|
ReadManyFilesToolName,
|
|
2258
2267
|
GetProjectFileStructureToolName,
|
|
2259
2268
|
GlobToolName,
|
|
2269
|
+
GrepToolName,
|
|
2260
2270
|
ListDirectoryToolName
|
|
2261
2271
|
];
|
|
2262
2272
|
var dangerousTools = [
|
|
@@ -2284,7 +2294,7 @@ function createEnvironmentTool(toolName, environment, config) {
|
|
|
2284
2294
|
}
|
|
2285
2295
|
function createToolsForEnvironment(environment, toolsDefinition = "all") {
|
|
2286
2296
|
const sanitizedToolsDefinition = sanitizeToolsDefinition(toolsDefinition);
|
|
2287
|
-
const isCliEnvironment =
|
|
2297
|
+
const isCliEnvironment = isCommandLine(environment);
|
|
2288
2298
|
const tools = {};
|
|
2289
2299
|
for (const toolDefinition of sanitizedToolsDefinition) {
|
|
2290
2300
|
const actualToolName = toolDefinition.toolName;
|
|
@@ -2305,7 +2315,7 @@ function createToolsForEnvironment(environment, toolsDefinition = "all") {
|
|
|
2305
2315
|
}
|
|
2306
2316
|
tools[toolNameToUse] = createEnvironmentTool(
|
|
2307
2317
|
actualToolName,
|
|
2308
|
-
|
|
2318
|
+
environment,
|
|
2309
2319
|
toolConfig
|
|
2310
2320
|
);
|
|
2311
2321
|
}
|
|
@@ -2361,6 +2371,54 @@ function sanitizeToolsDefinition(toolsDefinition) {
|
|
|
2361
2371
|
});
|
|
2362
2372
|
}
|
|
2363
2373
|
|
|
2374
|
+
// src/util/truncate.ts
|
|
2375
|
+
function truncateString(str) {
|
|
2376
|
+
const lines = str.split("\n");
|
|
2377
|
+
while (lines.length > 0 && lines[lines.length - 1] === "") {
|
|
2378
|
+
lines.pop();
|
|
2379
|
+
}
|
|
2380
|
+
const isMultiline = lines.length > 1;
|
|
2381
|
+
if (isMultiline) {
|
|
2382
|
+
if (lines.length > 5) {
|
|
2383
|
+
const truncatedLines = lines.slice(0, 5).join("\n");
|
|
2384
|
+
const moreLines = lines.length - 5;
|
|
2385
|
+
const lineSuffix = moreLines === 1 ? "line" : "lines";
|
|
2386
|
+
return `${truncatedLines}
|
|
2387
|
+
...(${moreLines} more ${lineSuffix})`;
|
|
2388
|
+
}
|
|
2389
|
+
return lines.join("\n");
|
|
2390
|
+
}
|
|
2391
|
+
const singleLine = lines[0] || "";
|
|
2392
|
+
if (singleLine.length > 300) {
|
|
2393
|
+
const moreChars = singleLine.length - 300;
|
|
2394
|
+
return `${singleLine.slice(0, 300)}...(${moreChars} more characters)`;
|
|
2395
|
+
}
|
|
2396
|
+
return singleLine;
|
|
2397
|
+
}
|
|
2398
|
+
function truncateObject(obj) {
|
|
2399
|
+
const result = {};
|
|
2400
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
2401
|
+
if (typeof value === "string") {
|
|
2402
|
+
result[key] = truncateString(value);
|
|
2403
|
+
} else if (Array.isArray(value)) {
|
|
2404
|
+
result[key] = value.map((item) => {
|
|
2405
|
+
if (typeof item === "string") {
|
|
2406
|
+
return truncateString(item);
|
|
2407
|
+
}
|
|
2408
|
+
if (typeof item === "object" && item !== null) {
|
|
2409
|
+
return truncateObject(item);
|
|
2410
|
+
}
|
|
2411
|
+
return item;
|
|
2412
|
+
});
|
|
2413
|
+
} else if (typeof value === "object" && value !== null) {
|
|
2414
|
+
result[key] = truncateObject(value);
|
|
2415
|
+
} else {
|
|
2416
|
+
result[key] = value;
|
|
2417
|
+
}
|
|
2418
|
+
}
|
|
2419
|
+
return result;
|
|
2420
|
+
}
|
|
2421
|
+
|
|
2364
2422
|
// src/util/get-step-log.ts
|
|
2365
2423
|
function getStepLog(stepResult) {
|
|
2366
2424
|
const { content } = stepResult;
|
|
@@ -2374,13 +2432,17 @@ function getStepLog(stepResult) {
|
|
|
2374
2432
|
}
|
|
2375
2433
|
logEntry += ": ";
|
|
2376
2434
|
if (part.type === "tool-call" && "input" in part) {
|
|
2377
|
-
logEntry += typeof part.input === "string" ? part.input :
|
|
2435
|
+
logEntry += typeof part.input === "string" ? truncateString(part.input) : part.input === null || part.input === void 0 ? String(part.input) : JSON.stringify(
|
|
2436
|
+
truncateObject(part.input)
|
|
2437
|
+
);
|
|
2378
2438
|
} else if (part.type === "tool-result" && "output" in part) {
|
|
2379
|
-
logEntry += typeof part.output === "string" ? part.output :
|
|
2439
|
+
logEntry += typeof part.output === "string" ? truncateString(part.output) : part.output === null || part.output === void 0 ? String(part.output) : JSON.stringify(
|
|
2440
|
+
truncateObject(part.output)
|
|
2441
|
+
);
|
|
2380
2442
|
} else if (part.type === "tool-error" && "error" in part) {
|
|
2381
2443
|
logEntry += typeof part.error === "object" && part.error !== null && "message" in part.error ? part.error.message : String(part.error);
|
|
2382
2444
|
} else if (part.type === "text" && "text" in part) {
|
|
2383
|
-
logEntry += part.text;
|
|
2445
|
+
logEntry += truncateString(part.text);
|
|
2384
2446
|
}
|
|
2385
2447
|
logEntry += "\n";
|
|
2386
2448
|
});
|
|
@@ -2389,6 +2451,9 @@ function getStepLog(stepResult) {
|
|
|
2389
2451
|
|
|
2390
2452
|
// src/agent-creators.ts
|
|
2391
2453
|
function createCodeAgent(agentConfig) {
|
|
2454
|
+
return new ToolLoopAgent(createCodeAgentSettings(agentConfig));
|
|
2455
|
+
}
|
|
2456
|
+
function createCodeAgentSettings(agentConfig) {
|
|
2392
2457
|
const {
|
|
2393
2458
|
maxSteps,
|
|
2394
2459
|
allowSubmit,
|
|
@@ -2397,46 +2462,29 @@ function createCodeAgent(agentConfig) {
|
|
|
2397
2462
|
tools: originalTools,
|
|
2398
2463
|
stopWhen: originalStopWhen,
|
|
2399
2464
|
prepareStep: originalPrepareStep,
|
|
2400
|
-
|
|
2465
|
+
instructions: originalSystemInstruction,
|
|
2401
2466
|
...remainingConfig
|
|
2402
2467
|
} = agentConfig;
|
|
2403
2468
|
let agentSettings;
|
|
2404
|
-
let
|
|
2469
|
+
let tools;
|
|
2405
2470
|
if ("environments" in remainingConfig) {
|
|
2406
2471
|
const { environments, environmentToolsDefinition, ...agentSettingsInput } = remainingConfig;
|
|
2407
2472
|
agentSettings = { ...agentSettingsInput };
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
|
|
2412
|
-
`No tools definition provided for environment "${environmentName}". Please provide a tools definition for each environment.`
|
|
2413
|
-
);
|
|
2414
|
-
}
|
|
2415
|
-
const envTools = createToolsForNamedEnvironment(
|
|
2416
|
-
environmentName,
|
|
2417
|
-
environment,
|
|
2418
|
-
environmentToolsDefinition[environmentName]
|
|
2419
|
-
);
|
|
2420
|
-
for (const [toolName, tool] of Object.entries(envTools)) {
|
|
2421
|
-
if (toolName in environmentTools) {
|
|
2422
|
-
throw new Error(
|
|
2423
|
-
`Tool name conflict: The tool name "${toolName}" from environment "${environmentName}" is already used by another environment's tools.`
|
|
2424
|
-
);
|
|
2425
|
-
}
|
|
2426
|
-
environmentTools[toolName] = tool;
|
|
2427
|
-
}
|
|
2428
|
-
}
|
|
2473
|
+
tools = createCodeAgentTools(
|
|
2474
|
+
{ environments, environmentToolsDefinition },
|
|
2475
|
+
originalTools
|
|
2476
|
+
);
|
|
2429
2477
|
} else if ("environment" in remainingConfig) {
|
|
2430
2478
|
const { environment, environmentToolsDefinition, ...agentSettingsInput } = remainingConfig;
|
|
2431
2479
|
agentSettings = { ...agentSettingsInput };
|
|
2432
|
-
|
|
2433
|
-
environment,
|
|
2434
|
-
|
|
2480
|
+
tools = createCodeAgentTools(
|
|
2481
|
+
{ environment, environmentToolsDefinition },
|
|
2482
|
+
originalTools
|
|
2435
2483
|
);
|
|
2436
2484
|
} else {
|
|
2437
2485
|
agentSettings = { ...remainingConfig };
|
|
2486
|
+
tools = originalTools || {};
|
|
2438
2487
|
}
|
|
2439
|
-
const tools = environmentTools && originalTools ? mergeTools(environmentTools, originalTools) : originalTools || environmentTools || {};
|
|
2440
2488
|
if (allowSubmit) {
|
|
2441
2489
|
if (SubmitToolName in tools) {
|
|
2442
2490
|
throw new Error(
|
|
@@ -2464,16 +2512,54 @@ ${stepLog}`, stepCount - 1);
|
|
|
2464
2512
|
} : originalPrepareStep;
|
|
2465
2513
|
const stopWhenCondition = allowSubmit ? [stepCountIs(maxSteps), hasToolCall(SubmitToolName)] : stepCountIs(maxSteps);
|
|
2466
2514
|
const stopWhen = originalStopWhen ? mergeStopWhen(originalStopWhen, stopWhenCondition) : stopWhenCondition;
|
|
2467
|
-
const
|
|
2515
|
+
const instructions = !omitAdditionalInstructions ? mergeSystemInstructions(
|
|
2468
2516
|
originalSystemInstruction,
|
|
2469
2517
|
getAdditionalInstructions({ maxSteps, allowSubmit, tools })
|
|
2470
2518
|
) : originalSystemInstruction;
|
|
2471
|
-
return
|
|
2519
|
+
return {
|
|
2472
2520
|
...agentSettings,
|
|
2473
|
-
|
|
2521
|
+
instructions,
|
|
2474
2522
|
prepareStep,
|
|
2475
2523
|
stopWhen
|
|
2476
|
-
}
|
|
2524
|
+
};
|
|
2525
|
+
}
|
|
2526
|
+
function createCodeAgentTools(agentToolsConfig, originalTools) {
|
|
2527
|
+
if ("environments" in agentToolsConfig) {
|
|
2528
|
+
const { environments, environmentToolsDefinition } = agentToolsConfig;
|
|
2529
|
+
const environmentTools = {};
|
|
2530
|
+
for (const [environmentName, environment] of Object.entries(environments)) {
|
|
2531
|
+
if (!(environmentName in environmentToolsDefinition)) {
|
|
2532
|
+
throw new Error(
|
|
2533
|
+
`No tools definition provided for environment "${environmentName}". Please provide a tools definition for each environment.`
|
|
2534
|
+
);
|
|
2535
|
+
}
|
|
2536
|
+
const envTools = createToolsForNamedEnvironment(
|
|
2537
|
+
environmentName,
|
|
2538
|
+
environment,
|
|
2539
|
+
environmentToolsDefinition[environmentName]
|
|
2540
|
+
);
|
|
2541
|
+
for (const [toolName, tool] of Object.entries(envTools)) {
|
|
2542
|
+
if (toolName in environmentTools) {
|
|
2543
|
+
throw new Error(
|
|
2544
|
+
`Tool name conflict: The tool name "${toolName}" from environment "${environmentName}" is already used by another environment's tools.`
|
|
2545
|
+
);
|
|
2546
|
+
}
|
|
2547
|
+
environmentTools[toolName] = tool;
|
|
2548
|
+
}
|
|
2549
|
+
}
|
|
2550
|
+
return originalTools ? mergeTools(environmentTools, originalTools) : environmentTools;
|
|
2551
|
+
}
|
|
2552
|
+
if ("environment" in agentToolsConfig) {
|
|
2553
|
+
const { environment, environmentToolsDefinition } = agentToolsConfig;
|
|
2554
|
+
const environmentTools = createToolsForEnvironment(
|
|
2555
|
+
environment,
|
|
2556
|
+
environmentToolsDefinition
|
|
2557
|
+
);
|
|
2558
|
+
return originalTools ? mergeTools(environmentTools, originalTools) : environmentTools;
|
|
2559
|
+
}
|
|
2560
|
+
throw new Error(
|
|
2561
|
+
'No environments provided in agent tools configuration. Please provide either "environment" or "environments".'
|
|
2562
|
+
);
|
|
2477
2563
|
}
|
|
2478
2564
|
function mergeTools(baseTools, additionalTools) {
|
|
2479
2565
|
const tools = { ...baseTools };
|
|
@@ -2499,9 +2585,26 @@ function mergeStopWhen(baseStopWhen, additionalStopWhen) {
|
|
|
2499
2585
|
}
|
|
2500
2586
|
return [baseStopWhen, additionalStopWhen];
|
|
2501
2587
|
}
|
|
2502
|
-
function mergeSystemInstructions(
|
|
2503
|
-
if (
|
|
2504
|
-
|
|
2588
|
+
function mergeSystemInstructions(baseInstructions, additionalInstructions) {
|
|
2589
|
+
if (baseInstructions) {
|
|
2590
|
+
if (Array.isArray(baseInstructions)) {
|
|
2591
|
+
return [
|
|
2592
|
+
...baseInstructions,
|
|
2593
|
+
{
|
|
2594
|
+
role: "system",
|
|
2595
|
+
content: additionalInstructions
|
|
2596
|
+
}
|
|
2597
|
+
];
|
|
2598
|
+
}
|
|
2599
|
+
if (typeof baseInstructions === "object") {
|
|
2600
|
+
return {
|
|
2601
|
+
...baseInstructions,
|
|
2602
|
+
content: `${baseInstructions.content.trimEnd()}
|
|
2603
|
+
|
|
2604
|
+
${additionalInstructions}`
|
|
2605
|
+
};
|
|
2606
|
+
}
|
|
2607
|
+
return `${baseInstructions.trimEnd()}
|
|
2505
2608
|
|
|
2506
2609
|
${additionalInstructions}`;
|
|
2507
2610
|
}
|
|
@@ -2526,12 +2629,10 @@ function createEnvironment(environmentName, config) {
|
|
|
2526
2629
|
return new EnvironmentClass(config);
|
|
2527
2630
|
}
|
|
2528
2631
|
export {
|
|
2529
|
-
CopyFileResult,
|
|
2530
2632
|
CopyFileTool,
|
|
2531
2633
|
CopyFileToolInput,
|
|
2532
2634
|
CopyFileToolName,
|
|
2533
2635
|
CopyFileToolOutput,
|
|
2534
|
-
DeleteFileResult,
|
|
2535
2636
|
DeleteFileTool,
|
|
2536
2637
|
DeleteFileToolInput,
|
|
2537
2638
|
DeleteFileToolName,
|
|
@@ -2553,20 +2654,22 @@ export {
|
|
|
2553
2654
|
GlobToolInput,
|
|
2554
2655
|
GlobToolName,
|
|
2555
2656
|
GlobToolOutput,
|
|
2657
|
+
GrepTool,
|
|
2658
|
+
GrepToolInput,
|
|
2659
|
+
GrepToolName,
|
|
2660
|
+
GrepToolOutput,
|
|
2556
2661
|
ListDirectoryTool,
|
|
2557
2662
|
ListDirectoryToolInput,
|
|
2558
2663
|
ListDirectoryToolName,
|
|
2559
2664
|
ListDirectoryToolOutput,
|
|
2560
2665
|
MockFilesystemEnvironment,
|
|
2561
2666
|
MockFilesystemEnvironmentName,
|
|
2562
|
-
MoveFileResult,
|
|
2563
2667
|
MoveFileTool,
|
|
2564
2668
|
MoveFileToolInput,
|
|
2565
2669
|
MoveFileToolName,
|
|
2566
2670
|
MoveFileToolOutput,
|
|
2567
2671
|
NodeFilesystemEnvironment,
|
|
2568
2672
|
NodeFilesystemEnvironmentName,
|
|
2569
|
-
ReadFileResult,
|
|
2570
2673
|
ReadFileTool,
|
|
2571
2674
|
ReadFileToolInput,
|
|
2572
2675
|
ReadFileToolName,
|
|
@@ -2575,7 +2678,6 @@ export {
|
|
|
2575
2678
|
ReadManyFilesToolInput,
|
|
2576
2679
|
ReadManyFilesToolName,
|
|
2577
2680
|
ReadManyFilesToolOutput,
|
|
2578
|
-
RunCommandResult,
|
|
2579
2681
|
RunCommandTool,
|
|
2580
2682
|
RunCommandToolInput,
|
|
2581
2683
|
RunCommandToolName,
|
|
@@ -2586,12 +2688,13 @@ export {
|
|
|
2586
2688
|
SubmitToolOutput,
|
|
2587
2689
|
UnsafeLocalEnvironment,
|
|
2588
2690
|
UnsafeLocalEnvironmentName,
|
|
2589
|
-
WriteFileResult,
|
|
2590
2691
|
WriteFileTool,
|
|
2591
2692
|
WriteFileToolInput,
|
|
2592
2693
|
WriteFileToolName,
|
|
2593
2694
|
WriteFileToolOutput,
|
|
2594
2695
|
createCodeAgent,
|
|
2696
|
+
createCodeAgentSettings,
|
|
2697
|
+
createCodeAgentTools,
|
|
2595
2698
|
createEnvironment,
|
|
2596
2699
|
createEnvironmentTool,
|
|
2597
2700
|
createToolsForEnvironment,
|