ai-code-agents 0.1.0-beta.1

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/dist/index.cjs ADDED
@@ -0,0 +1,2688 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var index_exports = {};
32
+ __export(index_exports, {
33
+ CopyFileResult: () => CopyFileResult,
34
+ CopyFileTool: () => CopyFileTool,
35
+ CopyFileToolInput: () => CopyFileToolInput,
36
+ CopyFileToolName: () => CopyFileToolName,
37
+ CopyFileToolOutput: () => CopyFileToolOutput,
38
+ DeleteFileResult: () => DeleteFileResult,
39
+ DeleteFileTool: () => DeleteFileTool,
40
+ DeleteFileToolInput: () => DeleteFileToolInput,
41
+ DeleteFileToolName: () => DeleteFileToolName,
42
+ DeleteFileToolOutput: () => DeleteFileToolOutput,
43
+ DockerEnvironment: () => DockerEnvironment,
44
+ DockerEnvironmentName: () => DockerEnvironmentName,
45
+ EditFileTool: () => EditFileTool,
46
+ EditFileToolInput: () => EditFileToolInput,
47
+ EditFileToolName: () => EditFileToolName,
48
+ EditFileToolOutput: () => EditFileToolOutput,
49
+ EnvironmentNames: () => EnvironmentNames,
50
+ EnvironmentToolNames: () => EnvironmentToolNames,
51
+ EnvironmentToolSafetyLevels: () => EnvironmentToolSafetyLevels,
52
+ GetProjectFileStructureTool: () => GetProjectFileStructureTool,
53
+ GetProjectFileStructureToolInput: () => GetProjectFileStructureToolInput,
54
+ GetProjectFileStructureToolName: () => GetProjectFileStructureToolName,
55
+ GetProjectFileStructureToolOutput: () => GetProjectFileStructureToolOutput,
56
+ GlobTool: () => GlobTool,
57
+ GlobToolInput: () => GlobToolInput,
58
+ GlobToolName: () => GlobToolName,
59
+ GlobToolOutput: () => GlobToolOutput,
60
+ ListDirectoryTool: () => ListDirectoryTool,
61
+ ListDirectoryToolInput: () => ListDirectoryToolInput,
62
+ ListDirectoryToolName: () => ListDirectoryToolName,
63
+ ListDirectoryToolOutput: () => ListDirectoryToolOutput,
64
+ MockFilesystemEnvironment: () => MockFilesystemEnvironment,
65
+ MockFilesystemEnvironmentName: () => MockFilesystemEnvironmentName,
66
+ MoveFileResult: () => MoveFileResult,
67
+ MoveFileTool: () => MoveFileTool,
68
+ MoveFileToolInput: () => MoveFileToolInput,
69
+ MoveFileToolName: () => MoveFileToolName,
70
+ MoveFileToolOutput: () => MoveFileToolOutput,
71
+ NodeFilesystemEnvironment: () => NodeFilesystemEnvironment,
72
+ NodeFilesystemEnvironmentName: () => NodeFilesystemEnvironmentName,
73
+ ReadFileResult: () => ReadFileResult,
74
+ ReadFileTool: () => ReadFileTool,
75
+ ReadFileToolInput: () => ReadFileToolInput,
76
+ ReadFileToolName: () => ReadFileToolName,
77
+ ReadFileToolOutput: () => ReadFileToolOutput,
78
+ ReadManyFilesTool: () => ReadManyFilesTool,
79
+ ReadManyFilesToolInput: () => ReadManyFilesToolInput,
80
+ ReadManyFilesToolName: () => ReadManyFilesToolName,
81
+ ReadManyFilesToolOutput: () => ReadManyFilesToolOutput,
82
+ RunCommandResult: () => RunCommandResult,
83
+ RunCommandTool: () => RunCommandTool,
84
+ RunCommandToolInput: () => RunCommandToolInput,
85
+ RunCommandToolName: () => RunCommandToolName,
86
+ RunCommandToolOutput: () => RunCommandToolOutput,
87
+ UnsafeLocalEnvironment: () => UnsafeLocalEnvironment,
88
+ UnsafeLocalEnvironmentName: () => UnsafeLocalEnvironmentName,
89
+ WriteFileResult: () => WriteFileResult,
90
+ WriteFileTool: () => WriteFileTool,
91
+ WriteFileToolInput: () => WriteFileToolInput,
92
+ WriteFileToolName: () => WriteFileToolName,
93
+ WriteFileToolOutput: () => WriteFileToolOutput,
94
+ createCodeAgent: () => createCodeAgent,
95
+ createEnvironment: () => createEnvironment,
96
+ createEnvironmentTool: () => createEnvironmentTool,
97
+ createToolsForEnvironment: () => createToolsForEnvironment,
98
+ createToolsForNamedEnvironment: () => createToolsForNamedEnvironment
99
+ });
100
+ module.exports = __toCommonJS(index_exports);
101
+
102
+ // src/environments/docker-environment.ts
103
+ var import_node_child_process = require("child_process");
104
+
105
+ // src/util/escape-command-arg.ts
106
+ function escapeCommandArg(arg) {
107
+ if ("" === arg) {
108
+ return "''";
109
+ }
110
+ return `'${arg.replace(/'/g, "'\\''")}'`;
111
+ }
112
+
113
+ // src/util/validate-relative-path.ts
114
+ var path = __toESM(require("path"), 1);
115
+ function validateRelativePath(filePath) {
116
+ if (path.isAbsolute(filePath)) {
117
+ throw new Error("Absolute paths are not allowed.");
118
+ }
119
+ if (filePath.startsWith("~")) {
120
+ throw new Error('Paths starting with "~" are not allowed.');
121
+ }
122
+ if (filePath.includes("\0")) {
123
+ throw new Error("Paths must not contain null bytes.");
124
+ }
125
+ const normalizedPath = path.normalize(filePath);
126
+ if (normalizedPath.startsWith("..")) {
127
+ throw new Error("Path traversal is not allowed.");
128
+ }
129
+ }
130
+
131
+ // src/environments/filesystem-environment-base.ts
132
+ var FilesystemEnvironmentBase = class {
133
+ _envConfig;
134
+ /**
135
+ * Constructs a new environment instance.
136
+ *
137
+ * @param config - Environment configuration.
138
+ */
139
+ constructor(config) {
140
+ this._envConfig = config;
141
+ }
142
+ /**
143
+ * Reads the content of a file at the specified path.
144
+ *
145
+ * @param path - The path to the file to read, relative to the project directory.
146
+ * @returns A promise that resolves to a ReadFileResult.
147
+ */
148
+ async readFile(path5) {
149
+ validateRelativePath(path5);
150
+ if (!await this.fileExists(path5)) {
151
+ throw new Error(`File not found: ${path5}`);
152
+ }
153
+ const content = await this.readFileContent(path5);
154
+ return {
155
+ path: path5,
156
+ content
157
+ };
158
+ }
159
+ /**
160
+ * Writes content to a file at the specified path.
161
+ *
162
+ * If a file is already present at the path, it will be overwritten.
163
+ *
164
+ * @param path - The path to the file to write, relative to the project directory.
165
+ * @param content - The content to write to the file.
166
+ * @returns A promise that resolves to a WriteFileResult.
167
+ */
168
+ async writeFile(path5, content) {
169
+ validateRelativePath(path5);
170
+ await this.writeFileContent(path5, content);
171
+ return {
172
+ path: path5,
173
+ message: "File written successfully."
174
+ };
175
+ }
176
+ /**
177
+ * Deletes a file at the specified path.
178
+ *
179
+ * @param path - The path to the file to delete, relative to the project directory.
180
+ * @returns A promise that resolves to a DeleteFileResult.
181
+ */
182
+ async deleteFile(path5) {
183
+ validateRelativePath(path5);
184
+ if (!await this.fileExists(path5)) {
185
+ return {
186
+ path: path5,
187
+ message: "File was already deleted."
188
+ };
189
+ }
190
+ await this.deleteFileContent(path5);
191
+ return {
192
+ path: path5,
193
+ message: "File deleted successfully."
194
+ };
195
+ }
196
+ /**
197
+ * Moves a file from a source path to a destination path.
198
+ *
199
+ * If a file is already present at the destination path, it will be overwritten.
200
+ *
201
+ * @param sourcePath - The path to the file to move.
202
+ * @param destinationPath - The path to move the file to.
203
+ * @returns A promise that resolves to a MoveFileResult.
204
+ */
205
+ async moveFile(sourcePath, destinationPath) {
206
+ validateRelativePath(sourcePath);
207
+ validateRelativePath(destinationPath);
208
+ if (!await this.fileExists(sourcePath)) {
209
+ throw new Error(`File not found: ${sourcePath}`);
210
+ }
211
+ await this.moveFileContent(sourcePath, destinationPath);
212
+ return {
213
+ sourcePath,
214
+ destinationPath,
215
+ message: "File moved successfully."
216
+ };
217
+ }
218
+ /**
219
+ * Copies a file from a source path to a destination path.
220
+ *
221
+ * If a file is already present at the destination path, it will be overwritten.
222
+ *
223
+ * @param sourcePath - The path to the file to copy.
224
+ * @param destinationPath - The path to copy the file to.
225
+ * @returns A promise that resolves to a CopyFileResult.
226
+ */
227
+ async copyFile(sourcePath, destinationPath) {
228
+ validateRelativePath(sourcePath);
229
+ validateRelativePath(destinationPath);
230
+ if (!await this.fileExists(sourcePath)) {
231
+ throw new Error(`File not found: ${sourcePath}`);
232
+ }
233
+ await this.copyFileContent(sourcePath, destinationPath);
234
+ return {
235
+ sourcePath,
236
+ destinationPath,
237
+ message: "File copied successfully."
238
+ };
239
+ }
240
+ /**
241
+ * Moves the content of a file from a source path to a destination path, relative to the project directory.
242
+ *
243
+ * When this method is called, it is guaranteed that the source file exists.
244
+ * This method unconditionally moves the content, even if a file already exists at the destination path.
245
+ *
246
+ * @param relativeSourcePath - The path to the file to move, relative to the project directory.
247
+ * @param relativeDestinationPath - The path to move the file to, relative to the project directory.
248
+ */
249
+ async moveFileContent(relativeSourcePath, relativeDestinationPath) {
250
+ const content = await this.readFileContent(relativeSourcePath);
251
+ this.writeFileContent(relativeDestinationPath, content);
252
+ this.deleteFileContent(relativeSourcePath);
253
+ }
254
+ /**
255
+ * Copies the content of a file from a source path to a destination path, relative to the project directory.
256
+ *
257
+ * When this method is called, it is guaranteed that the source file exists.
258
+ * This method unconditionally copies the content, even if a file already exists at the destination path.
259
+ *
260
+ * @param relativeSourcePath - The path to the file to copy, relative to the project directory.
261
+ * @param relativeDestinationPath - The path to copy the file to, relative to the project directory.
262
+ */
263
+ async copyFileContent(relativeSourcePath, relativeDestinationPath) {
264
+ const content = await this.readFileContent(relativeSourcePath);
265
+ this.writeFileContent(relativeDestinationPath, content);
266
+ }
267
+ };
268
+
269
+ // src/environments/command-line-environment-base.ts
270
+ var CommandLineEnvironmentBase = class extends FilesystemEnvironmentBase {
271
+ /**
272
+ * Runs a CLI command in environment.
273
+ *
274
+ * @param command - The command to run.
275
+ * @returns A promise that resolves to a RunCommandResult.
276
+ */
277
+ async runCommand(command) {
278
+ const [exitCode, stdout, stderr] = await this.executeCommand(command);
279
+ return {
280
+ command,
281
+ exitCode,
282
+ stdout,
283
+ stderr
284
+ };
285
+ }
286
+ };
287
+
288
+ // src/environments/unix-environment-base.ts
289
+ var UnixEnvironmentBase = class extends CommandLineEnvironmentBase {
290
+ /**
291
+ * Checks whether a file exists at the specified path relative to the project directory.
292
+ *
293
+ * @param relativePath - The path to the file to check, relative to the project directory.
294
+ * @returns True if the file exists, false otherwise.
295
+ */
296
+ async fileExists(relativePath) {
297
+ const command = `if [ -e ${escapeCommandArg(relativePath)} ]; then echo "yes"; else echo "no"; fi`;
298
+ const { exitCode, stdout } = await this.runCommand(command);
299
+ return exitCode === 0 && stdout.trim() === "yes";
300
+ }
301
+ /**
302
+ * Gets the content of a file at the specified path, relative to the project directory.
303
+ *
304
+ * When this method is called, it is guaranteed that the file exists.
305
+ *
306
+ * @param relativePath - The path to the file to read, relative to the project directory.
307
+ * @returns The content of the file.
308
+ */
309
+ async readFileContent(relativePath) {
310
+ const command = `cat ${escapeCommandArg(relativePath)}`;
311
+ const { exitCode, stdout } = await this.runCommand(command);
312
+ return exitCode === 0 ? stdout : "";
313
+ }
314
+ /**
315
+ * Writes content to a file at the specified path, relative to the project directory.
316
+ *
317
+ * This method unconditionally writes the content, even if a file already exists at the path, or if the file is new.
318
+ *
319
+ * @param relativePath - The path to the file to write, relative to the project directory.
320
+ * @param content - The content to write to the file.
321
+ */
322
+ async writeFileContent(relativePath, content) {
323
+ const command = `sh -c "echo ${escapeCommandArg(
324
+ content
325
+ )} > ${escapeCommandArg(relativePath)}"`;
326
+ const { exitCode, stderr } = await this.runCommand(command);
327
+ if (exitCode !== 0) {
328
+ throw new Error(`Failed to write file: ${stderr || "Unknown error"}`);
329
+ }
330
+ }
331
+ /**
332
+ * Deletes a file at the specified path, relative to the project directory.
333
+ *
334
+ * When this method is called, it is guaranteed that the file exists.
335
+ *
336
+ * @param relativePath - The path to the file to delete, relative to the project directory.
337
+ */
338
+ async deleteFileContent(relativePath) {
339
+ const command = `rm ${escapeCommandArg(relativePath)}`;
340
+ const { exitCode, stderr } = await this.runCommand(command);
341
+ if (exitCode !== 0) {
342
+ throw new Error(`Failed to delete file: ${stderr || "Unknown error"}`);
343
+ }
344
+ }
345
+ /**
346
+ * Moves the content of a file from a source path to a destination path, relative to the project directory.
347
+ *
348
+ * When this method is called, it is guaranteed that the source file exists.
349
+ * This method unconditionally moves the content, even if a file already exists at the destination path.
350
+ *
351
+ * @param relativeSourcePath - The path to the file to move, relative to the project directory.
352
+ * @param relativeDestinationPath - The path to move the file to, relative to the project directory.
353
+ */
354
+ async moveFileContent(relativeSourcePath, relativeDestinationPath) {
355
+ const command = `mv ${escapeCommandArg(relativeSourcePath)} ${escapeCommandArg(
356
+ relativeDestinationPath
357
+ )}`;
358
+ const { exitCode, stderr } = await this.runCommand(command);
359
+ if (exitCode !== 0) {
360
+ throw new Error(`Failed to move file: ${stderr || "Unknown error"}`);
361
+ }
362
+ }
363
+ /**
364
+ * Copies the content of a file from a source path to a destination path, relative to the project directory.
365
+ *
366
+ * When this method is called, it is guaranteed that the source file exists.
367
+ * This method unconditionally copies the content, even if a file already exists at the destination path.
368
+ *
369
+ * @param relativeSourcePath - The path to the file to copy, relative to the project directory.
370
+ * @param relativeDestinationPath - The path to copy the file to, relative to the project directory.
371
+ */
372
+ async copyFileContent(relativeSourcePath, relativeDestinationPath) {
373
+ const command = `cp ${escapeCommandArg(relativeSourcePath)} ${escapeCommandArg(
374
+ relativeDestinationPath
375
+ )}`;
376
+ const result = await this.runCommand(command);
377
+ if (result.exitCode !== 0) {
378
+ throw new Error(
379
+ `Failed to copy file: ${result.stderr || "Unknown error"}`
380
+ );
381
+ }
382
+ }
383
+ };
384
+
385
+ // src/environments/docker-environment.ts
386
+ var DockerEnvironmentName = "docker";
387
+ var DockerEnvironment = class extends UnixEnvironmentBase {
388
+ _commandPrefix;
389
+ /**
390
+ * Constructs a new environment instance.
391
+ *
392
+ * @param config - Environment configuration.
393
+ */
394
+ constructor(config) {
395
+ super(config);
396
+ const { directoryPath } = this._envConfig;
397
+ this._commandPrefix = directoryPath ? `cd ${escapeCommandArg(directoryPath)} && ` : "";
398
+ }
399
+ /**
400
+ * Gets the environment name.
401
+ *
402
+ * @returns The environment name.
403
+ */
404
+ get name() {
405
+ return DockerEnvironmentName;
406
+ }
407
+ /**
408
+ * Executes a command in the environment and returns the exit code, stdout, and stderr.
409
+ *
410
+ * @param command - The command to execute.
411
+ * @returns A promise that resolves to a tuple containing the exit code, stdout, and stderr.
412
+ */
413
+ async executeCommand(command) {
414
+ return new Promise((resolve) => {
415
+ (0, import_node_child_process.exec)(
416
+ `docker exec ${this._envConfig.containerId} ${this._commandPrefix}${command}`,
417
+ (error, stdout, stderr) => {
418
+ const exitCode = error ? error.code ?? 1 : 0;
419
+ resolve([exitCode, stdout, stderr]);
420
+ }
421
+ );
422
+ });
423
+ }
424
+ };
425
+
426
+ // src/environments/mock-filesystem-environment.ts
427
+ var import_node_path = __toESM(require("path"), 1);
428
+ var MockFilesystemEnvironmentName = "mock-filesystem";
429
+ var MockFilesystemEnvironment = class extends FilesystemEnvironmentBase {
430
+ files;
431
+ _preparePath;
432
+ /**
433
+ * Constructs a new environment instance.
434
+ *
435
+ * @param config - Environment configuration.
436
+ */
437
+ constructor(config = {}) {
438
+ super(config);
439
+ const { initialFiles, directoryPath } = this._envConfig;
440
+ this.files = initialFiles ?? /* @__PURE__ */ new Map();
441
+ this._preparePath = directoryPath ? (filePath) => import_node_path.default.join(directoryPath, filePath) : (filePath) => filePath;
442
+ }
443
+ /**
444
+ * Gets the environment name.
445
+ *
446
+ * @returns The environment name.
447
+ */
448
+ get name() {
449
+ return MockFilesystemEnvironmentName;
450
+ }
451
+ /**
452
+ * Checks whether a file exists at the specified path relative to the project directory.
453
+ *
454
+ * @param relativePath - The path to the file to check, relative to the project directory.
455
+ * @returns True if the file exists, false otherwise.
456
+ */
457
+ async fileExists(relativePath) {
458
+ return this.files.has(this._preparePath(relativePath));
459
+ }
460
+ /**
461
+ * Gets the content of a file at the specified path, relative to the project directory.
462
+ *
463
+ * When this method is called, it is guaranteed that the file exists.
464
+ *
465
+ * @param relativePath - The path to the file to read, relative to the project directory.
466
+ * @returns The content of the file.
467
+ */
468
+ async readFileContent(relativePath) {
469
+ return this.files.get(this._preparePath(relativePath)) ?? "";
470
+ }
471
+ /**
472
+ * Writes content to a file at the specified path, relative to the project directory.
473
+ *
474
+ * This method unconditionally writes the content, even if a file already exists at the path, or if the file is new.
475
+ *
476
+ * @param relativePath - The path to the file to write, relative to the project directory.
477
+ * @param content - The content to write to the file.
478
+ */
479
+ async writeFileContent(relativePath, content) {
480
+ this.files.set(this._preparePath(relativePath), content);
481
+ }
482
+ /**
483
+ * Deletes a file at the specified path, relative to the project directory.
484
+ *
485
+ * @param relativePath - The path to the file to delete, relative to the project directory.
486
+ */
487
+ async deleteFileContent(relativePath) {
488
+ this.files.delete(this._preparePath(relativePath));
489
+ }
490
+ };
491
+
492
+ // src/environments/node-filesystem-environment.ts
493
+ var import_promises = __toESM(require("fs/promises"), 1);
494
+ var import_node_path2 = __toESM(require("path"), 1);
495
+ var NodeFilesystemEnvironmentName = "node-filesystem";
496
+ var NodeFilesystemEnvironment = class extends FilesystemEnvironmentBase {
497
+ /**
498
+ * Constructs a new NodeFilesystemEnvironment instance.
499
+ *
500
+ * @param config - Environment configuration including the mandatory directoryPath.
501
+ */
502
+ constructor(config) {
503
+ if (!config.directoryPath) {
504
+ throw new Error("The directory path must be provided");
505
+ }
506
+ super(config);
507
+ }
508
+ /**
509
+ * Gets the environment name.
510
+ *
511
+ * @returns The environment name.
512
+ */
513
+ get name() {
514
+ return NodeFilesystemEnvironmentName;
515
+ }
516
+ /**
517
+ * Checks whether a file exists at the specified path relative to the project directory.
518
+ *
519
+ * @param relativePath - The path to the file to check, relative to the project directory.
520
+ * @returns True if the file exists, false otherwise.
521
+ */
522
+ async fileExists(relativePath) {
523
+ const absolutePath = import_node_path2.default.join(this._envConfig.directoryPath, relativePath);
524
+ try {
525
+ await import_promises.default.stat(absolutePath);
526
+ return true;
527
+ } catch {
528
+ return false;
529
+ }
530
+ }
531
+ /**
532
+ * Gets the content of a file at the specified path, relative to the project directory.
533
+ *
534
+ * When this method is called, it is guaranteed that the file exists.
535
+ *
536
+ * @param relativePath - The path to the file to read, relative to the project directory.
537
+ * @returns The content of the file.
538
+ */
539
+ async readFileContent(relativePath) {
540
+ const absolutePath = import_node_path2.default.join(this._envConfig.directoryPath, relativePath);
541
+ return import_promises.default.readFile(absolutePath, "utf-8");
542
+ }
543
+ /**
544
+ * Writes content to a file at the specified path, relative to the project directory.
545
+ *
546
+ * This method unconditionally writes the content, even if a file already exists at the path, or if the file is new.
547
+ *
548
+ * @param relativePath - The path to the file to write, relative to the project directory.
549
+ * @param content - The content to write to the file.
550
+ */
551
+ async writeFileContent(relativePath, content) {
552
+ const absolutePath = import_node_path2.default.join(this._envConfig.directoryPath, relativePath);
553
+ await import_promises.default.writeFile(absolutePath, content, "utf-8");
554
+ }
555
+ /**
556
+ * Deletes a file at the specified path, relative to the project directory.
557
+ *
558
+ * When this method is called, it is guaranteed that the file exists.
559
+ *
560
+ * @param relativePath - The path to the file to delete, relative to the project directory.
561
+ */
562
+ async deleteFileContent(relativePath) {
563
+ const absolutePath = import_node_path2.default.join(this._envConfig.directoryPath, relativePath);
564
+ await import_promises.default.rm(absolutePath);
565
+ }
566
+ /**
567
+ * Moves the content of a file from a source path to a destination path, relative to the project directory.
568
+ *
569
+ * When this method is called, it is guaranteed that the source file exists.
570
+ * This method unconditionally moves the content, even if a file already exists at the destination path.
571
+ *
572
+ * @param relativeSourcePath - The path to the file to move, relative to the project directory.
573
+ * @param relativeDestinationPath - The path to move the file to, relative to the project directory.
574
+ */
575
+ async moveFileContent(relativeSourcePath, relativeDestinationPath) {
576
+ const sourcePath = import_node_path2.default.join(
577
+ this._envConfig.directoryPath,
578
+ relativeSourcePath
579
+ );
580
+ const destinationPath = import_node_path2.default.join(
581
+ this._envConfig.directoryPath,
582
+ relativeDestinationPath
583
+ );
584
+ await import_promises.default.rename(sourcePath, destinationPath);
585
+ }
586
+ };
587
+
588
+ // src/environments/unsafe-local-environment.ts
589
+ var import_node_child_process2 = require("child_process");
590
+ var UnsafeLocalEnvironmentName = "unsafe-local";
591
+ var UnsafeLocalEnvironment = class extends UnixEnvironmentBase {
592
+ _commandPrefix;
593
+ /**
594
+ * Constructs a new environment instance.
595
+ *
596
+ * @param config - Environment configuration.
597
+ */
598
+ constructor(config) {
599
+ const { directoryPath } = config;
600
+ if (!directoryPath) {
601
+ throw new Error("The directory path must be provided");
602
+ }
603
+ if (!directoryPath.startsWith("/")) {
604
+ throw new Error('The directory path must be absolute (start with "/")');
605
+ }
606
+ super(config);
607
+ this._commandPrefix = `cd ${escapeCommandArg(directoryPath)} && `;
608
+ }
609
+ /**
610
+ * Gets the environment name.
611
+ *
612
+ * @returns The environment name.
613
+ */
614
+ get name() {
615
+ return UnsafeLocalEnvironmentName;
616
+ }
617
+ /**
618
+ * Executes a command in the environment and returns the exit code, stdout, and stderr.
619
+ *
620
+ * @param command - The command to execute.
621
+ * @returns A promise that resolves to a tuple containing the exit code, stdout, and stderr.
622
+ */
623
+ async executeCommand(command) {
624
+ return new Promise((resolve) => {
625
+ (0, import_node_child_process2.exec)(`${this._commandPrefix}${command}`, (error, stdout, stderr) => {
626
+ const exitCode = error ? error.code ?? 1 : 0;
627
+ resolve([exitCode, stdout, stderr]);
628
+ });
629
+ });
630
+ }
631
+ };
632
+
633
+ // src/tools/copy-file-tool.ts
634
+ var import_zod = require("zod");
635
+
636
+ // src/types.ts
637
+ var z = __toESM(require("zod"), 1);
638
+ var ReadFileResult = z.object({
639
+ path: z.string().meta({
640
+ description: "The path to the file that was read."
641
+ }),
642
+ content: z.string().meta({
643
+ description: "The content of the file that was read."
644
+ })
645
+ });
646
+ var WriteFileResult = z.object({
647
+ path: z.string().meta({
648
+ description: "The path to the file that was written."
649
+ }),
650
+ message: z.string().meta({
651
+ description: "A message indicating the result of the write operation."
652
+ })
653
+ });
654
+ var DeleteFileResult = z.object({
655
+ path: z.string().meta({
656
+ description: "The path to the file that was deleted."
657
+ }),
658
+ message: z.string().meta({
659
+ description: "A message indicating the result of the delete operation."
660
+ })
661
+ });
662
+ var MoveFileResult = z.object({
663
+ sourcePath: z.string().meta({
664
+ description: "The original path of the file that was moved."
665
+ }),
666
+ destinationPath: z.string().meta({
667
+ description: "The new path of the file that was moved to."
668
+ }),
669
+ message: z.string().meta({
670
+ description: "A message indicating the result of the move operation."
671
+ })
672
+ });
673
+ var CopyFileResult = z.object({
674
+ sourcePath: z.string().meta({
675
+ description: "The original path of the file that was copied."
676
+ }),
677
+ destinationPath: z.string().meta({
678
+ description: "The new path of the file that was copied to."
679
+ }),
680
+ message: z.string().meta({
681
+ description: "A message indicating the result of the copy operation."
682
+ })
683
+ });
684
+ var RunCommandResult = z.object({
685
+ command: z.string().meta({
686
+ description: "The command that was executed."
687
+ }),
688
+ exitCode: z.number().meta({
689
+ description: "The exit code of the command."
690
+ }),
691
+ stdout: z.string().meta({
692
+ description: "The standard output of the command."
693
+ }),
694
+ stderr: z.string().meta({
695
+ description: "The standard error output of the command."
696
+ })
697
+ });
698
+
699
+ // src/tools/tool-base.ts
700
+ var ToolBase = class {
701
+ _toolConfig;
702
+ _name;
703
+ _description;
704
+ _inputSchema;
705
+ _outputSchema;
706
+ _needsApproval;
707
+ /**
708
+ * Constructs a new tool instance.
709
+ *
710
+ * @param toolConfig - Optional tool config, can be used to override some defaults.
711
+ */
712
+ constructor(toolConfig) {
713
+ const {
714
+ name: defaultName,
715
+ description: defaultDescription,
716
+ inputSchema,
717
+ outputSchema,
718
+ needsApproval: defaultNeedsApproval
719
+ } = this.getMetadata();
720
+ this._name = toolConfig?.name || defaultName;
721
+ this._description = toolConfig?.description || defaultDescription;
722
+ this._inputSchema = inputSchema;
723
+ this._outputSchema = outputSchema;
724
+ this._needsApproval = toolConfig?.needsApproval !== void 0 ? toolConfig.needsApproval : defaultNeedsApproval;
725
+ }
726
+ /**
727
+ * Gets the tool name.
728
+ *
729
+ * @returns The tool name.
730
+ */
731
+ get name() {
732
+ return this._name;
733
+ }
734
+ /**
735
+ * Gets the tool description.
736
+ *
737
+ * @returns The tool description.
738
+ */
739
+ get description() {
740
+ return this._description;
741
+ }
742
+ /**
743
+ * Gets the input schema for the tool.
744
+ *
745
+ * @returns The input schema.
746
+ */
747
+ get inputSchema() {
748
+ return this._inputSchema;
749
+ }
750
+ /**
751
+ * Gets the input schema for the tool.
752
+ *
753
+ * @returns The input schema.
754
+ */
755
+ get outputSchema() {
756
+ return this._outputSchema;
757
+ }
758
+ /**
759
+ * Gets whether the tool needs approval before use.
760
+ *
761
+ * @returns True if the tool needs approval, false otherwise.
762
+ */
763
+ get needsApproval() {
764
+ return this._needsApproval;
765
+ }
766
+ };
767
+
768
+ // src/tools/environment-tool-base.ts
769
+ var EnvironmentToolBase = class extends ToolBase {
770
+ _environment;
771
+ /**
772
+ * Constructs a new `EnvironmentToolBase` instance.
773
+ *
774
+ * @param environment - The execution environment to apply the tool in.
775
+ * @param toolConfig - Optional tool config, can be used to override some defaults.
776
+ */
777
+ constructor(environment, toolConfig) {
778
+ super(toolConfig);
779
+ this._environment = environment;
780
+ }
781
+ /**
782
+ * Gets the current execution environment for the tool.
783
+ *
784
+ * @returns The current execution environment.
785
+ */
786
+ get environment() {
787
+ return this._environment;
788
+ }
789
+ /**
790
+ * Executes the tool with the given input.
791
+ *
792
+ * @param input - The input for the tool.
793
+ * @param _options - Options from the tool call.
794
+ * @returns A promise that resolves to the tool execution result.
795
+ */
796
+ execute(input, _options) {
797
+ return this.executeForEnvironment(this._environment, input);
798
+ }
799
+ };
800
+
801
+ // src/tools/copy-file-tool.ts
802
+ var CopyFileToolName = "copy_file";
803
+ var CopyFileToolInput = import_zod.z.object({
804
+ sourcePath: import_zod.z.string().meta({
805
+ description: "The path to the file to copy, relative to the project directory."
806
+ }),
807
+ destinationPath: import_zod.z.string().meta({
808
+ 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."
809
+ })
810
+ });
811
+ var CopyFileToolOutput = CopyFileResult;
812
+ var CopyFileTool = class extends EnvironmentToolBase {
813
+ /**
814
+ * Returns the metadata for the tool.
815
+ *
816
+ * The name, description, and needsApproval properties are defaults which can be overridden in the constructor.
817
+ *
818
+ * @returns The tool metadata.
819
+ */
820
+ getMetadata() {
821
+ return {
822
+ name: CopyFileToolName,
823
+ description: "Copies a file from a source path to a destination path.",
824
+ inputSchema: CopyFileToolInput,
825
+ outputSchema: CopyFileToolOutput,
826
+ needsApproval: false
827
+ };
828
+ }
829
+ /**
830
+ * Executes the tool in the given execution environment with the given input.
831
+ *
832
+ * @param env - The execution environment to use.
833
+ * @param input - The input for the tool.
834
+ * @returns A promise that resolves to the tool execution result.
835
+ */
836
+ executeForEnvironment(env, input) {
837
+ return env.copyFile(input.sourcePath, input.destinationPath);
838
+ }
839
+ /**
840
+ * Converts the tool output to a format suitable for model consumption.
841
+ *
842
+ * @param output - The output from the tool execution.
843
+ * @returns The formatted tool result.
844
+ */
845
+ toModelOutput(output) {
846
+ return {
847
+ type: "text",
848
+ value: `File \`${output.sourcePath}\` copied successfully to \`${output.destinationPath}\`.`
849
+ };
850
+ }
851
+ /**
852
+ * Gets the examples for the tool.
853
+ *
854
+ * @returns The tool examples.
855
+ */
856
+ get examples() {
857
+ return [
858
+ {
859
+ input: {
860
+ sourcePath: "src/index.ts",
861
+ destinationPath: "index.ts"
862
+ },
863
+ output: "File `src/index.ts` copied successfully to `index.ts`."
864
+ }
865
+ ];
866
+ }
867
+ };
868
+
869
+ // src/tools/delete-file-tool.ts
870
+ var import_zod2 = require("zod");
871
+ var DeleteFileToolName = "delete_file";
872
+ var DeleteFileToolInput = import_zod2.z.object({
873
+ path: import_zod2.z.string().meta({
874
+ description: "The path to the file to delete, relative to the project directory."
875
+ })
876
+ });
877
+ var DeleteFileToolOutput = DeleteFileResult;
878
+ var DeleteFileTool = class extends EnvironmentToolBase {
879
+ /**
880
+ * Returns the metadata for the tool.
881
+ *
882
+ * The name, description, and needsApproval properties are defaults which can be overridden in the constructor.
883
+ *
884
+ * @returns The tool metadata.
885
+ */
886
+ getMetadata() {
887
+ return {
888
+ name: DeleteFileToolName,
889
+ description: "Deletes the file at the specified path.",
890
+ inputSchema: DeleteFileToolInput,
891
+ outputSchema: DeleteFileToolOutput,
892
+ needsApproval: true
893
+ };
894
+ }
895
+ /**
896
+ * Executes the tool in the given execution environment with the given input.
897
+ *
898
+ * @param env - The execution environment to use.
899
+ * @param input - The input for the tool.
900
+ * @returns A promise that resolves to the tool execution result.
901
+ */
902
+ executeForEnvironment(env, input) {
903
+ return env.deleteFile(input.path);
904
+ }
905
+ /**
906
+ * Converts the tool output to a format suitable for model consumption.
907
+ *
908
+ * @param output - The output from the tool execution.
909
+ * @returns The formatted tool result.
910
+ */
911
+ toModelOutput(output) {
912
+ return {
913
+ type: "text",
914
+ value: `File \`${output.path}\` deleted successfully.`
915
+ };
916
+ }
917
+ /**
918
+ * Gets the examples for the tool.
919
+ *
920
+ * @returns The tool examples.
921
+ */
922
+ get examples() {
923
+ return [
924
+ {
925
+ input: {
926
+ path: "src/components/Chart.tsx"
927
+ },
928
+ output: "File `src/components/Chart.tsx` deleted successfully."
929
+ }
930
+ ];
931
+ }
932
+ };
933
+
934
+ // src/tools/edit-file-tool.ts
935
+ var import_zod3 = require("zod");
936
+ var EditFileToolName = "edit_file";
937
+ var EditFileToolInput = import_zod3.z.object({
938
+ path: import_zod3.z.string().meta({
939
+ description: "The path to the file to edit, relative to the project directory."
940
+ }),
941
+ oldString: import_zod3.z.string().meta({
942
+ description: "The exact string to replace in the file."
943
+ }),
944
+ newString: import_zod3.z.string().meta({
945
+ description: "The string to replace the old string with."
946
+ }),
947
+ replaceAll: import_zod3.z.boolean().optional().meta({
948
+ description: "Whether to replace all occurrences of the old string. Defaults to false."
949
+ })
950
+ });
951
+ var EditFileToolOutput = import_zod3.z.object({
952
+ path: import_zod3.z.string().meta({
953
+ description: "The path to the file that was edited."
954
+ }),
955
+ oldString: import_zod3.z.string().meta({
956
+ description: "The old string that was replaced."
957
+ }),
958
+ newString: import_zod3.z.string().meta({
959
+ description: "The new string that replaced the old string."
960
+ }),
961
+ replacements: import_zod3.z.number().meta({
962
+ description: "The number of replacements made."
963
+ }),
964
+ message: import_zod3.z.string().meta({
965
+ description: "A message indicating the result of the edit operation."
966
+ })
967
+ });
968
+ function escapeRegExp(string2) {
969
+ return string2.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
970
+ }
971
+ var EditFileTool = class extends EnvironmentToolBase {
972
+ /**
973
+ * Returns the metadata for the tool.
974
+ *
975
+ * The name, description, and needsApproval properties are defaults which can be overridden in the constructor.
976
+ *
977
+ * @returns The tool metadata.
978
+ */
979
+ getMetadata() {
980
+ return {
981
+ name: EditFileToolName,
982
+ description: "Edits a file by replacing strings.",
983
+ inputSchema: EditFileToolInput,
984
+ outputSchema: EditFileToolOutput,
985
+ needsApproval: true
986
+ };
987
+ }
988
+ /**
989
+ * Executes the tool in the given execution environment with the given input.
990
+ *
991
+ * @param env - The execution environment to use.
992
+ * @param input - The input for the tool.
993
+ * @returns A promise that resolves to the tool execution result.
994
+ */
995
+ async executeForEnvironment(env, input) {
996
+ const { path: path5, oldString, newString, replaceAll = false } = input;
997
+ const readResult = await env.readFile(path5);
998
+ let content = readResult.content;
999
+ let replacements = 0;
1000
+ if (replaceAll) {
1001
+ const escapedOldString = escapeRegExp(oldString);
1002
+ const regex = new RegExp(escapedOldString, "g");
1003
+ const matches = content.match(regex);
1004
+ replacements = matches ? matches.length : 0;
1005
+ content = content.replace(regex, newString);
1006
+ } else {
1007
+ const index = content.indexOf(oldString);
1008
+ if (index !== -1) {
1009
+ content = content.substring(0, index) + newString + content.substring(index + oldString.length);
1010
+ replacements = 1;
1011
+ }
1012
+ }
1013
+ await env.writeFile(path5, content);
1014
+ const message = replacements > 0 ? `Successfully made ${replacements} replacement(s) in file.` : "No replacements made - old string not found.";
1015
+ return {
1016
+ path: path5,
1017
+ oldString,
1018
+ newString,
1019
+ replacements,
1020
+ message
1021
+ };
1022
+ }
1023
+ /**
1024
+ * Converts the tool output to a format suitable for model consumption.
1025
+ *
1026
+ * @param output - The output from the tool execution.
1027
+ * @returns The formatted tool result.
1028
+ */
1029
+ toModelOutput(output) {
1030
+ return {
1031
+ type: "text",
1032
+ value: `Edited file \`${output.path}\` with ${output.replacements} replacement(s).`
1033
+ };
1034
+ }
1035
+ /**
1036
+ * Gets the examples for the tool.
1037
+ *
1038
+ * @returns The tool examples.
1039
+ */
1040
+ get examples() {
1041
+ return [
1042
+ {
1043
+ input: {
1044
+ path: "src/example.ts",
1045
+ oldString: 'console.log("hello");',
1046
+ newString: 'console.log("world");',
1047
+ replaceAll: false
1048
+ },
1049
+ output: {
1050
+ path: "src/example.ts",
1051
+ oldString: 'console.log("hello");',
1052
+ newString: 'console.log("world");',
1053
+ replacements: 1,
1054
+ message: "Successfully made 1 replacement(s) in file."
1055
+ }
1056
+ },
1057
+ {
1058
+ input: {
1059
+ path: "src/example.ts",
1060
+ oldString: "var",
1061
+ newString: "let",
1062
+ replaceAll: true
1063
+ },
1064
+ output: {
1065
+ path: "src/example.ts",
1066
+ oldString: "var",
1067
+ newString: "let",
1068
+ replacements: 3,
1069
+ message: "Successfully made 3 replacement(s) in file."
1070
+ }
1071
+ }
1072
+ ];
1073
+ }
1074
+ };
1075
+
1076
+ // src/tools/get-project-file-structure-tool.ts
1077
+ var import_zod4 = require("zod");
1078
+
1079
+ // src/util/build-tree-from-files.ts
1080
+ function renderTree(node, prefix = "") {
1081
+ const entries = Object.keys(node).sort();
1082
+ let result = "";
1083
+ for (let i = 0; i < entries.length; i++) {
1084
+ const entry = entries[i];
1085
+ const isLast = i === entries.length - 1;
1086
+ const connector = isLast ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
1087
+ const nextPrefix = prefix + (isLast ? " " : "\u2502 ");
1088
+ result += prefix + connector + "**" + entry + "**\n";
1089
+ if (Object.keys(node[entry]).length > 0) {
1090
+ result += renderTree(node[entry], nextPrefix);
1091
+ }
1092
+ }
1093
+ return result;
1094
+ }
1095
+ function buildTreeFromFiles(files) {
1096
+ if (files.length === 0) {
1097
+ return "";
1098
+ }
1099
+ const sortedFiles = [...files].sort();
1100
+ const tree = {};
1101
+ for (const file of sortedFiles) {
1102
+ const parts = file.split("/");
1103
+ let current = tree;
1104
+ for (const part of parts) {
1105
+ if (!current[part]) {
1106
+ current[part] = {};
1107
+ }
1108
+ current = current[part];
1109
+ }
1110
+ }
1111
+ return renderTree(tree).trim();
1112
+ }
1113
+
1114
+ // src/tools/get-project-file-structure-tool.ts
1115
+ var GetProjectFileStructureToolName = "get_project_file_structure";
1116
+ var GetProjectFileStructureToolInput = import_zod4.z.object({
1117
+ path: import_zod4.z.string().optional().meta({
1118
+ description: 'Root path to list files from, relative to the project directory. Defaults to ".".'
1119
+ }),
1120
+ excludeGitIgnored: import_zod4.z.boolean().optional().meta({
1121
+ description: "Whether to exclude files ignored by Git. Defaults to true."
1122
+ })
1123
+ });
1124
+ var GetProjectFileStructureToolOutput = import_zod4.z.object({
1125
+ files: import_zod4.z.array(import_zod4.z.string()).meta({
1126
+ description: "List of all file paths found, relative to the root path."
1127
+ }),
1128
+ excludeGitIgnored: import_zod4.z.boolean().meta({
1129
+ description: "Whether files ignored by Git were excluded."
1130
+ })
1131
+ });
1132
+ var GetProjectFileStructureTool = class extends EnvironmentToolBase {
1133
+ /**
1134
+ * Returns the metadata for the tool.
1135
+ *
1136
+ * The name, description, and needsApproval properties are defaults which can be overridden in the constructor.
1137
+ *
1138
+ * @returns The tool metadata.
1139
+ */
1140
+ getMetadata() {
1141
+ return {
1142
+ name: GetProjectFileStructureToolName,
1143
+ description: "Recursively lists all files in the project directory and formats them as a tree structure.",
1144
+ inputSchema: GetProjectFileStructureToolInput,
1145
+ outputSchema: GetProjectFileStructureToolOutput,
1146
+ needsApproval: false
1147
+ };
1148
+ }
1149
+ /**
1150
+ * Executes the tool in the given execution environment with the given input.
1151
+ *
1152
+ * @param env - The execution environment to use.
1153
+ * @param input - The input for the tool.
1154
+ * @returns A promise that resolves to the tool execution result.
1155
+ */
1156
+ async executeForEnvironment(env, input) {
1157
+ const { path: path5 = ".", excludeGitIgnored = true } = input;
1158
+ const escapedPath = escapeCommandArg(path5);
1159
+ let command = `find ${escapedPath} -type f`;
1160
+ if (excludeGitIgnored) {
1161
+ let gitIgnoredPaths = [];
1162
+ try {
1163
+ const { content: gitignoreContent } = await env.readFile(".gitignore");
1164
+ gitIgnoredPaths = gitignoreContent.split("\n").map((line) => line.trim()).filter((line) => line && !line.startsWith("#"));
1165
+ } catch (_error) {
1166
+ }
1167
+ for (const gitIgnoredPath of gitIgnoredPaths) {
1168
+ if (!gitIgnoredPath.endsWith("/")) {
1169
+ const escapedPath2 = escapeCommandArg(`*/${gitIgnoredPath}/*`);
1170
+ command += ` -not -name ${escapeCommandArg(gitIgnoredPath)} -not -path ${escapedPath2}`;
1171
+ } else {
1172
+ const escapedPath2 = escapeCommandArg(`*/${gitIgnoredPath}*`);
1173
+ command += ` -not -path ${escapedPath2}`;
1174
+ }
1175
+ }
1176
+ }
1177
+ command += " | sort";
1178
+ const { stdout, stderr, exitCode } = await env.runCommand(command);
1179
+ if (exitCode !== 0) {
1180
+ throw new Error(
1181
+ `Failed to get project file structure with command "${command}": ${stderr}`
1182
+ );
1183
+ }
1184
+ const files = stdout.split("\n").map((path6) => path6.trim()).filter(Boolean);
1185
+ const trimInitialDotSlash = (path6) => path6.startsWith("./") ? path6.slice(2) : path6;
1186
+ return {
1187
+ files: files.map(trimInitialDotSlash),
1188
+ excludeGitIgnored
1189
+ };
1190
+ }
1191
+ /**
1192
+ * Converts the tool output to a format suitable for model consumption.
1193
+ *
1194
+ * @param output - The output from the tool execution.
1195
+ * @returns The formatted tool result.
1196
+ */
1197
+ toModelOutput(output) {
1198
+ const tree = buildTreeFromFiles(output.files);
1199
+ if (!tree) {
1200
+ return {
1201
+ type: "text",
1202
+ value: "No files found."
1203
+ };
1204
+ }
1205
+ return {
1206
+ type: "text",
1207
+ value: tree
1208
+ };
1209
+ }
1210
+ /**
1211
+ * Gets the examples for the tool.
1212
+ *
1213
+ * @returns The tool examples.
1214
+ */
1215
+ get examples() {
1216
+ return [
1217
+ {
1218
+ input: {},
1219
+ output: `\u251C\u2500\u2500 **src/**
1220
+ \u2502 \u251C\u2500\u2500 **components/**
1221
+ \u2502 \u2502 \u251C\u2500\u2500 **Button.js**
1222
+ \u2502 \u2502 \u2514\u2500\u2500 **Header.js**
1223
+ \u2502 \u2514\u2500\u2500 **index.js**
1224
+ \u251C\u2500\u2500 **tests/**
1225
+ \u2502 \u2514\u2500\u2500 **test_runner.py**
1226
+ \u251C\u2500\u2500 .gitignore
1227
+ \u251C\u2500\u2500 README.md
1228
+ \u2514\u2500\u2500 package.json`
1229
+ }
1230
+ ];
1231
+ }
1232
+ };
1233
+
1234
+ // src/tools/glob-tool.ts
1235
+ var import_zod5 = require("zod");
1236
+
1237
+ // src/util/glob-to-reg-exp.ts
1238
+ function globToRegExp(glob) {
1239
+ let reStr = "";
1240
+ for (let i = 0; i < glob.length; i++) {
1241
+ const char = glob[i];
1242
+ switch (char) {
1243
+ case "*":
1244
+ if (glob[i + 1] === "*") {
1245
+ if (glob[i + 2] === "/") {
1246
+ reStr += "(?:.*\\/)?";
1247
+ i += 2;
1248
+ } else {
1249
+ reStr += ".*";
1250
+ i++;
1251
+ }
1252
+ } else {
1253
+ reStr += "[^/]*";
1254
+ }
1255
+ break;
1256
+ case "?":
1257
+ reStr += "[^/]";
1258
+ break;
1259
+ // Escape characters with special meaning in regex.
1260
+ case ".":
1261
+ case "(":
1262
+ case ")":
1263
+ case "[":
1264
+ case "]":
1265
+ case "{":
1266
+ case "}":
1267
+ case "+":
1268
+ case "^":
1269
+ case "$":
1270
+ case "|":
1271
+ case "\\":
1272
+ reStr += `\\${char}`;
1273
+ break;
1274
+ default:
1275
+ reStr += char;
1276
+ }
1277
+ }
1278
+ return new RegExp(`^${reStr}$`);
1279
+ }
1280
+
1281
+ // src/tools/glob-tool.ts
1282
+ var GlobToolName = "glob";
1283
+ var GlobToolInput = import_zod5.z.object({
1284
+ searchPattern: import_zod5.z.string().meta({
1285
+ description: 'The glob pattern to search for, relative to the search path / project directory (e.g. "**/*.ts", "docs/*.md").'
1286
+ }),
1287
+ searchPath: import_zod5.z.string().optional().meta({
1288
+ description: "The path to search within, relative to the project directory. Defaults to the project directory."
1289
+ }),
1290
+ excludeGitIgnored: import_zod5.z.boolean().optional().meta({
1291
+ description: "Whether to exclude files ignored by Git. Defaults to true."
1292
+ })
1293
+ });
1294
+ var GlobToolOutput = import_zod5.z.object({
1295
+ searchPattern: import_zod5.z.string().meta({
1296
+ description: "The glob pattern that was searched for."
1297
+ }),
1298
+ searchPath: import_zod5.z.string().meta({
1299
+ description: "The path that was searched within."
1300
+ }),
1301
+ excludeGitIgnored: import_zod5.z.boolean().meta({
1302
+ description: "Whether files ignored by Git were excluded."
1303
+ }),
1304
+ matchingPaths: import_zod5.z.array(import_zod5.z.string()).meta({
1305
+ description: "The list of file paths that matched the glob search, relative to the project directory."
1306
+ })
1307
+ });
1308
+ var GlobTool = class extends EnvironmentToolBase {
1309
+ /**
1310
+ * Returns the metadata for the tool.
1311
+ *
1312
+ * The name, description, and needsApproval properties are defaults which can be overridden in the constructor.
1313
+ *
1314
+ * @returns The tool metadata.
1315
+ */
1316
+ getMetadata() {
1317
+ return {
1318
+ name: GlobToolName,
1319
+ description: "Runs a glob search to find matching file paths in the project.",
1320
+ inputSchema: GlobToolInput,
1321
+ outputSchema: GlobToolOutput,
1322
+ needsApproval: false
1323
+ };
1324
+ }
1325
+ /**
1326
+ * Executes the tool in the given execution environment with the given input.
1327
+ *
1328
+ * @param env - The execution environment to use.
1329
+ * @param input - The input for the tool.
1330
+ * @returns A promise that resolves to the tool execution result.
1331
+ */
1332
+ async executeForEnvironment(env, input) {
1333
+ const { searchPattern, searchPath = "", excludeGitIgnored = true } = input;
1334
+ if (searchPattern.startsWith("/")) {
1335
+ throw new Error(
1336
+ "The search pattern must not start with a forward slash."
1337
+ );
1338
+ }
1339
+ if (searchPath) {
1340
+ validateRelativePath(searchPath);
1341
+ }
1342
+ const untrailingslashedSearchPath = searchPath === "" ? "." : searchPath.replace(/\/+$/, "");
1343
+ const escapedSearchPath = escapeCommandArg(untrailingslashedSearchPath);
1344
+ let command = `find ${escapedSearchPath} -type f`;
1345
+ if (excludeGitIgnored) {
1346
+ let gitIgnoredPaths = [];
1347
+ try {
1348
+ const { content: gitignoreContent } = await env.readFile(".gitignore");
1349
+ gitIgnoredPaths = gitignoreContent.split("\n").map((line) => line.trim()).filter((line) => line && !line.startsWith("#"));
1350
+ } catch (_error) {
1351
+ }
1352
+ for (const gitIgnoredPath of gitIgnoredPaths) {
1353
+ if (!gitIgnoredPath.endsWith("/")) {
1354
+ const escapedPath = escapeCommandArg(`*/${gitIgnoredPath}/*`);
1355
+ command += ` -not -name ${escapeCommandArg(gitIgnoredPath)} -not -path ${escapedPath}`;
1356
+ } else {
1357
+ const escapedPath = escapeCommandArg(`*/${gitIgnoredPath}*`);
1358
+ command += ` -not -path ${escapedPath}`;
1359
+ }
1360
+ }
1361
+ }
1362
+ const { stdout, stderr, exitCode } = await env.runCommand(command);
1363
+ if (exitCode !== 0) {
1364
+ throw new Error(
1365
+ `Failed to glob files with command "${command}": ${stderr}`
1366
+ );
1367
+ }
1368
+ const matchingPaths = stdout.split("\n").map((path5) => path5.trim()).filter(Boolean);
1369
+ const trimInitialDotSlash = (path5) => path5.startsWith("./") ? path5.slice(2) : path5;
1370
+ if (searchPattern !== "" && searchPattern !== "**") {
1371
+ const combinedPattern = `${untrailingslashedSearchPath}/${searchPattern}`;
1372
+ const regExp = globToRegExp(combinedPattern);
1373
+ const filteredMatchingPaths = matchingPaths.filter(
1374
+ (path5) => regExp.test(path5)
1375
+ );
1376
+ return {
1377
+ searchPattern,
1378
+ searchPath,
1379
+ excludeGitIgnored,
1380
+ matchingPaths: filteredMatchingPaths.map(trimInitialDotSlash)
1381
+ };
1382
+ }
1383
+ return {
1384
+ searchPattern,
1385
+ searchPath,
1386
+ excludeGitIgnored,
1387
+ matchingPaths: matchingPaths.map(trimInitialDotSlash)
1388
+ };
1389
+ }
1390
+ /**
1391
+ * Converts the tool output to a format suitable for model consumption.
1392
+ *
1393
+ * @param output - The output from the tool execution.
1394
+ * @returns The formatted tool result.
1395
+ */
1396
+ toModelOutput(output) {
1397
+ if (output.matchingPaths.length === 0) {
1398
+ return {
1399
+ type: "text",
1400
+ value: "No matching files found."
1401
+ };
1402
+ }
1403
+ const bulletPoints = output.matchingPaths.map((path5) => `- \`${path5}\``).join("\n");
1404
+ return {
1405
+ type: "text",
1406
+ value: `Matching files:
1407
+ ${bulletPoints}
1408
+ `
1409
+ };
1410
+ }
1411
+ /**
1412
+ * Gets the examples for the tool.
1413
+ *
1414
+ * @returns The tool examples.
1415
+ */
1416
+ get examples() {
1417
+ return [
1418
+ {
1419
+ input: {
1420
+ searchPattern: "src/**/*.tsx"
1421
+ },
1422
+ output: `Matching files:
1423
+ - \`src/app/page.tsx\`
1424
+ - \`src/components/chart.tsx\`
1425
+ - \`src/components/footer.tsx\`
1426
+ - \`src/components/header.tsx\`
1427
+ `
1428
+ },
1429
+ {
1430
+ input: {
1431
+ searchPattern: "*",
1432
+ searchPath: "packages/my-project"
1433
+ },
1434
+ output: `Matching files:
1435
+ - \`packages/my-project/package.json\`
1436
+ - \`packages/my-project/README.md\`
1437
+ - \`packages/my-project/tsconfig.json\`
1438
+ - \`packages/my-project/vitest.config.ts\`
1439
+ `
1440
+ }
1441
+ ];
1442
+ }
1443
+ };
1444
+
1445
+ // src/tools/list-directory-tool.ts
1446
+ var import_zod6 = require("zod");
1447
+ var ListDirectoryToolName = "list_directory";
1448
+ var ListDirectoryToolInput = import_zod6.z.object({
1449
+ path: import_zod6.z.string().meta({
1450
+ description: "The directory path to list, relative to the project directory."
1451
+ })
1452
+ });
1453
+ var ListDirectoryToolOutput = import_zod6.z.object({
1454
+ path: import_zod6.z.string().meta({
1455
+ description: "The directory path that was listed."
1456
+ }),
1457
+ files: import_zod6.z.array(import_zod6.z.string()).meta({
1458
+ description: "List of files in the directory."
1459
+ }),
1460
+ directories: import_zod6.z.array(import_zod6.z.string()).meta({
1461
+ description: "List of subdirectories in the directory."
1462
+ })
1463
+ });
1464
+ var ListDirectoryTool = class extends EnvironmentToolBase {
1465
+ /**
1466
+ * Returns the metadata for the tool.
1467
+ *
1468
+ * The name, description, and needsApproval properties are defaults which can be overridden in the constructor.
1469
+ *
1470
+ * @returns The tool metadata.
1471
+ */
1472
+ getMetadata() {
1473
+ return {
1474
+ name: ListDirectoryToolName,
1475
+ description: "Lists all files and directories in the specified directory, differentiating between files and directories. Non-recursive.",
1476
+ inputSchema: ListDirectoryToolInput,
1477
+ outputSchema: ListDirectoryToolOutput,
1478
+ needsApproval: false
1479
+ };
1480
+ }
1481
+ /**
1482
+ * Executes the tool in the given execution environment with the given input.
1483
+ *
1484
+ * @param env - The execution environment to use.
1485
+ * @param input - The input for the tool.
1486
+ * @returns A promise that resolves to the tool execution result.
1487
+ */
1488
+ async executeForEnvironment(env, input) {
1489
+ const escapedPath = escapeCommandArg(input.path);
1490
+ const command = `ls -la ${escapedPath}`;
1491
+ const { stdout, stderr, exitCode } = await env.runCommand(command);
1492
+ if (exitCode !== 0) {
1493
+ throw new Error(
1494
+ `Failed to list directory "${input.path}" with command "${command}": ${stderr}`
1495
+ );
1496
+ }
1497
+ const lines = stdout.split("\n").filter((line) => line.trim() !== "");
1498
+ const files = [];
1499
+ const directories = [];
1500
+ for (let i = 1; i < lines.length; i++) {
1501
+ const line = lines[i].trim();
1502
+ if (!line) continue;
1503
+ const typeChar = line.charAt(0);
1504
+ const parts = line.split(/\s+/);
1505
+ const name = parts[parts.length - 1];
1506
+ if (name === "." || name === "..") continue;
1507
+ if (typeChar === "d") {
1508
+ directories.push(name);
1509
+ } else if (typeChar === "-") {
1510
+ files.push(name);
1511
+ }
1512
+ }
1513
+ return {
1514
+ path: input.path,
1515
+ files,
1516
+ directories
1517
+ };
1518
+ }
1519
+ /**
1520
+ * Converts the tool output to a format suitable for model consumption.
1521
+ *
1522
+ * @param output - The output from the tool execution.
1523
+ * @returns The formatted tool result.
1524
+ */
1525
+ toModelOutput(output) {
1526
+ const formatEntries = (entries, type) => {
1527
+ if (entries.length === 0) {
1528
+ return `No ${type} found.`;
1529
+ }
1530
+ const bulletPoints = entries.map((name) => `- \`${name}\``).join("\n");
1531
+ return `${type.charAt(0).toUpperCase() + type.slice(1)}:
1532
+ ${bulletPoints}`;
1533
+ };
1534
+ const filesSection = formatEntries(output.files, "files");
1535
+ const directoriesSection = formatEntries(output.directories, "directories");
1536
+ return {
1537
+ type: "text",
1538
+ value: `Directory listing for \`${output.path}\`:
1539
+
1540
+ ${filesSection}
1541
+
1542
+ ${directoriesSection}`
1543
+ };
1544
+ }
1545
+ /**
1546
+ * Gets the examples for the tool.
1547
+ *
1548
+ * @returns The tool examples.
1549
+ */
1550
+ get examples() {
1551
+ return [
1552
+ {
1553
+ input: {
1554
+ path: "src"
1555
+ },
1556
+ output: `Directory listing for \`src\`:
1557
+
1558
+ Files:
1559
+ - \`index.ts\`
1560
+ - \`utils.ts\`
1561
+
1562
+ Directories:
1563
+ - \`components\`
1564
+ - \`hooks\``
1565
+ }
1566
+ ];
1567
+ }
1568
+ };
1569
+
1570
+ // src/tools/move-file-tool.ts
1571
+ var import_zod7 = require("zod");
1572
+ var MoveFileToolName = "move_file";
1573
+ var MoveFileToolInput = import_zod7.z.object({
1574
+ sourcePath: import_zod7.z.string().meta({
1575
+ description: "The path to the file to move, relative to the project directory."
1576
+ }),
1577
+ destinationPath: import_zod7.z.string().meta({
1578
+ description: "The path to the destination where the file should be moved, relative to the project directory. If the file already exists, it will be overwritten."
1579
+ })
1580
+ });
1581
+ var MoveFileToolOutput = MoveFileResult;
1582
+ var MoveFileTool = class extends EnvironmentToolBase {
1583
+ /**
1584
+ * Returns the metadata for the tool.
1585
+ *
1586
+ * The name, description, and needsApproval properties are defaults which can be overridden in the constructor.
1587
+ *
1588
+ * @returns The tool metadata.
1589
+ */
1590
+ getMetadata() {
1591
+ return {
1592
+ name: MoveFileToolName,
1593
+ description: "Moves a file from a source path to a destination path.",
1594
+ inputSchema: MoveFileToolInput,
1595
+ outputSchema: MoveFileToolOutput,
1596
+ needsApproval: false
1597
+ };
1598
+ }
1599
+ /**
1600
+ * Executes the tool in the given execution environment with the given input.
1601
+ *
1602
+ * @param env - The execution environment to use.
1603
+ * @param input - The input for the tool.
1604
+ * @returns A promise that resolves to the tool execution result.
1605
+ */
1606
+ executeForEnvironment(env, input) {
1607
+ return env.moveFile(input.sourcePath, input.destinationPath);
1608
+ }
1609
+ /**
1610
+ * Converts the tool output to a format suitable for model consumption.
1611
+ *
1612
+ * @param output - The output from the tool execution.
1613
+ * @returns The formatted tool result.
1614
+ */
1615
+ toModelOutput(output) {
1616
+ return {
1617
+ type: "text",
1618
+ value: `File \`${output.sourcePath}\` moved successfully to \`${output.destinationPath}\`.`
1619
+ };
1620
+ }
1621
+ /**
1622
+ * Gets the examples for the tool.
1623
+ *
1624
+ * @returns The tool examples.
1625
+ */
1626
+ get examples() {
1627
+ return [
1628
+ {
1629
+ input: {
1630
+ sourcePath: "src/lib/types.ts",
1631
+ destinationPath: "lib/index.ts"
1632
+ },
1633
+ output: "File `src/lib/types.ts` moved successfully to `lib/index.ts`."
1634
+ }
1635
+ ];
1636
+ }
1637
+ };
1638
+
1639
+ // src/tools/read-file-tool.ts
1640
+ var import_zod8 = require("zod");
1641
+
1642
+ // src/util/get-language-identifier-from-file-path.ts
1643
+ var import_node_path3 = __toESM(require("path"), 1);
1644
+ var jsLanguage = {
1645
+ identifier: "javascript",
1646
+ name: "JavaScript",
1647
+ fileExtensions: ["js", "jsx"]
1648
+ };
1649
+ var tsLanguage = {
1650
+ identifier: "typescript",
1651
+ name: "TypeScript",
1652
+ fileExtensions: ["ts", "tsx"]
1653
+ };
1654
+ var ymlLanguage = {
1655
+ identifier: "yaml",
1656
+ name: "YAML",
1657
+ fileExtensions: ["yml", "yaml"]
1658
+ };
1659
+ var EXTENSION_TO_LANGUAGE = {
1660
+ ts: tsLanguage,
1661
+ tsx: tsLanguage,
1662
+ js: jsLanguage,
1663
+ jsx: jsLanguage,
1664
+ py: {
1665
+ identifier: "python",
1666
+ name: "Python",
1667
+ fileExtensions: ["py"]
1668
+ },
1669
+ java: {
1670
+ identifier: "java",
1671
+ name: "Java",
1672
+ fileExtensions: ["java"]
1673
+ },
1674
+ c: {
1675
+ identifier: "c",
1676
+ name: "C",
1677
+ fileExtensions: ["c"]
1678
+ },
1679
+ cpp: {
1680
+ identifier: "cpp",
1681
+ name: "C++",
1682
+ fileExtensions: ["cpp"]
1683
+ },
1684
+ cs: {
1685
+ identifier: "chsarp",
1686
+ name: "C#",
1687
+ fileExtensions: ["cs"]
1688
+ },
1689
+ go: {
1690
+ identifier: "go",
1691
+ name: "Go",
1692
+ fileExtensions: ["go"]
1693
+ },
1694
+ rs: {
1695
+ identifier: "rust",
1696
+ name: "Rust",
1697
+ fileExtensions: ["rs"]
1698
+ },
1699
+ php: {
1700
+ identifier: "php",
1701
+ name: "PHP",
1702
+ fileExtensions: ["php"]
1703
+ },
1704
+ rb: {
1705
+ identifier: "ruby",
1706
+ name: "Ruby",
1707
+ fileExtensions: ["rb"]
1708
+ },
1709
+ swift: {
1710
+ identifier: "swift",
1711
+ name: "Swift",
1712
+ fileExtensions: ["swift"]
1713
+ },
1714
+ kt: {
1715
+ identifier: "kotlin",
1716
+ name: "Kotlin",
1717
+ fileExtensions: ["kt"]
1718
+ },
1719
+ scala: {
1720
+ identifier: "scala",
1721
+ name: "Scala",
1722
+ fileExtensions: ["scala"]
1723
+ },
1724
+ html: {
1725
+ identifier: "html",
1726
+ name: "HTML",
1727
+ fileExtensions: ["html"]
1728
+ },
1729
+ css: {
1730
+ identifier: "css",
1731
+ name: "CSS",
1732
+ fileExtensions: ["css"]
1733
+ },
1734
+ sass: {
1735
+ identifier: "sass",
1736
+ name: "Sass",
1737
+ fileExtensions: ["sass"]
1738
+ },
1739
+ scss: {
1740
+ identifier: "scss",
1741
+ name: "SCSS",
1742
+ fileExtensions: ["scss"]
1743
+ },
1744
+ less: {
1745
+ identifier: "less",
1746
+ name: "Less",
1747
+ fileExtensions: ["less"]
1748
+ },
1749
+ json: {
1750
+ identifier: "json",
1751
+ name: "JSON",
1752
+ fileExtensions: ["json"]
1753
+ },
1754
+ md: {
1755
+ identifier: "markdown",
1756
+ name: "Markdown",
1757
+ fileExtensions: ["md"]
1758
+ },
1759
+ toml: {
1760
+ identifier: "toml",
1761
+ name: "TOML",
1762
+ fileExtensions: ["toml"]
1763
+ },
1764
+ yml: ymlLanguage,
1765
+ yaml: ymlLanguage,
1766
+ xml: {
1767
+ identifier: "xml",
1768
+ name: "XML",
1769
+ fileExtensions: ["xml"]
1770
+ },
1771
+ sql: {
1772
+ identifier: "sql",
1773
+ name: "SQL",
1774
+ fileExtensions: ["sql"]
1775
+ },
1776
+ graphql: {
1777
+ identifier: "graphql",
1778
+ name: "GraphQL",
1779
+ fileExtensions: ["graphql"]
1780
+ },
1781
+ sh: {
1782
+ identifier: "bash",
1783
+ name: "Shell",
1784
+ fileExtensions: ["sh"]
1785
+ },
1786
+ ps1: {
1787
+ identifier: "bash",
1788
+ name: "PowerShell",
1789
+ fileExtensions: ["ps1"]
1790
+ }
1791
+ };
1792
+ function getLanguageFromFilePath(filePath) {
1793
+ const extension = import_node_path3.default.extname(filePath).slice(1).toLowerCase() || "";
1794
+ return EXTENSION_TO_LANGUAGE[extension];
1795
+ }
1796
+ function getLanguageIdentifierFromFilePath(filePath) {
1797
+ const language = getLanguageFromFilePath(filePath);
1798
+ return language ? language.identifier : "";
1799
+ }
1800
+
1801
+ // src/tools/read-file-tool.ts
1802
+ var ReadFileToolName = "read_file";
1803
+ var ReadFileToolInput = import_zod8.z.object({
1804
+ path: import_zod8.z.string().meta({
1805
+ description: "The path to the file to read, relative to the project directory."
1806
+ })
1807
+ });
1808
+ var ReadFileToolOutput = ReadFileResult;
1809
+ var formatModelResponse = (output) => {
1810
+ const language = getLanguageIdentifierFromFilePath(output.path);
1811
+ return `File: \`${output.path}\`
1812
+ Content:
1813
+ \`\`\`${language}
1814
+ ${output.content}
1815
+ \`\`\`
1816
+ `;
1817
+ };
1818
+ var ReadFileTool = class extends EnvironmentToolBase {
1819
+ /**
1820
+ * Returns the metadata for the tool.
1821
+ *
1822
+ * The name, description, and needsApproval properties are defaults which can be overridden in the constructor.
1823
+ *
1824
+ * @returns The tool metadata.
1825
+ */
1826
+ getMetadata() {
1827
+ return {
1828
+ name: ReadFileToolName,
1829
+ description: "Reads the content of a file at the specified path.",
1830
+ inputSchema: ReadFileToolInput,
1831
+ outputSchema: ReadFileToolOutput,
1832
+ needsApproval: false
1833
+ };
1834
+ }
1835
+ /**
1836
+ * Executes the tool in the given execution environment with the given input.
1837
+ *
1838
+ * @param env - The execution environment to use.
1839
+ * @param input - The input for the tool.
1840
+ * @returns A promise that resolves to the tool execution result.
1841
+ */
1842
+ executeForEnvironment(env, input) {
1843
+ return env.readFile(input.path);
1844
+ }
1845
+ /**
1846
+ * Converts the tool output to a format suitable for model consumption.
1847
+ *
1848
+ * @param output - The output from the tool execution.
1849
+ * @returns The formatted tool result.
1850
+ */
1851
+ toModelOutput(output) {
1852
+ return {
1853
+ type: "text",
1854
+ value: formatModelResponse(output)
1855
+ };
1856
+ }
1857
+ /**
1858
+ * Gets the examples for the tool.
1859
+ *
1860
+ * @returns The tool examples.
1861
+ */
1862
+ get examples() {
1863
+ const exampleContent = `import clsx from 'clsx';
1864
+
1865
+ type LoaderProps = {
1866
+ className?: string;
1867
+ };
1868
+
1869
+ export function Loader(props: LoaderProps) {
1870
+ const { className } = props;
1871
+
1872
+ return (
1873
+ <div className={clsx('loader', className)}>
1874
+ Loading\u2026
1875
+ </div>
1876
+ );
1877
+ }
1878
+ `;
1879
+ return [
1880
+ {
1881
+ input: {
1882
+ path: "src/components/Loader.tsx"
1883
+ },
1884
+ output: formatModelResponse({
1885
+ path: "src/components/Loader.tsx",
1886
+ content: exampleContent
1887
+ })
1888
+ }
1889
+ ];
1890
+ }
1891
+ };
1892
+
1893
+ // src/tools/read-many-files-tool.ts
1894
+ var import_zod9 = require("zod");
1895
+ var ReadManyFilesToolName = "read_many_files";
1896
+ var ReadManyFilesToolInput = import_zod9.z.object({
1897
+ paths: import_zod9.z.array(import_zod9.z.string()).meta({
1898
+ description: "The paths to the files to read, relative to the project directory."
1899
+ })
1900
+ });
1901
+ var ReadManyFilesToolOutput = import_zod9.z.record(import_zod9.z.string(), ReadFileResult);
1902
+ var formatModelResponse2 = (output) => {
1903
+ const language = getLanguageIdentifierFromFilePath(output.path);
1904
+ return `File: \`${output.path}\`
1905
+ Content:
1906
+ \`\`\`${language}
1907
+ ${output.content}
1908
+ \`\`\`
1909
+ `;
1910
+ };
1911
+ var ReadManyFilesTool = class extends EnvironmentToolBase {
1912
+ /**
1913
+ * Returns the metadata for the tool.
1914
+ *
1915
+ * The name, description, and needsApproval properties are defaults which can be overridden in the constructor.
1916
+ *
1917
+ * @returns The tool metadata.
1918
+ */
1919
+ getMetadata() {
1920
+ return {
1921
+ name: ReadManyFilesToolName,
1922
+ description: "Reads the contents of the files at the specified paths.",
1923
+ inputSchema: ReadManyFilesToolInput,
1924
+ outputSchema: ReadManyFilesToolOutput,
1925
+ needsApproval: false
1926
+ };
1927
+ }
1928
+ /**
1929
+ * Executes the tool in the given execution environment with the given input.
1930
+ *
1931
+ * @param env - The execution environment to use.
1932
+ * @param input - The input for the tool.
1933
+ * @returns A promise that resolves to the tool execution result.
1934
+ */
1935
+ async executeForEnvironment(env, input) {
1936
+ const results = await Promise.all(
1937
+ input.paths.map((path5) => env.readFile(path5))
1938
+ );
1939
+ return results.reduce((acc, result) => {
1940
+ acc[result.path] = result;
1941
+ return acc;
1942
+ }, {});
1943
+ }
1944
+ /**
1945
+ * Converts the tool output to a format suitable for model consumption.
1946
+ *
1947
+ * @param output - The output from the tool execution.
1948
+ * @returns The formatted tool result.
1949
+ */
1950
+ toModelOutput(output) {
1951
+ const fileContentResponses = Object.values(output).map(
1952
+ (fileResult) => formatModelResponse2(fileResult)
1953
+ );
1954
+ return {
1955
+ type: "text",
1956
+ value: fileContentResponses.join("\n")
1957
+ };
1958
+ }
1959
+ /**
1960
+ * Gets the examples for the tool.
1961
+ *
1962
+ * @returns The tool examples.
1963
+ */
1964
+ get examples() {
1965
+ const exampleContent1 = `import clsx from 'clsx';
1966
+
1967
+ type LoaderProps = {
1968
+ className?: string;
1969
+ };
1970
+
1971
+ export function Loader(props: LoaderProps) {
1972
+ const { className } = props;
1973
+
1974
+ return (
1975
+ <div className={clsx('loader', className)}>
1976
+ Loading\u2026
1977
+ </div>
1978
+ );
1979
+ }
1980
+ `;
1981
+ const exampleContent2 = `export function snakeCaseToCamelCase(snakeCase: string): string {
1982
+ return snakeCase.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());
1983
+ }
1984
+ `;
1985
+ return [
1986
+ {
1987
+ input: {
1988
+ paths: [
1989
+ "src/components/Loader.tsx",
1990
+ "src/util/snake-case-to-camel-case.ts"
1991
+ ]
1992
+ },
1993
+ output: formatModelResponse2({
1994
+ path: "src/components/Loader.tsx",
1995
+ content: exampleContent1
1996
+ }) + "\n" + formatModelResponse2({
1997
+ path: "src/util/snake-case-to-camel-case.ts",
1998
+ content: exampleContent2
1999
+ })
2000
+ }
2001
+ ];
2002
+ }
2003
+ };
2004
+
2005
+ // src/tools/run-command-tool.ts
2006
+ var import_zod10 = require("zod");
2007
+ var RunCommandToolName = "run_command";
2008
+ var RunCommandToolInput = import_zod10.z.object({
2009
+ command: import_zod10.z.string().meta({ description: "The CLI command to run, including all arguments." })
2010
+ });
2011
+ var RunCommandToolOutput = RunCommandResult;
2012
+ function formatCommandResultToModelResponse(output) {
2013
+ const stdout = !output.stdout.trim() ? "(none)" : `
2014
+ \`\`\`
2015
+ ${output.stdout}
2016
+ \`\`\``;
2017
+ const stderr = !output.stderr.trim() ? "(none)" : `
2018
+ \`\`\`
2019
+ ${output.stderr}
2020
+ \`\`\``;
2021
+ return `Command: \`${output.command}\`
2022
+ Exit Code: ${output.exitCode}
2023
+ Output (stdout): ${stdout}
2024
+ Error Output (stderr): ${stderr}
2025
+ `;
2026
+ }
2027
+ var RunCommandTool = class extends EnvironmentToolBase {
2028
+ /**
2029
+ * Returns the metadata for the tool.
2030
+ *
2031
+ * The name, description, and needsApproval properties are defaults which can be overridden in the constructor.
2032
+ *
2033
+ * @returns The tool metadata.
2034
+ */
2035
+ getMetadata() {
2036
+ return {
2037
+ name: RunCommandToolName,
2038
+ description: "Runs the specific CLI command.",
2039
+ inputSchema: RunCommandToolInput,
2040
+ outputSchema: RunCommandToolOutput,
2041
+ needsApproval: true
2042
+ };
2043
+ }
2044
+ /**
2045
+ * Executes the tool in the given execution environment with the given input.
2046
+ *
2047
+ * @param env - The execution environment to use.
2048
+ * @param input - The input for the tool.
2049
+ * @returns A promise that resolves to the tool execution result.
2050
+ */
2051
+ executeForEnvironment(env, input) {
2052
+ return env.runCommand(input.command);
2053
+ }
2054
+ /**
2055
+ * Converts the tool output to a format suitable for model consumption.
2056
+ *
2057
+ * @param output - The output from the tool execution.
2058
+ * @returns The formatted tool result.
2059
+ */
2060
+ toModelOutput(output) {
2061
+ return {
2062
+ type: "text",
2063
+ value: formatCommandResultToModelResponse(output)
2064
+ };
2065
+ }
2066
+ /**
2067
+ * Gets the examples for the tool.
2068
+ *
2069
+ * @returns The tool examples.
2070
+ */
2071
+ get examples() {
2072
+ const exampleGitOutput = `diff --git a/src/util/string-utils.ts b/src/util/string-utils.ts
2073
+ index 1836072..b13adef 100644
2074
+ --- a/src/util/string-utils.ts
2075
+ +++ b/src/util/string-utils.ts
2076
+ @@ -1,3 +1,7 @@
2077
+ export function snakeCaseToCamelCase(str: string): string {
2078
+ return str.replace(/_([a-z])/g, (match, p1) => p1.toUpperCase());
2079
+ }
2080
+ +
2081
+ +export function camelCaseToSnakeCase(str: string): string {
2082
+ + return str.replace(/([A-Z])/g, (match) => \`_\${match.toLowerCase()}\`);
2083
+ +}
2084
+ `;
2085
+ const exampleNpmOutput = `
2086
+ added 1 package, and changed 1 package in 2s
2087
+
2088
+ 156 packages are looking for funding
2089
+ run \`npm fund\` for details`;
2090
+ const exampleMkdirError = `mkdir: src/lib: No such file or directory
2091
+ `;
2092
+ return [
2093
+ {
2094
+ input: {
2095
+ command: "git --no-pager diff"
2096
+ },
2097
+ output: formatCommandResultToModelResponse({
2098
+ command: "git --no-pager diff",
2099
+ exitCode: 0,
2100
+ stdout: exampleGitOutput,
2101
+ stderr: ""
2102
+ })
2103
+ },
2104
+ {
2105
+ input: {
2106
+ command: "npm install zod"
2107
+ },
2108
+ output: formatCommandResultToModelResponse({
2109
+ command: "npm install zod",
2110
+ exitCode: 0,
2111
+ stdout: exampleNpmOutput,
2112
+ stderr: ""
2113
+ })
2114
+ },
2115
+ {
2116
+ input: {
2117
+ command: "mkdir src/lib/api"
2118
+ },
2119
+ output: formatCommandResultToModelResponse({
2120
+ command: "mkdir src/lib/api",
2121
+ exitCode: 1,
2122
+ stdout: "",
2123
+ stderr: exampleMkdirError
2124
+ })
2125
+ }
2126
+ ];
2127
+ }
2128
+ };
2129
+
2130
+ // src/tools/write-file-tool.ts
2131
+ var import_zod11 = require("zod");
2132
+ var WriteFileToolName = "write_file";
2133
+ var WriteFileToolInput = import_zod11.z.object({
2134
+ path: import_zod11.z.string().meta({
2135
+ description: "The path to the file to write, relative to the project directory."
2136
+ }),
2137
+ content: import_zod11.z.string().meta({
2138
+ description: "The content to write to the file. If the file already exists, the content will replace existing content."
2139
+ })
2140
+ });
2141
+ var WriteFileToolOutput = WriteFileResult;
2142
+ var WriteFileTool = class extends EnvironmentToolBase {
2143
+ /**
2144
+ * Returns the metadata for the tool.
2145
+ *
2146
+ * The name, description, and needsApproval properties are defaults which can be overridden in the constructor.
2147
+ *
2148
+ * @returns The tool metadata.
2149
+ */
2150
+ getMetadata() {
2151
+ return {
2152
+ name: WriteFileToolName,
2153
+ description: "Writes content to a file at the specified path.",
2154
+ inputSchema: WriteFileToolInput,
2155
+ outputSchema: WriteFileToolOutput,
2156
+ needsApproval: false
2157
+ };
2158
+ }
2159
+ /**
2160
+ * Executes the tool in the given execution environment with the given input.
2161
+ *
2162
+ * @param env - The execution environment to use.
2163
+ * @param input - The input for the tool.
2164
+ * @returns A promise that resolves to the tool execution result.
2165
+ */
2166
+ executeForEnvironment(env, input) {
2167
+ return env.writeFile(input.path, input.content);
2168
+ }
2169
+ /**
2170
+ * Converts the tool output to a format suitable for model consumption.
2171
+ *
2172
+ * @param output - The output from the tool execution.
2173
+ * @returns The formatted tool result.
2174
+ */
2175
+ toModelOutput(output) {
2176
+ return {
2177
+ type: "text",
2178
+ value: `File \`${output.path}\` written successfully.`
2179
+ };
2180
+ }
2181
+ /**
2182
+ * Gets the examples for the tool.
2183
+ *
2184
+ * @returns The tool examples.
2185
+ */
2186
+ get examples() {
2187
+ const exampleContent = `export function snakeCaseToCamelCase(snakeCase: string): string {
2188
+ return snakeCase.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());
2189
+ }
2190
+ `;
2191
+ return [
2192
+ {
2193
+ input: {
2194
+ path: "src/util/snake-case-to-camel-case.ts",
2195
+ content: exampleContent
2196
+ },
2197
+ output: "File `src/util/snake-case-to-camel-case.ts` written successfully."
2198
+ }
2199
+ ];
2200
+ }
2201
+ };
2202
+
2203
+ // src/agent-creators.ts
2204
+ var import_ai = require("ai");
2205
+
2206
+ // src/tools/submit-tool.ts
2207
+ var import_zod12 = require("zod");
2208
+ var SubmitToolName = "submit";
2209
+ var SubmitToolInput = import_zod12.z.object({});
2210
+ var SubmitToolOutput = import_zod12.z.object({});
2211
+ var SubmitTool = class extends ToolBase {
2212
+ /**
2213
+ * Returns the metadata for the tool.
2214
+ *
2215
+ * The name, description, and needsApproval properties are defaults which can be overridden in the constructor.
2216
+ *
2217
+ * @returns The tool metadata.
2218
+ */
2219
+ getMetadata() {
2220
+ return {
2221
+ name: SubmitToolName,
2222
+ description: "Submits the current task, indicating that it is completed.",
2223
+ inputSchema: SubmitToolInput,
2224
+ outputSchema: SubmitToolOutput,
2225
+ needsApproval: false
2226
+ };
2227
+ }
2228
+ /**
2229
+ * Executes the tool with the given input.
2230
+ *
2231
+ * @param _ - The input for the tool. Unused.
2232
+ * @param __ - Options from the tool call. Unused.
2233
+ * @returns A promise that resolves to the tool execution result.
2234
+ */
2235
+ async execute(_, __) {
2236
+ return {};
2237
+ }
2238
+ /**
2239
+ * Converts the tool output to a format suitable for model consumption.
2240
+ *
2241
+ * @param _ - The output from the tool execution. Unused.
2242
+ * @returns The formatted tool result.
2243
+ */
2244
+ toModelOutput(_) {
2245
+ return {
2246
+ type: "text",
2247
+ value: `Task submitted successfully.`
2248
+ };
2249
+ }
2250
+ /**
2251
+ * Gets the examples for the tool.
2252
+ *
2253
+ * @returns The tool examples.
2254
+ */
2255
+ get examples() {
2256
+ return [];
2257
+ }
2258
+ };
2259
+
2260
+ // src/instructions.ts
2261
+ function getAdditionalInstructions(config) {
2262
+ const { maxSteps, allowSubmit, tools } = config;
2263
+ const exampleSections = [];
2264
+ for (const [toolName, tool] of Object.entries(tools)) {
2265
+ if ("examples" in tool && Array.isArray(tool.examples) && tool.examples.length > 0) {
2266
+ let toolSection = `### Tool: \`${toolName}\`
2267
+
2268
+ `;
2269
+ for (const example of tool.examples) {
2270
+ toolSection += formatExampleForInstructions(toolName, example);
2271
+ }
2272
+ exampleSections.push(toolSection.trim());
2273
+ }
2274
+ }
2275
+ const workflowGuidelines = [
2276
+ /*
2277
+ * If there are examples, the tool information is already mentioned in a separate Tool Examples section.
2278
+ * Therefore the line below is only relevant if there are no examples.
2279
+ */
2280
+ ...!exampleSections.length ? [
2281
+ "You have access to several tools to assist you in completing your task."
2282
+ ] : [],
2283
+ "You must issue tool calls to complete your task. Do not engage with the user directly.",
2284
+ ...allowSubmit ? [
2285
+ `Once you think you have completed your task, call the \`${SubmitToolName}\` tool to submit your results.`
2286
+ ] : [],
2287
+ `You have a maximum of ${maxSteps} steps to complete your task.`
2288
+ ];
2289
+ const importantWorkflowGuidelines = `## Important Workflow Guidelines
2290
+
2291
+ ${workflowGuidelines.map((line) => `- ${line}`).join("\n")}
2292
+
2293
+ 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.
2294
+ `;
2295
+ if (exampleSections.length) {
2296
+ return `## Tool Examples
2297
+
2298
+ You have access to several tools to assist you in completing your task. Here are some examples of how to use them:
2299
+
2300
+ ${exampleSections.join("\n\n")}
2301
+
2302
+ ` + importantWorkflowGuidelines;
2303
+ }
2304
+ return importantWorkflowGuidelines;
2305
+ }
2306
+ function formatExampleForInstructions(toolName, example) {
2307
+ const input = typeof example.input === "undefined" ? "" : typeof example.input === "string" || typeof example.input === "number" ? example.input : JSON.stringify(example.input, null, 2);
2308
+ const output = typeof example.output === "undefined" ? "" : typeof example.output === "string" || typeof example.output === "number" ? example.output : JSON.stringify(example.output, null, 2);
2309
+ if (output === "") {
2310
+ return `<example>
2311
+ <tool_call>
2312
+ ${toolName}(${input})
2313
+ </tool_call>
2314
+ </example>`;
2315
+ }
2316
+ return `<example>
2317
+ <tool_call>
2318
+ ${toolName}(${input})
2319
+ </tool_call>
2320
+ <tool_response>
2321
+ ${output}
2322
+ </tool_response>
2323
+ </example>`;
2324
+ }
2325
+
2326
+ // src/tool-creators.ts
2327
+ var availableEnvironmentTools = {
2328
+ [ReadFileToolName]: ReadFileTool,
2329
+ [WriteFileToolName]: WriteFileTool,
2330
+ [DeleteFileToolName]: DeleteFileTool,
2331
+ [EditFileToolName]: EditFileTool,
2332
+ [MoveFileToolName]: MoveFileTool,
2333
+ [CopyFileToolName]: CopyFileTool,
2334
+ [ReadManyFilesToolName]: ReadManyFilesTool,
2335
+ [GetProjectFileStructureToolName]: GetProjectFileStructureTool,
2336
+ [GlobToolName]: GlobTool,
2337
+ [ListDirectoryToolName]: ListDirectoryTool,
2338
+ [RunCommandToolName]: RunCommandTool
2339
+ };
2340
+ var cliOnlyTools = [
2341
+ GetProjectFileStructureToolName,
2342
+ GlobToolName,
2343
+ ListDirectoryToolName,
2344
+ RunCommandToolName
2345
+ ];
2346
+ var readonlyTools = [
2347
+ ReadFileToolName,
2348
+ ReadManyFilesToolName,
2349
+ GetProjectFileStructureToolName,
2350
+ GlobToolName,
2351
+ ListDirectoryToolName
2352
+ ];
2353
+ var dangerousTools = [
2354
+ DeleteFileToolName,
2355
+ RunCommandToolName
2356
+ ];
2357
+ var EnvironmentToolSafetyLevels = [
2358
+ "readonly",
2359
+ "basic",
2360
+ "all"
2361
+ ];
2362
+ var EnvironmentToolNames = Object.keys(
2363
+ availableEnvironmentTools
2364
+ );
2365
+ function createEnvironmentTool(toolName, environment, config) {
2366
+ if (!(toolName in availableEnvironmentTools)) {
2367
+ throw new Error(`Unsupported environment: ${toolName}`);
2368
+ }
2369
+ const EnvironmentToolClass = availableEnvironmentTools[toolName];
2370
+ return new EnvironmentToolClass(
2371
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
2372
+ environment,
2373
+ config
2374
+ );
2375
+ }
2376
+ function createToolsForEnvironment(environment, toolsDefinition = "all") {
2377
+ const sanitizedToolsDefinition = sanitizeToolsDefinition(toolsDefinition);
2378
+ const isCliEnvironment = "runCommand" in environment;
2379
+ const tools = {};
2380
+ for (const toolDefinition of sanitizedToolsDefinition) {
2381
+ const actualToolName = toolDefinition.toolName;
2382
+ if (!isCliEnvironment && cliOnlyTools.includes(actualToolName)) {
2383
+ throw new Error(
2384
+ `The "${actualToolName}" tool can only be used with command-line environments.`
2385
+ );
2386
+ }
2387
+ const toolNameToUse = toolDefinition.toolConfig?.name || toolDefinition.toolName;
2388
+ let toolConfig;
2389
+ if (toolDefinition.toolConfig) {
2390
+ toolConfig = toolDefinition.toolConfig;
2391
+ }
2392
+ if (toolNameToUse in tools) {
2393
+ throw new Error(
2394
+ `Multiple tools named "${toolNameToUse}" are provided - make sure tool names are unique.`
2395
+ );
2396
+ }
2397
+ tools[toolNameToUse] = createEnvironmentTool(
2398
+ actualToolName,
2399
+ isCliEnvironment ? environment : environment,
2400
+ toolConfig
2401
+ );
2402
+ }
2403
+ return tools;
2404
+ }
2405
+ function createToolsForNamedEnvironment(environmentName, environment, toolsDefinition = "all") {
2406
+ const sanitizedToolsDefinition = sanitizeToolsDefinition(toolsDefinition);
2407
+ const toolsDefinitionWithEnvironmentName = sanitizedToolsDefinition.map(
2408
+ (toolDefinition) => {
2409
+ if (toolDefinition.toolConfig) {
2410
+ const toolNameToUse = toolDefinition.toolConfig.name || toolDefinition.toolName;
2411
+ return {
2412
+ toolName: toolDefinition.toolName,
2413
+ toolConfig: {
2414
+ ...toolDefinition.toolConfig,
2415
+ name: `${toolNameToUse}_in_${environmentName}`
2416
+ }
2417
+ };
2418
+ }
2419
+ return {
2420
+ toolName: toolDefinition.toolName,
2421
+ toolConfig: {
2422
+ name: `${toolDefinition.toolName}_in_${environmentName}`
2423
+ }
2424
+ };
2425
+ }
2426
+ );
2427
+ return createToolsForEnvironment(
2428
+ environment,
2429
+ toolsDefinitionWithEnvironmentName
2430
+ );
2431
+ }
2432
+ function sanitizeToolsDefinition(toolsDefinition) {
2433
+ if (typeof toolsDefinition === "string") {
2434
+ switch (toolsDefinition) {
2435
+ case "readonly":
2436
+ toolsDefinition = readonlyTools;
2437
+ break;
2438
+ case "basic":
2439
+ toolsDefinition = EnvironmentToolNames.filter(
2440
+ (toolName) => !dangerousTools.includes(toolName)
2441
+ );
2442
+ break;
2443
+ default:
2444
+ toolsDefinition = [...EnvironmentToolNames];
2445
+ }
2446
+ }
2447
+ return toolsDefinition.map((tool) => {
2448
+ if (typeof tool === "string") {
2449
+ return { toolName: tool };
2450
+ }
2451
+ return tool;
2452
+ });
2453
+ }
2454
+
2455
+ // src/util/get-step-log.ts
2456
+ function getStepLog(stepResult) {
2457
+ const { content } = stepResult;
2458
+ let logEntry = "";
2459
+ content.forEach((part) => {
2460
+ logEntry += part.type;
2461
+ if ("toolName" in part && "toolCallId" in part && part.toolCallId) {
2462
+ logEntry += ` (${part.toolName}, ID ${part.toolCallId})`;
2463
+ } else if ("toolName" in part) {
2464
+ logEntry += ` (${part.toolName})`;
2465
+ }
2466
+ logEntry += ": ";
2467
+ if (part.type === "tool-call" && "input" in part) {
2468
+ logEntry += typeof part.input === "string" ? part.input : JSON.stringify(part.input);
2469
+ } else if (part.type === "tool-result" && "output" in part) {
2470
+ logEntry += typeof part.output === "string" ? part.output : JSON.stringify(part.output);
2471
+ } else if (part.type === "tool-error" && "error" in part) {
2472
+ logEntry += typeof part.error === "object" && part.error !== null && "message" in part.error ? part.error.message : String(part.error);
2473
+ } else if (part.type === "text" && "text" in part) {
2474
+ logEntry += part.text;
2475
+ }
2476
+ logEntry += "\n";
2477
+ });
2478
+ return logEntry.trim();
2479
+ }
2480
+
2481
+ // src/agent-creators.ts
2482
+ function createCodeAgent(agentConfig) {
2483
+ const {
2484
+ maxSteps,
2485
+ allowSubmit,
2486
+ logStep,
2487
+ omitAdditionalInstructions,
2488
+ tools: originalTools,
2489
+ stopWhen: originalStopWhen,
2490
+ prepareStep: originalPrepareStep,
2491
+ system: originalSystemInstruction,
2492
+ ...remainingConfig
2493
+ } = agentConfig;
2494
+ let agentSettings;
2495
+ let environmentTools;
2496
+ if ("environments" in remainingConfig) {
2497
+ const { environments, environmentToolsDefinition, ...agentSettingsInput } = remainingConfig;
2498
+ agentSettings = { ...agentSettingsInput };
2499
+ environmentTools = {};
2500
+ for (const [environmentName, environment] of Object.entries(environments)) {
2501
+ if (!(environmentName in environmentToolsDefinition)) {
2502
+ throw new Error(
2503
+ `No tools definition provided for environment "${environmentName}". Please provide a tools definition for each environment.`
2504
+ );
2505
+ }
2506
+ const environmentTools2 = createToolsForNamedEnvironment(
2507
+ environmentName,
2508
+ environment,
2509
+ environmentToolsDefinition[environmentName]
2510
+ );
2511
+ for (const [toolName, tool] of Object.entries(environmentTools2)) {
2512
+ if (toolName in environmentTools2) {
2513
+ throw new Error(
2514
+ `Tool name conflict: The tool name "${toolName}" from environment "${environmentName}" is already used by another environment's tools.`
2515
+ );
2516
+ }
2517
+ environmentTools2[toolName] = tool;
2518
+ }
2519
+ }
2520
+ } else if ("environment" in remainingConfig) {
2521
+ const { environment, environmentToolsDefinition, ...agentSettingsInput } = remainingConfig;
2522
+ agentSettings = { ...agentSettingsInput };
2523
+ environmentTools = createToolsForEnvironment(
2524
+ environment,
2525
+ environmentToolsDefinition
2526
+ );
2527
+ } else {
2528
+ agentSettings = { ...remainingConfig };
2529
+ }
2530
+ const tools = environmentTools && originalTools ? mergeTools(environmentTools, originalTools) : originalTools || environmentTools || {};
2531
+ if (allowSubmit) {
2532
+ if (SubmitToolName in tools) {
2533
+ throw new Error(
2534
+ `Tool name conflict: The Submit tool name "${SubmitToolName}" is already used by another tool.`
2535
+ );
2536
+ }
2537
+ tools[SubmitToolName] = new SubmitTool();
2538
+ }
2539
+ if (Object.keys(tools).length > 0) {
2540
+ agentSettings.tools = tools;
2541
+ }
2542
+ let stepCount = 0;
2543
+ const prepareStep = logStep ? (prepareStepInput) => {
2544
+ const { steps } = prepareStepInput;
2545
+ if (steps.length > 0) {
2546
+ stepCount += 1;
2547
+ const stepLog = getStepLog(steps[steps.length - 1]);
2548
+ logStep(`=== Step ${stepCount} ===
2549
+ ${stepLog}`, stepCount - 1);
2550
+ }
2551
+ if (originalPrepareStep) {
2552
+ return originalPrepareStep(prepareStepInput);
2553
+ }
2554
+ return void 0;
2555
+ } : originalPrepareStep;
2556
+ const stopWhenCondition = allowSubmit ? [(0, import_ai.stepCountIs)(maxSteps), (0, import_ai.hasToolCall)(SubmitToolName)] : (0, import_ai.stepCountIs)(maxSteps);
2557
+ const stopWhen = originalStopWhen ? mergeStopWhen(originalStopWhen, stopWhenCondition) : stopWhenCondition;
2558
+ const system = !omitAdditionalInstructions ? mergeSystemInstructions(
2559
+ originalSystemInstruction,
2560
+ getAdditionalInstructions({ maxSteps, allowSubmit, tools })
2561
+ ) : originalSystemInstruction;
2562
+ return new import_ai.Experimental_Agent({
2563
+ ...agentSettings,
2564
+ system,
2565
+ prepareStep,
2566
+ stopWhen
2567
+ });
2568
+ }
2569
+ function mergeTools(baseTools, additionalTools) {
2570
+ const tools = { ...baseTools };
2571
+ for (const [toolName, tool] of Object.entries(additionalTools)) {
2572
+ if (toolName in tools) {
2573
+ throw new Error(
2574
+ `Tool name conflict: The additional tool name "${toolName}" is already used by the code environment tools.`
2575
+ );
2576
+ }
2577
+ tools[toolName] = tool;
2578
+ }
2579
+ return tools;
2580
+ }
2581
+ function mergeStopWhen(baseStopWhen, additionalStopWhen) {
2582
+ if (Array.isArray(baseStopWhen)) {
2583
+ if (Array.isArray(additionalStopWhen)) {
2584
+ return [...baseStopWhen, ...additionalStopWhen];
2585
+ }
2586
+ return [...baseStopWhen, additionalStopWhen];
2587
+ }
2588
+ if (Array.isArray(additionalStopWhen)) {
2589
+ return [baseStopWhen, ...additionalStopWhen];
2590
+ }
2591
+ return [baseStopWhen, additionalStopWhen];
2592
+ }
2593
+ function mergeSystemInstructions(baseSystem, additionalInstructions) {
2594
+ if (baseSystem) {
2595
+ return `${baseSystem.trimEnd()}
2596
+
2597
+ ${additionalInstructions}`;
2598
+ }
2599
+ return additionalInstructions;
2600
+ }
2601
+
2602
+ // src/environment-creators.ts
2603
+ var availableEnvironments = {
2604
+ [UnsafeLocalEnvironmentName]: UnsafeLocalEnvironment,
2605
+ [DockerEnvironmentName]: DockerEnvironment,
2606
+ [MockFilesystemEnvironmentName]: MockFilesystemEnvironment,
2607
+ [NodeFilesystemEnvironmentName]: NodeFilesystemEnvironment
2608
+ };
2609
+ var EnvironmentNames = Object.keys(
2610
+ availableEnvironments
2611
+ );
2612
+ function createEnvironment(environmentName, config) {
2613
+ if (!(environmentName in availableEnvironments)) {
2614
+ throw new Error(`Unsupported environment: ${environmentName}`);
2615
+ }
2616
+ const EnvironmentClass = availableEnvironments[environmentName];
2617
+ return new EnvironmentClass(config);
2618
+ }
2619
+ // Annotate the CommonJS export names for ESM import in node:
2620
+ 0 && (module.exports = {
2621
+ CopyFileResult,
2622
+ CopyFileTool,
2623
+ CopyFileToolInput,
2624
+ CopyFileToolName,
2625
+ CopyFileToolOutput,
2626
+ DeleteFileResult,
2627
+ DeleteFileTool,
2628
+ DeleteFileToolInput,
2629
+ DeleteFileToolName,
2630
+ DeleteFileToolOutput,
2631
+ DockerEnvironment,
2632
+ DockerEnvironmentName,
2633
+ EditFileTool,
2634
+ EditFileToolInput,
2635
+ EditFileToolName,
2636
+ EditFileToolOutput,
2637
+ EnvironmentNames,
2638
+ EnvironmentToolNames,
2639
+ EnvironmentToolSafetyLevels,
2640
+ GetProjectFileStructureTool,
2641
+ GetProjectFileStructureToolInput,
2642
+ GetProjectFileStructureToolName,
2643
+ GetProjectFileStructureToolOutput,
2644
+ GlobTool,
2645
+ GlobToolInput,
2646
+ GlobToolName,
2647
+ GlobToolOutput,
2648
+ ListDirectoryTool,
2649
+ ListDirectoryToolInput,
2650
+ ListDirectoryToolName,
2651
+ ListDirectoryToolOutput,
2652
+ MockFilesystemEnvironment,
2653
+ MockFilesystemEnvironmentName,
2654
+ MoveFileResult,
2655
+ MoveFileTool,
2656
+ MoveFileToolInput,
2657
+ MoveFileToolName,
2658
+ MoveFileToolOutput,
2659
+ NodeFilesystemEnvironment,
2660
+ NodeFilesystemEnvironmentName,
2661
+ ReadFileResult,
2662
+ ReadFileTool,
2663
+ ReadFileToolInput,
2664
+ ReadFileToolName,
2665
+ ReadFileToolOutput,
2666
+ ReadManyFilesTool,
2667
+ ReadManyFilesToolInput,
2668
+ ReadManyFilesToolName,
2669
+ ReadManyFilesToolOutput,
2670
+ RunCommandResult,
2671
+ RunCommandTool,
2672
+ RunCommandToolInput,
2673
+ RunCommandToolName,
2674
+ RunCommandToolOutput,
2675
+ UnsafeLocalEnvironment,
2676
+ UnsafeLocalEnvironmentName,
2677
+ WriteFileResult,
2678
+ WriteFileTool,
2679
+ WriteFileToolInput,
2680
+ WriteFileToolName,
2681
+ WriteFileToolOutput,
2682
+ createCodeAgent,
2683
+ createEnvironment,
2684
+ createEnvironmentTool,
2685
+ createToolsForEnvironment,
2686
+ createToolsForNamedEnvironment
2687
+ });
2688
+ //# sourceMappingURL=index.cjs.map