@avasis-ai/synthcode 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +292 -0
  3. package/dist/chunk-53ZOIXM4.js +624 -0
  4. package/dist/chunk-53ZOIXM4.js.map +1 -0
  5. package/dist/chunk-BWXHO6UJ.js +115 -0
  6. package/dist/chunk-BWXHO6UJ.js.map +1 -0
  7. package/dist/chunk-CARUMOML.js +123 -0
  8. package/dist/chunk-CARUMOML.js.map +1 -0
  9. package/dist/chunk-DGUM43GV.js +11 -0
  10. package/dist/chunk-DGUM43GV.js.map +1 -0
  11. package/dist/chunk-F34HO4RA.js +487 -0
  12. package/dist/chunk-F34HO4RA.js.map +1 -0
  13. package/dist/chunk-FK7S2S7V.js +132 -0
  14. package/dist/chunk-FK7S2S7V.js.map +1 -0
  15. package/dist/chunk-MQ7XP6VT.js +174 -0
  16. package/dist/chunk-MQ7XP6VT.js.map +1 -0
  17. package/dist/chunk-TLPOO6C3.js +176 -0
  18. package/dist/chunk-TLPOO6C3.js.map +1 -0
  19. package/dist/chunk-W6OLZ2OI.js +56 -0
  20. package/dist/chunk-W6OLZ2OI.js.map +1 -0
  21. package/dist/cli/index.cjs +151 -0
  22. package/dist/cli/index.cjs.map +1 -0
  23. package/dist/cli/index.d.cts +1 -0
  24. package/dist/cli/index.d.ts +1 -0
  25. package/dist/cli/index.js +8 -0
  26. package/dist/cli/index.js.map +1 -0
  27. package/dist/cli/run.cjs +128 -0
  28. package/dist/cli/run.cjs.map +1 -0
  29. package/dist/cli/run.d.cts +1 -0
  30. package/dist/cli/run.d.ts +1 -0
  31. package/dist/cli/run.js +126 -0
  32. package/dist/cli/run.js.map +1 -0
  33. package/dist/index-D-K6sx8s.d.cts +8 -0
  34. package/dist/index-D-K6sx8s.d.ts +8 -0
  35. package/dist/index.cjs +2909 -0
  36. package/dist/index.cjs.map +1 -0
  37. package/dist/index.d.cts +274 -0
  38. package/dist/index.d.ts +274 -0
  39. package/dist/index.js +1048 -0
  40. package/dist/index.js.map +1 -0
  41. package/dist/llm/index.cjs +531 -0
  42. package/dist/llm/index.cjs.map +1 -0
  43. package/dist/llm/index.d.cts +70 -0
  44. package/dist/llm/index.d.ts +70 -0
  45. package/dist/llm/index.js +24 -0
  46. package/dist/llm/index.js.map +1 -0
  47. package/dist/mcp/index.cjs +323 -0
  48. package/dist/mcp/index.cjs.map +1 -0
  49. package/dist/mcp/index.d.cts +39 -0
  50. package/dist/mcp/index.d.ts +39 -0
  51. package/dist/mcp/index.js +11 -0
  52. package/dist/mcp/index.js.map +1 -0
  53. package/dist/memory/index.cjs +146 -0
  54. package/dist/memory/index.cjs.map +1 -0
  55. package/dist/memory/index.d.cts +51 -0
  56. package/dist/memory/index.d.ts +51 -0
  57. package/dist/memory/index.js +10 -0
  58. package/dist/memory/index.js.map +1 -0
  59. package/dist/tools/fuzzy-edit.cjs +200 -0
  60. package/dist/tools/fuzzy-edit.cjs.map +1 -0
  61. package/dist/tools/fuzzy-edit.d.cts +9 -0
  62. package/dist/tools/fuzzy-edit.d.ts +9 -0
  63. package/dist/tools/fuzzy-edit.js +12 -0
  64. package/dist/tools/fuzzy-edit.js.map +1 -0
  65. package/dist/tools/index.cjs +1032 -0
  66. package/dist/tools/index.cjs.map +1 -0
  67. package/dist/tools/index.d.cts +4 -0
  68. package/dist/tools/index.d.ts +4 -0
  69. package/dist/tools/index.js +39 -0
  70. package/dist/tools/index.js.map +1 -0
  71. package/dist/types-C11cw5ZD.d.cts +177 -0
  72. package/dist/types-C11cw5ZD.d.ts +177 -0
  73. package/dist/utils-TF4TBXQJ.js +10 -0
  74. package/dist/utils-TF4TBXQJ.js.map +1 -0
  75. package/dist/web-fetch-B42QzYD2.d.cts +85 -0
  76. package/dist/web-fetch-EDdhxmEf.d.ts +85 -0
  77. package/package.json +134 -0
@@ -0,0 +1,1032 @@
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 __esm = (fn, res) => function __init() {
9
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
10
+ };
11
+ var __export = (target, all) => {
12
+ for (var name in all)
13
+ __defProp(target, name, { get: all[name], enumerable: true });
14
+ };
15
+ var __copyProps = (to, from, except, desc) => {
16
+ if (from && typeof from === "object" || typeof from === "function") {
17
+ for (let key of __getOwnPropNames(from))
18
+ if (!__hasOwnProp.call(to, key) && key !== except)
19
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
20
+ }
21
+ return to;
22
+ };
23
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
24
+ // If the importer is in node compatibility mode or this is not an ESM
25
+ // file that has been converted to a CommonJS file using a Babel-
26
+ // compatible transform (i.e. "__esModule" has not been set), then set
27
+ // "default" to the CommonJS "module.exports" for node compatibility.
28
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
29
+ mod
30
+ ));
31
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
32
+
33
+ // src/utils.ts
34
+ var utils_exports = {};
35
+ __export(utils_exports, {
36
+ globToRegExp: () => globToRegExp,
37
+ walkDir: () => walkDir
38
+ });
39
+ function globToRegExp(pattern) {
40
+ const parts = pattern.split("/");
41
+ let regex = "";
42
+ for (let i = 0; i < parts.length; i++) {
43
+ const part = parts[i];
44
+ if (part === "**") {
45
+ regex += "(?:[^/]*(?:\\/|$))*";
46
+ } else {
47
+ const escaped = part.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, "[^/]*").replace(/\?/g, "[^/]");
48
+ regex += escaped + "\\/";
49
+ }
50
+ }
51
+ regex = regex.replace(/\\\//g, "/").replace(/\/$/, "");
52
+ return new RegExp(`(^|/)${regex}(/|$)`);
53
+ }
54
+ async function walkDir(dir, options) {
55
+ const maxDepth = options?.maxDepth ?? Infinity;
56
+ const followSymlinks = options?.followSymlinks ?? false;
57
+ const results = [];
58
+ async function walk(current, depth) {
59
+ if (depth > maxDepth) return;
60
+ let entries;
61
+ try {
62
+ entries = await fs4.promises.readdir(current, { withFileTypes: true });
63
+ } catch {
64
+ return;
65
+ }
66
+ for (const entry of entries) {
67
+ const fullPath = path4.join(current, entry.name);
68
+ if (entry.name === "node_modules" || entry.name === ".git") continue;
69
+ try {
70
+ let stat;
71
+ if (entry.isSymbolicLink() && !followSymlinks) continue;
72
+ stat = await fs4.promises.stat(fullPath);
73
+ if (stat.isFile()) {
74
+ results.push({ path: fullPath, stat });
75
+ } else if (stat.isDirectory()) {
76
+ await walk(fullPath, depth + 1);
77
+ }
78
+ } catch {
79
+ continue;
80
+ }
81
+ }
82
+ }
83
+ await walk(dir, 0);
84
+ return results;
85
+ }
86
+ var fs4, path4;
87
+ var init_utils = __esm({
88
+ "src/utils.ts"() {
89
+ "use strict";
90
+ fs4 = __toESM(require("fs"), 1);
91
+ path4 = __toESM(require("path"), 1);
92
+ }
93
+ });
94
+
95
+ // src/tools/index.ts
96
+ var tools_exports = {};
97
+ __export(tools_exports, {
98
+ BashTool: () => BashTool,
99
+ FileEditTool: () => FileEditTool,
100
+ FileReadTool: () => FileReadTool,
101
+ FileWriteTool: () => FileWriteTool,
102
+ FuzzyEditError: () => FuzzyEditError,
103
+ GlobTool: () => GlobTool,
104
+ GrepTool: () => GrepTool,
105
+ ToolRegistry: () => ToolRegistry,
106
+ WebFetchTool: () => WebFetchTool,
107
+ defineTool: () => defineTool,
108
+ defineToolFromClass: () => defineToolFromClass,
109
+ fuzzyContains: () => fuzzyContains,
110
+ fuzzyReplace: () => fuzzyReplace,
111
+ orchestrateTools: () => orchestrateTools
112
+ });
113
+ module.exports = __toCommonJS(tools_exports);
114
+
115
+ // src/tools/tool.ts
116
+ function zodToJsonSchema(schema) {
117
+ const s = schema;
118
+ const def = s._def;
119
+ const typeName = def.typeName;
120
+ const description = def.description;
121
+ const base = {};
122
+ if (description) base.description = description;
123
+ switch (typeName) {
124
+ case "ZodString":
125
+ return { ...base, type: "string" };
126
+ case "ZodNumber":
127
+ return { ...base, type: "number" };
128
+ case "ZodBoolean":
129
+ return { ...base, type: "boolean" };
130
+ case "ZodNull":
131
+ return { ...base, type: "null" };
132
+ case "ZodArray": {
133
+ const items = zodToJsonSchema(def.element);
134
+ return { ...base, type: "array", items };
135
+ }
136
+ case "ZodObject": {
137
+ const shapeFn = def.shape;
138
+ const shape = shapeFn();
139
+ const properties = {};
140
+ const required = [];
141
+ for (const [key, value] of Object.entries(shape)) {
142
+ properties[key] = zodToJsonSchema(value);
143
+ const propDef = value._def;
144
+ if (propDef.typeName !== "ZodOptional" && propDef.typeName !== "ZodNullish" && propDef.typeName !== "ZodDefault") {
145
+ required.push(key);
146
+ }
147
+ }
148
+ const result = { ...base, type: "object", properties };
149
+ if (required.length > 0) result.required = required;
150
+ return result;
151
+ }
152
+ case "ZodEnum":
153
+ return { ...base, enum: def.values };
154
+ case "ZodLiteral":
155
+ return { ...base, const: def.value };
156
+ case "ZodUnion": {
157
+ const options = def.options.map((o) => zodToJsonSchema(o));
158
+ return { ...base, anyOf: options };
159
+ }
160
+ case "ZodDiscriminatedUnion": {
161
+ const options = def.options.map((o) => zodToJsonSchema(o));
162
+ return { ...base, anyOf: options };
163
+ }
164
+ case "ZodOptional":
165
+ return zodToJsonSchema(def.innerType);
166
+ case "ZodNullable": {
167
+ const inner = zodToJsonSchema(def.innerType);
168
+ inner.nullable = true;
169
+ return inner;
170
+ }
171
+ case "ZodNullish": {
172
+ const inner = zodToJsonSchema(def.innerType);
173
+ inner.nullable = true;
174
+ return inner;
175
+ }
176
+ case "ZodDefault":
177
+ return zodToJsonSchema(def.innerType);
178
+ case "ZodRecord": {
179
+ const valueSchema = zodToJsonSchema(def.valueType);
180
+ return { ...base, type: "object", additionalProperties: valueSchema };
181
+ }
182
+ case "ZodTuple": {
183
+ const items = def.items.map((o) => zodToJsonSchema(o));
184
+ return { ...base, type: "array", items, minItems: items.length, maxItems: items.length };
185
+ }
186
+ case "ZodEffects": {
187
+ return zodToJsonSchema(def.innerType);
188
+ }
189
+ case "ZodAny":
190
+ return {};
191
+ case "ZodUnknown":
192
+ return {};
193
+ case "ZodVoid":
194
+ return { ...base, type: "null" };
195
+ case "ZodNever":
196
+ return { ...base, not: {} };
197
+ default:
198
+ return { ...base, type: "string" };
199
+ }
200
+ }
201
+ function defineTool(config) {
202
+ const tool = {
203
+ name: config.name,
204
+ description: config.description,
205
+ inputSchema: config.inputSchema,
206
+ isReadOnly: config.isReadOnly ?? false,
207
+ isConcurrencySafe: config.isConcurrencySafe ?? false,
208
+ execute: config.execute,
209
+ toAPI() {
210
+ return {
211
+ name: config.name,
212
+ description: config.description,
213
+ input_schema: zodToJsonSchema(config.inputSchema)
214
+ };
215
+ },
216
+ toString(input) {
217
+ const entries = Object.entries(input).map(([k, v]) => {
218
+ if (typeof v === "string") return `${k}: "${v}"`;
219
+ if (v === void 0) return `${k}: undefined`;
220
+ if (v === null) return `${k}: null`;
221
+ return `${k}: ${String(v)}`;
222
+ }).join(", ");
223
+ return `${config.name}({ ${entries} })`;
224
+ }
225
+ };
226
+ return tool;
227
+ }
228
+ function defineToolFromClass(ctor) {
229
+ const instance = new ctor();
230
+ return {
231
+ name: instance.name,
232
+ description: instance.description,
233
+ inputSchema: instance.inputSchema,
234
+ isReadOnly: instance.isReadOnly,
235
+ isConcurrencySafe: instance.isConcurrencySafe,
236
+ execute: (input, context) => instance.execute(input, context),
237
+ toAPI: () => instance.toAPI(),
238
+ toString: (input) => instance.toString(input)
239
+ };
240
+ }
241
+
242
+ // src/tools/registry.ts
243
+ var ToolRegistry = class {
244
+ tools = /* @__PURE__ */ new Map();
245
+ constructor(tools) {
246
+ if (tools) {
247
+ for (const tool of tools) {
248
+ this.add(tool);
249
+ }
250
+ }
251
+ }
252
+ /** Add a tool to the registry. Duplicate names are ignored (first one wins). */
253
+ add(tool) {
254
+ if (this.tools.has(tool.name)) {
255
+ console.warn(`[ToolRegistry] Duplicate tool "${tool.name}" ignored (first one wins)`);
256
+ return;
257
+ }
258
+ this.tools.set(tool.name, tool);
259
+ }
260
+ /** Get a tool by name. */
261
+ get(name) {
262
+ return this.tools.get(name);
263
+ }
264
+ /** Check if a tool exists by name. */
265
+ has(name) {
266
+ return this.tools.has(name);
267
+ }
268
+ /** Find tool by case-insensitive name. Returns undefined if not found. */
269
+ findCaseInsensitive(name) {
270
+ const lower = name.toLowerCase();
271
+ if (this.tools.has(name)) return name;
272
+ for (const key of this.tools.keys()) {
273
+ if (key.toLowerCase() === lower) return key;
274
+ }
275
+ return void 0;
276
+ }
277
+ /** List all registered tool names. */
278
+ listNames() {
279
+ return Array.from(this.tools.keys());
280
+ }
281
+ /** Get all registered tools. */
282
+ getAll() {
283
+ return Array.from(this.tools.values());
284
+ }
285
+ /** Get all tools in API format, sorted by name for cache stability. */
286
+ getAPI() {
287
+ return this.getAll().sort((a, b) => a.name.localeCompare(b.name)).map((t) => t.toAPI());
288
+ }
289
+ /** Number of registered tools. */
290
+ get size() {
291
+ return this.tools.size;
292
+ }
293
+ };
294
+
295
+ // src/tools/orchestrator.ts
296
+ var Semaphore = class {
297
+ constructor(max) {
298
+ this.max = max;
299
+ }
300
+ max;
301
+ current = 0;
302
+ queue = [];
303
+ acquire() {
304
+ if (this.current < this.max) {
305
+ this.current++;
306
+ return Promise.resolve();
307
+ }
308
+ return new Promise((resolve) => {
309
+ this.queue.push(resolve);
310
+ });
311
+ }
312
+ release() {
313
+ this.current--;
314
+ const next = this.queue.shift();
315
+ if (next) {
316
+ this.current++;
317
+ next();
318
+ }
319
+ }
320
+ };
321
+ function partitionToolCalls(toolCalls, registry) {
322
+ const batches = [];
323
+ let currentBatch = [];
324
+ let currentBatchIsConcurrent = false;
325
+ for (const call of toolCalls) {
326
+ const tool = registry.get(call.name);
327
+ const isConcurrent = tool ? tool.isReadOnly && tool.isConcurrencySafe : false;
328
+ if (isConcurrent && currentBatchIsConcurrent) {
329
+ currentBatch.push(call);
330
+ } else {
331
+ if (currentBatch.length > 0) {
332
+ batches.push(currentBatch);
333
+ }
334
+ currentBatch = [call];
335
+ currentBatchIsConcurrent = isConcurrent;
336
+ }
337
+ }
338
+ if (currentBatch.length > 0) {
339
+ batches.push(currentBatch);
340
+ }
341
+ return batches;
342
+ }
343
+ async function executeToolCall(call, registry, context, permissionCheck, abortSignal) {
344
+ if (abortSignal?.aborted) {
345
+ return {
346
+ id: call.id,
347
+ name: call.name,
348
+ output: "Execution aborted",
349
+ isError: true,
350
+ durationMs: 0
351
+ };
352
+ }
353
+ const tool = registry.get(call.name);
354
+ if (!tool) {
355
+ return {
356
+ id: call.id,
357
+ name: call.name,
358
+ output: `Unknown tool: ${call.name}`,
359
+ isError: true,
360
+ durationMs: 0
361
+ };
362
+ }
363
+ const start = performance.now();
364
+ try {
365
+ const parseResult = tool.inputSchema.safeParse(call.input);
366
+ if (!parseResult.success) {
367
+ return {
368
+ id: call.id,
369
+ name: call.name,
370
+ output: `Invalid input for ${call.name}: ${parseResult.error.issues.map((i) => i.message).join(", ")}`,
371
+ isError: true,
372
+ durationMs: Math.round(performance.now() - start)
373
+ };
374
+ }
375
+ if (permissionCheck) {
376
+ const allowed = await permissionCheck(call.name, call.input);
377
+ if (!allowed) {
378
+ return {
379
+ id: call.id,
380
+ name: call.name,
381
+ output: `Permission denied for tool: ${call.name}`,
382
+ isError: true,
383
+ durationMs: Math.round(performance.now() - start)
384
+ };
385
+ }
386
+ }
387
+ const output = await tool.execute(parseResult.data, context);
388
+ return {
389
+ id: call.id,
390
+ name: call.name,
391
+ output,
392
+ isError: false,
393
+ durationMs: Math.round(performance.now() - start)
394
+ };
395
+ } catch (err) {
396
+ const message = err instanceof Error ? err.message : String(err);
397
+ return {
398
+ id: call.id,
399
+ name: call.name,
400
+ output: `Error executing ${call.name}: ${message}`,
401
+ isError: true,
402
+ durationMs: Math.round(performance.now() - start)
403
+ };
404
+ }
405
+ }
406
+ async function orchestrateTools(tools, toolCalls, context, permissionCheck, abortSignal) {
407
+ const batches = partitionToolCalls(toolCalls, tools);
408
+ const results = [];
409
+ for (const batch of batches) {
410
+ if (abortSignal?.aborted) {
411
+ for (const call of batch) {
412
+ results.push({
413
+ id: call.id,
414
+ name: call.name,
415
+ output: "Execution aborted",
416
+ isError: true,
417
+ durationMs: 0
418
+ });
419
+ }
420
+ continue;
421
+ }
422
+ if (batch.length > 1) {
423
+ const semaphore = new Semaphore(10);
424
+ const promises2 = batch.map(
425
+ (call) => semaphore.acquire().then(async () => {
426
+ try {
427
+ return await executeToolCall(call, tools, context, permissionCheck, abortSignal);
428
+ } finally {
429
+ semaphore.release();
430
+ }
431
+ })
432
+ );
433
+ const settled = await Promise.allSettled(promises2);
434
+ for (let i = 0; i < settled.length; i++) {
435
+ const s = settled[i];
436
+ if (s.status === "fulfilled") {
437
+ results.push(s.value);
438
+ } else {
439
+ results.push({
440
+ id: batch[i].id,
441
+ name: batch[i].name,
442
+ output: `Unexpected error: ${s.reason instanceof Error ? s.reason.message : String(s.reason)}`,
443
+ isError: true,
444
+ durationMs: 0
445
+ });
446
+ }
447
+ }
448
+ } else {
449
+ const result = await executeToolCall(batch[0], tools, context, permissionCheck, abortSignal);
450
+ results.push(result);
451
+ }
452
+ }
453
+ return results;
454
+ }
455
+
456
+ // src/tools/bash.ts
457
+ var import_node_child_process = require("child_process");
458
+ var import_zod = require("zod");
459
+ var MAX_OUTPUT = 50 * 1024;
460
+ var TRUNCATE_HALF = 25 * 1024;
461
+ function truncateOutput(output) {
462
+ if (output.length <= MAX_OUTPUT) return output;
463
+ const notice = `
464
+
465
+ ... [output truncated: showing first ${TRUNCATE_HALF} and last ${TRUNCATE_HALF} of ${output.length} characters] ...
466
+
467
+ `;
468
+ return output.slice(0, TRUNCATE_HALF) + notice + output.slice(-TRUNCATE_HALF);
469
+ }
470
+ var BashTool = defineTool({
471
+ name: "bash",
472
+ description: "Execute a shell command. Returns stdout and stderr. Use for running build commands, git operations, package managers, and other CLI tools.",
473
+ inputSchema: import_zod.z.object({
474
+ command: import_zod.z.string().describe("The shell command to execute"),
475
+ timeout: import_zod.z.number().optional().describe("Timeout in milliseconds (default 120000)"),
476
+ workdir: import_zod.z.string().optional().describe("Working directory for the command")
477
+ }),
478
+ isReadOnly: false,
479
+ isConcurrencySafe: false,
480
+ execute: async ({ command, timeout = 12e4, workdir }, context) => {
481
+ return new Promise((resolve) => {
482
+ let settled = false;
483
+ const done = (result) => {
484
+ if (settled) return;
485
+ settled = true;
486
+ resolve(result);
487
+ };
488
+ if (context.abortSignal?.aborted) {
489
+ done("Command aborted before execution");
490
+ return;
491
+ }
492
+ const child = (0, import_node_child_process.exec)(
493
+ command,
494
+ {
495
+ cwd: workdir ?? context.cwd,
496
+ timeout,
497
+ maxBuffer: 10 * 1024 * 1024,
498
+ killSignal: "SIGKILL"
499
+ },
500
+ (error, stdout, stderr) => {
501
+ let output = "";
502
+ if (stdout) output += `STDOUT:
503
+ ${stdout}
504
+
505
+ `;
506
+ if (stderr) output += `STDERR:
507
+ ${stderr}
508
+
509
+ `;
510
+ output += `Exit code: ${error?.code ?? 0}`;
511
+ if (error && error.killed) {
512
+ output = `Command timed out after ${timeout}ms
513
+
514
+ ${output}`;
515
+ }
516
+ done(truncateOutput(output));
517
+ }
518
+ );
519
+ child.on("error", (err) => {
520
+ done(`Failed to execute command: ${err.message}`);
521
+ });
522
+ if (context.abortSignal) {
523
+ context.abortSignal.addEventListener(
524
+ "abort",
525
+ () => {
526
+ child.kill("SIGKILL");
527
+ done("Command aborted");
528
+ },
529
+ { once: true }
530
+ );
531
+ }
532
+ });
533
+ }
534
+ });
535
+
536
+ // src/tools/file-read.ts
537
+ var import_promises = __toESM(require("fs/promises"), 1);
538
+ var import_node_path = __toESM(require("path"), 1);
539
+ var import_zod2 = require("zod");
540
+ var MAX_LINE_LENGTH = 2e3;
541
+ var FileReadTool = defineTool({
542
+ name: "file_read",
543
+ description: "Read the contents of a file. Returns the file content with line numbers. Use GlobTool to find files first.",
544
+ inputSchema: import_zod2.z.object({
545
+ path: import_zod2.z.string().describe("Absolute or relative path to the file"),
546
+ offset: import_zod2.z.number().optional().describe("Line number to start reading from (1-indexed)"),
547
+ limit: import_zod2.z.number().optional().describe("Maximum number of lines to read")
548
+ }),
549
+ isReadOnly: true,
550
+ isConcurrencySafe: true,
551
+ execute: async ({ path: filePath, offset, limit }, context) => {
552
+ try {
553
+ const resolved = import_node_path.default.isAbsolute(filePath) ? filePath : import_node_path.default.resolve(context.cwd, filePath);
554
+ const content = await import_promises.default.readFile(resolved, "utf-8");
555
+ const lines = content.split("\n");
556
+ const startLine = offset ? Math.max(1, offset) : 1;
557
+ const startIndex = startLine - 1;
558
+ const endIndex = limit != null ? startIndex + limit : lines.length;
559
+ const selected = lines.slice(startIndex, endIndex);
560
+ const formatted = selected.map((line, i) => {
561
+ const lineNum = startLine + i;
562
+ const truncated = line.length > MAX_LINE_LENGTH ? line.slice(0, MAX_LINE_LENGTH) + "..." : line;
563
+ return `${lineNum}: ${truncated}`;
564
+ }).join("\n");
565
+ return formatted;
566
+ } catch (err) {
567
+ if (err.code === "ENOENT") {
568
+ return `Error: File not found: ${filePath}`;
569
+ }
570
+ if (err.code === "EISDIR") {
571
+ return `Error: Path is a directory: ${filePath}`;
572
+ }
573
+ return `Error reading file: ${err instanceof Error ? err.message : String(err)}`;
574
+ }
575
+ }
576
+ });
577
+
578
+ // src/tools/file-write.ts
579
+ var import_promises2 = __toESM(require("fs/promises"), 1);
580
+ var import_node_path2 = __toESM(require("path"), 1);
581
+ var import_zod3 = require("zod");
582
+ var FileWriteTool = defineTool({
583
+ name: "file_write",
584
+ description: "Write content to a file. Creates the file if it doesn't exist, overwrites if it does. Parent directories are created automatically.",
585
+ inputSchema: import_zod3.z.object({
586
+ path: import_zod3.z.string().describe("Path to the file"),
587
+ content: import_zod3.z.string().describe("Content to write")
588
+ }),
589
+ isReadOnly: false,
590
+ isConcurrencySafe: false,
591
+ execute: async ({ path: filePath, content }, context) => {
592
+ try {
593
+ const resolved = import_node_path2.default.isAbsolute(filePath) ? filePath : import_node_path2.default.resolve(context.cwd, filePath);
594
+ const dir = import_node_path2.default.dirname(resolved);
595
+ await import_promises2.default.mkdir(dir, { recursive: true });
596
+ await import_promises2.default.writeFile(resolved, content, "utf-8");
597
+ return `Wrote ${content.length} characters to ${filePath}`;
598
+ } catch (err) {
599
+ return `Error writing file: ${err instanceof Error ? err.message : String(err)}`;
600
+ }
601
+ }
602
+ });
603
+
604
+ // src/tools/file-edit.ts
605
+ var import_promises3 = __toESM(require("fs/promises"), 1);
606
+ var import_node_path3 = __toESM(require("path"), 1);
607
+ var import_zod4 = require("zod");
608
+
609
+ // src/tools/fuzzy-edit.ts
610
+ var FuzzyEditError = class extends Error {
611
+ constructor(kind, message) {
612
+ super(message);
613
+ this.kind = kind;
614
+ this.name = "FuzzyEditError";
615
+ }
616
+ kind;
617
+ };
618
+ function levenshtein(a, b) {
619
+ const m = a.length;
620
+ const n = b.length;
621
+ if (m === 0) return n;
622
+ if (n === 0) return m;
623
+ const dp = Array.from({ length: m + 1 }, () => new Array(n + 1).fill(0));
624
+ for (let i = 0; i <= m; i++) dp[i][0] = i;
625
+ for (let j = 0; j <= n; j++) dp[0][j] = j;
626
+ for (let i = 1; i <= m; i++) {
627
+ for (let j = 1; j <= n; j++) {
628
+ const cost = a[i - 1] === b[j - 1] ? 0 : 1;
629
+ dp[i][j] = Math.min(dp[i - 1][j] + 1, dp[i][j - 1] + 1, dp[i - 1][j - 1] + cost);
630
+ }
631
+ }
632
+ return dp[m][n];
633
+ }
634
+ function similarity(a, b) {
635
+ if (a.length > 1e3 || b.length > 1e3) return a === b ? 1 : 0;
636
+ const maxLen = Math.max(a.length, b.length);
637
+ if (maxLen === 0) return 1;
638
+ return 1 - levenshtein(a, b) / maxLen;
639
+ }
640
+ function* simpleReplacer(content, find) {
641
+ if (content.includes(find)) yield find;
642
+ }
643
+ function* lineTrimmedReplacer(content, find) {
644
+ const lines = find.split("\n").map((l) => l.trim());
645
+ const contentLines = content.split("\n");
646
+ for (let i = 0; i <= contentLines.length - lines.length; i++) {
647
+ if (contentLines.slice(i, i + lines.length).every((cl, idx) => cl.trim() === lines[idx])) {
648
+ yield contentLines.slice(i, i + lines.length).join("\n");
649
+ }
650
+ }
651
+ }
652
+ function* blockAnchorReplacer(content, find) {
653
+ const findLines = find.split("\n");
654
+ const contentLines = content.split("\n");
655
+ if (findLines.length < 2) return;
656
+ const firstLine = findLines[0];
657
+ const lastLine = findLines[findLines.length - 1];
658
+ const middleLines = findLines.slice(1, -1);
659
+ for (let i = 0; i <= contentLines.length - findLines.length; i++) {
660
+ if (contentLines[i] !== firstLine) continue;
661
+ const endIdx = i + findLines.length - 1;
662
+ if (contentLines[endIdx] !== lastLine) continue;
663
+ const candidates = [];
664
+ for (let j = i + 1; j < endIdx; j++) {
665
+ candidates.push({ idx: j, score: 0 });
666
+ }
667
+ let totalScore = 0;
668
+ for (let k = 0; k < middleLines.length; k++) {
669
+ const contentLine = contentLines[i + 1 + k];
670
+ const sim = similarity(middleLines[k], contentLine);
671
+ totalScore += sim;
672
+ if (candidates[k]) candidates[k].score = sim;
673
+ }
674
+ const avgScore = totalScore / middleLines.length;
675
+ const threshold = candidates.length > 1 ? 0.3 : 0;
676
+ if (avgScore >= threshold) {
677
+ yield contentLines.slice(i, i + findLines.length).join("\n");
678
+ }
679
+ }
680
+ }
681
+ function* whitespaceNormalizedReplacer(content, find) {
682
+ const normFind = find.replace(/\s+/g, " ").trim();
683
+ if (!normFind) return;
684
+ const normContent = content.replace(/\s+/g, " ").trim();
685
+ const idx = normContent.indexOf(normFind);
686
+ if (idx === -1) return;
687
+ const firstWord = normFind.split(" ")[0];
688
+ const lastWord = normFind.split(" ").filter(Boolean).pop();
689
+ const firstIdx = content.indexOf(firstWord);
690
+ const lastIdx = content.lastIndexOf(lastWord);
691
+ if (firstIdx === -1 || lastIdx === -1 || lastIdx < firstIdx) return;
692
+ yield content.substring(firstIdx, lastIdx + lastWord.length);
693
+ }
694
+ function* indentationFlexibleReplacer(content, find) {
695
+ const lines = find.split("\n");
696
+ const minIndent = Math.min(...lines.filter((l) => l.trim().length > 0).map((l) => l.match(/^(\s*)/)?.[1].length ?? 0));
697
+ const dedented = lines.map((l) => l.substring(minIndent)).join("\n");
698
+ if (content.includes(dedented)) yield dedented;
699
+ }
700
+ function* escapeNormalizedReplacer(content, find) {
701
+ const normalized = find.replace(/\\n/g, "\n").replace(/\\t/g, " ").replace(/\\"/g, '"').replace(/\\'/g, "'");
702
+ if (content.includes(normalized)) yield normalized;
703
+ }
704
+ function* trimmedBoundaryReplacer(content, find) {
705
+ const trimmed = find.trim();
706
+ if (content.includes(trimmed)) yield trimmed;
707
+ }
708
+ function* contextAwareReplacer(content, find) {
709
+ const findLines = find.split("\n");
710
+ if (findLines.length < 3) return;
711
+ const firstLine = findLines[0].trim();
712
+ const lastLine = findLines[findLines.length - 1].trim();
713
+ const contentLines = content.split("\n");
714
+ for (let i = 0; i <= contentLines.length - 3; i++) {
715
+ if (contentLines[i].trim() !== firstLine) continue;
716
+ let bestEndIdx = -1;
717
+ let bestScore = 0;
718
+ for (let j = i + 2; j < contentLines.length; j++) {
719
+ if (contentLines[j].trim() === lastLine) {
720
+ const middleCount = j - i - 1;
721
+ let matchCount = 0;
722
+ for (let k = 1; k <= middleCount; k++) {
723
+ const fIdx = Math.floor(k / (middleCount + 1) * (findLines.length - 2));
724
+ if (fIdx >= 0 && fIdx < findLines.length - 2) {
725
+ if (similarity(contentLines[i + k].trim(), findLines[fIdx + 1].trim()) > 0.5) {
726
+ matchCount++;
727
+ }
728
+ }
729
+ }
730
+ const score = matchCount / middleCount;
731
+ if (score > bestScore) {
732
+ bestScore = score;
733
+ bestEndIdx = j;
734
+ }
735
+ }
736
+ }
737
+ if (bestEndIdx !== -1 && bestScore > 0.5) {
738
+ yield contentLines.slice(i, bestEndIdx + 1).join("\n");
739
+ }
740
+ }
741
+ }
742
+ var REPLACERS = [
743
+ simpleReplacer,
744
+ lineTrimmedReplacer,
745
+ blockAnchorReplacer,
746
+ whitespaceNormalizedReplacer,
747
+ indentationFlexibleReplacer,
748
+ escapeNormalizedReplacer,
749
+ trimmedBoundaryReplacer,
750
+ contextAwareReplacer
751
+ ];
752
+ function fuzzyReplace(content, oldString, newString, replaceAll = false) {
753
+ for (const replacer of REPLACERS) {
754
+ for (const search of replacer(content, oldString)) {
755
+ const idx = content.indexOf(search);
756
+ if (idx === -1) continue;
757
+ if (replaceAll) {
758
+ return content.split(search).join(newString);
759
+ }
760
+ const firstIdx = content.indexOf(search);
761
+ const lastIdx = content.lastIndexOf(search);
762
+ if (firstIdx !== lastIdx) continue;
763
+ return content.substring(0, firstIdx) + newString + content.substring(firstIdx + search.length);
764
+ }
765
+ }
766
+ throw new FuzzyEditError("not_found", `Could not find match for replacement (after 8 fuzzy strategies)`);
767
+ }
768
+ function fuzzyContains(content, find) {
769
+ try {
770
+ fuzzyReplace(content, find, "PLACEHOLDER_CHECK");
771
+ return true;
772
+ } catch {
773
+ return false;
774
+ }
775
+ }
776
+
777
+ // src/tools/file-edit.ts
778
+ var FileEditTool = defineTool({
779
+ name: "file_edit",
780
+ description: "Edit an existing file by replacing a string match with new content. Uses 9-strategy fuzzy matching (exact, line-trimmed, block-anchor with Levenshtein, whitespace-normalized, indentation-flexible, escape-normalized, trimmed-boundary, context-aware, multi-occurrence) so the oldString does not need to be a perfect character-for-character match. For multi-line edits, include enough surrounding context to ensure uniqueness.",
781
+ inputSchema: import_zod4.z.object({
782
+ path: import_zod4.z.string().describe("Path to the file"),
783
+ oldString: import_zod4.z.string().describe("The string to find and replace (fuzzy-matched)"),
784
+ newString: import_zod4.z.string().describe("The replacement string"),
785
+ replaceAll: import_zod4.z.boolean().optional().describe("Replace all occurrences instead of just the first")
786
+ }),
787
+ isReadOnly: false,
788
+ isConcurrencySafe: false,
789
+ execute: async ({ path: filePath, oldString, newString, replaceAll = false }, context) => {
790
+ try {
791
+ const resolved = import_node_path3.default.isAbsolute(filePath) ? filePath : import_node_path3.default.resolve(context.cwd, filePath);
792
+ const content = await import_promises3.default.readFile(resolved, "utf-8");
793
+ let newContent;
794
+ let count = 0;
795
+ if (replaceAll) {
796
+ const occurrences = content.split(oldString).length - 1;
797
+ if (occurrences === 0) {
798
+ try {
799
+ newContent = fuzzyReplace(content, oldString, newString, true);
800
+ count = 1;
801
+ } catch {
802
+ return `Error: oldString not found in ${filePath} (tried 9 fuzzy strategies)`;
803
+ }
804
+ } else {
805
+ newContent = content.split(oldString).join(newString);
806
+ count = occurrences;
807
+ }
808
+ } else {
809
+ try {
810
+ newContent = fuzzyReplace(content, oldString, newString, false);
811
+ count = 1;
812
+ } catch (err) {
813
+ const kind = err.kind;
814
+ if (kind === "ambiguous") {
815
+ return `Error: Multiple matches for oldString in ${filePath}. Provide more surrounding context or set replaceAll to true.`;
816
+ }
817
+ return `Error: oldString not found in ${filePath} (tried 9 fuzzy strategies)`;
818
+ }
819
+ }
820
+ await import_promises3.default.writeFile(resolved, newContent, "utf-8");
821
+ return `Replaced ${count} occurrence(s) in ${filePath}`;
822
+ } catch (err) {
823
+ if (err.code === "ENOENT") {
824
+ return `Error: File not found: ${filePath}`;
825
+ }
826
+ return `Error editing file: ${err instanceof Error ? err.message : String(err)}`;
827
+ }
828
+ }
829
+ });
830
+
831
+ // src/tools/glob.ts
832
+ var import_promises4 = __toESM(require("fs/promises"), 1);
833
+ var import_node_path4 = __toESM(require("path"), 1);
834
+ var import_zod5 = require("zod");
835
+ init_utils();
836
+ var MAX_RESULTS = 200;
837
+ async function walkDir2(dir) {
838
+ const { walkDir: walk } = await Promise.resolve().then(() => (init_utils(), utils_exports));
839
+ const entries = await walk(dir);
840
+ return entries.map((e) => e.path);
841
+ }
842
+ function matchInclude(filePath, includePattern) {
843
+ if (!includePattern) return true;
844
+ const base = import_node_path4.default.basename(filePath);
845
+ const re = globToRegExp(includePattern);
846
+ return re.test(base);
847
+ }
848
+ var GlobTool = defineTool({
849
+ name: "glob",
850
+ description: "Find files matching a glob pattern. Returns matching file paths sorted by modification time.",
851
+ inputSchema: import_zod5.z.object({
852
+ pattern: import_zod5.z.string().describe('Glob pattern (e.g., "**/*.ts", "src/**/*.tsx")'),
853
+ path: import_zod5.z.string().optional().describe("Directory to search in (default: current directory)"),
854
+ include: import_zod5.z.string().optional().describe('File extension or pattern to include (e.g., "*.ts")')
855
+ }),
856
+ isReadOnly: true,
857
+ isConcurrencySafe: true,
858
+ execute: async ({ pattern, path: searchPath, include }, context) => {
859
+ try {
860
+ const searchDir = searchPath ? import_node_path4.default.isAbsolute(searchPath) ? searchPath : import_node_path4.default.resolve(context.cwd, searchPath) : context.cwd;
861
+ const allFiles = await walkDir2(searchDir);
862
+ const re = globToRegExp(pattern);
863
+ const matched = [];
864
+ for (const filePath of allFiles) {
865
+ const relative = import_node_path4.default.relative(searchDir, filePath);
866
+ if (re.test(relative) && matchInclude(relative, include)) {
867
+ try {
868
+ const stat = await import_promises4.default.stat(filePath);
869
+ matched.push({ filePath: relative, mtimeMs: stat.mtimeMs });
870
+ } catch {
871
+ matched.push({ filePath: relative, mtimeMs: 0 });
872
+ }
873
+ }
874
+ }
875
+ matched.sort((a, b) => b.mtimeMs - a.mtimeMs);
876
+ const limited = matched.slice(0, MAX_RESULTS);
877
+ return limited.map((m) => m.filePath).join("\n");
878
+ } catch (err) {
879
+ return `Error searching files: ${err instanceof Error ? err.message : String(err)}`;
880
+ }
881
+ }
882
+ });
883
+
884
+ // src/tools/grep.ts
885
+ var import_promises5 = __toESM(require("fs/promises"), 1);
886
+ var import_node_path5 = __toESM(require("path"), 1);
887
+ var import_zod6 = require("zod");
888
+ init_utils();
889
+ var MAX_MATCHES = 200;
890
+ async function walkDir3(dir) {
891
+ const { walkDir: walk } = await Promise.resolve().then(() => (init_utils(), utils_exports));
892
+ const entries = await walk(dir);
893
+ return entries.map((e) => e.path);
894
+ }
895
+ var GrepTool = defineTool({
896
+ name: "grep",
897
+ description: "Search file contents using a regular expression. Returns matching file paths with line numbers.",
898
+ inputSchema: import_zod6.z.object({
899
+ pattern: import_zod6.z.string().describe("Regular expression to search for"),
900
+ path: import_zod6.z.string().optional().describe("Directory to search in"),
901
+ include: import_zod6.z.string().optional().describe('File pattern to include (e.g., "*.ts")')
902
+ }),
903
+ isReadOnly: true,
904
+ isConcurrencySafe: true,
905
+ execute: async ({ pattern, path: searchPath, include }, context) => {
906
+ try {
907
+ let regex;
908
+ try {
909
+ regex = new RegExp(pattern);
910
+ } catch {
911
+ return `Error: Invalid regular expression: ${pattern}`;
912
+ }
913
+ const searchDir = searchPath ? import_node_path5.default.isAbsolute(searchPath) ? searchPath : import_node_path5.default.resolve(context.cwd, searchPath) : context.cwd;
914
+ const includeRe = include ? globToRegExp(include) : null;
915
+ const allFiles = await walkDir3(searchDir);
916
+ const matches = [];
917
+ for (const filePath of allFiles) {
918
+ if (matches.length >= MAX_MATCHES) break;
919
+ if (includeRe) {
920
+ const base = import_node_path5.default.basename(filePath);
921
+ if (!includeRe.test(base)) continue;
922
+ }
923
+ let content;
924
+ try {
925
+ content = await import_promises5.default.readFile(filePath, "utf-8");
926
+ } catch {
927
+ continue;
928
+ }
929
+ const lines = content.split("\n");
930
+ const relative = import_node_path5.default.relative(searchDir, filePath);
931
+ for (let lineIdx = 0; lineIdx < lines.length; lineIdx++) {
932
+ if (matches.length >= MAX_MATCHES) break;
933
+ const line = lines[lineIdx];
934
+ if (regex.test(line)) {
935
+ matches.push(`${relative}:${lineIdx + 1}: ${line}`);
936
+ regex.lastIndex = 0;
937
+ } else {
938
+ regex.lastIndex = 0;
939
+ }
940
+ }
941
+ }
942
+ if (matches.length === 0) {
943
+ return "No matches found.";
944
+ }
945
+ return matches.join("\n");
946
+ } catch (err) {
947
+ return `Error searching files: ${err instanceof Error ? err.message : String(err)}`;
948
+ }
949
+ }
950
+ });
951
+
952
+ // src/tools/web-fetch.ts
953
+ var import_zod7 = require("zod");
954
+ var MAX_RESPONSE_SIZE = 100 * 1024;
955
+ var WebFetchTool = defineTool({
956
+ name: "web_fetch",
957
+ description: "Fetch content from a URL. Returns the response body as text. Supports HTTP and HTTPS.",
958
+ inputSchema: import_zod7.z.object({
959
+ url: import_zod7.z.string().url().describe("The URL to fetch"),
960
+ method: import_zod7.z.enum(["GET", "POST", "PUT", "DELETE"]).optional().describe("HTTP method (default: GET)"),
961
+ headers: import_zod7.z.record(import_zod7.z.string()).optional().describe("Request headers"),
962
+ body: import_zod7.z.string().optional().describe("Request body (for POST/PUT)")
963
+ }),
964
+ isReadOnly: true,
965
+ isConcurrencySafe: true,
966
+ execute: async ({ url, method = "GET", headers, body }, context) => {
967
+ try {
968
+ if (context.abortSignal?.aborted) {
969
+ return "Request aborted before execution";
970
+ }
971
+ const timeoutSignal = AbortSignal.timeout(3e4);
972
+ let signal;
973
+ if (context.abortSignal) {
974
+ signal = AbortSignal.any([context.abortSignal, timeoutSignal]);
975
+ } else {
976
+ signal = timeoutSignal;
977
+ }
978
+ const fetchOptions = {
979
+ method,
980
+ headers,
981
+ signal,
982
+ redirect: "follow"
983
+ };
984
+ if (body && method !== "GET") {
985
+ fetchOptions.body = body;
986
+ }
987
+ const response = await fetch(url, fetchOptions);
988
+ const contentType = response.headers.get("content-type") ?? "unknown";
989
+ const status = response.status;
990
+ const text = await response.text();
991
+ let result = `Status: ${status}
992
+ Content-Type: ${contentType}
993
+
994
+ `;
995
+ if (text.length > MAX_RESPONSE_SIZE) {
996
+ const half = Math.floor(MAX_RESPONSE_SIZE / 2);
997
+ const notice = `
998
+
999
+ ... [response truncated: showing first ${half} and last ${half} of ${text.length} characters] ...
1000
+
1001
+ `;
1002
+ result += text.slice(0, half) + notice + text.slice(-half);
1003
+ } else {
1004
+ result += text;
1005
+ }
1006
+ return result;
1007
+ } catch (err) {
1008
+ if (err instanceof Error && err.name === "AbortError") {
1009
+ return "Request aborted";
1010
+ }
1011
+ return `Error fetching URL: ${err instanceof Error ? err.message : String(err)}`;
1012
+ }
1013
+ }
1014
+ });
1015
+ // Annotate the CommonJS export names for ESM import in node:
1016
+ 0 && (module.exports = {
1017
+ BashTool,
1018
+ FileEditTool,
1019
+ FileReadTool,
1020
+ FileWriteTool,
1021
+ FuzzyEditError,
1022
+ GlobTool,
1023
+ GrepTool,
1024
+ ToolRegistry,
1025
+ WebFetchTool,
1026
+ defineTool,
1027
+ defineToolFromClass,
1028
+ fuzzyContains,
1029
+ fuzzyReplace,
1030
+ orchestrateTools
1031
+ });
1032
+ //# sourceMappingURL=index.cjs.map