@probelabs/probe 0.6.0-rc254 → 0.6.0-rc255

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 (47) hide show
  1. package/README.md +166 -3
  2. package/bin/binaries/probe-v0.6.0-rc255-aarch64-apple-darwin.tar.gz +0 -0
  3. package/bin/binaries/probe-v0.6.0-rc255-aarch64-unknown-linux-musl.tar.gz +0 -0
  4. package/bin/binaries/probe-v0.6.0-rc255-x86_64-apple-darwin.tar.gz +0 -0
  5. package/bin/binaries/probe-v0.6.0-rc255-x86_64-pc-windows-msvc.zip +0 -0
  6. package/bin/binaries/probe-v0.6.0-rc255-x86_64-unknown-linux-musl.tar.gz +0 -0
  7. package/build/agent/ProbeAgent.d.ts +1 -1
  8. package/build/agent/ProbeAgent.js +24 -16
  9. package/build/agent/acp/tools.js +2 -1
  10. package/build/agent/acp/tools.test.js +2 -1
  11. package/build/agent/index.js +1425 -410
  12. package/build/agent/tools.js +0 -28
  13. package/build/delegate.js +3 -0
  14. package/build/index.js +2 -0
  15. package/build/tools/common.js +6 -5
  16. package/build/tools/edit.js +457 -65
  17. package/build/tools/fileTracker.js +318 -0
  18. package/build/tools/fuzzyMatch.js +271 -0
  19. package/build/tools/hashline.js +131 -0
  20. package/build/tools/lineEditHeuristics.js +138 -0
  21. package/build/tools/symbolEdit.js +119 -0
  22. package/build/tools/vercel.js +40 -9
  23. package/cjs/agent/ProbeAgent.cjs +1528 -514
  24. package/cjs/index.cjs +1556 -540
  25. package/index.d.ts +189 -1
  26. package/package.json +1 -1
  27. package/src/agent/ProbeAgent.d.ts +1 -1
  28. package/src/agent/ProbeAgent.js +24 -16
  29. package/src/agent/acp/tools.js +2 -1
  30. package/src/agent/acp/tools.test.js +2 -1
  31. package/src/agent/index.js +14 -3
  32. package/src/agent/tools.js +0 -28
  33. package/src/delegate.js +3 -0
  34. package/src/index.js +2 -0
  35. package/src/tools/common.js +6 -5
  36. package/src/tools/edit.js +457 -65
  37. package/src/tools/fileTracker.js +318 -0
  38. package/src/tools/fuzzyMatch.js +271 -0
  39. package/src/tools/hashline.js +131 -0
  40. package/src/tools/lineEditHeuristics.js +138 -0
  41. package/src/tools/symbolEdit.js +119 -0
  42. package/src/tools/vercel.js +40 -9
  43. package/bin/binaries/probe-v0.6.0-rc254-aarch64-apple-darwin.tar.gz +0 -0
  44. package/bin/binaries/probe-v0.6.0-rc254-aarch64-unknown-linux-musl.tar.gz +0 -0
  45. package/bin/binaries/probe-v0.6.0-rc254-x86_64-apple-darwin.tar.gz +0 -0
  46. package/bin/binaries/probe-v0.6.0-rc254-x86_64-pc-windows-msvc.zip +0 -0
  47. package/bin/binaries/probe-v0.6.0-rc254-x86_64-unknown-linux-musl.tar.gz +0 -0
@@ -2329,7 +2329,7 @@ var require_headStream = __commonJS({
2329
2329
  if ((0, stream_type_check_1.isReadableStream)(stream2)) {
2330
2330
  return (0, headStream_browser_1.headStream)(stream2, bytes);
2331
2331
  }
2332
- return new Promise((resolve7, reject2) => {
2332
+ return new Promise((resolve8, reject2) => {
2333
2333
  const collector = new Collector();
2334
2334
  collector.limit = bytes;
2335
2335
  stream2.pipe(collector);
@@ -2340,7 +2340,7 @@ var require_headStream = __commonJS({
2340
2340
  collector.on("error", reject2);
2341
2341
  collector.on("finish", function() {
2342
2342
  const bytes2 = new Uint8Array(Buffer.concat(this.buffers));
2343
- resolve7(bytes2);
2343
+ resolve8(bytes2);
2344
2344
  });
2345
2345
  });
2346
2346
  };
@@ -2528,21 +2528,21 @@ var require_dist_cjs15 = __commonJS({
2528
2528
  let sendBody = true;
2529
2529
  if (!externalAgent && expect === "100-continue") {
2530
2530
  sendBody = await Promise.race([
2531
- new Promise((resolve7) => {
2532
- timeoutId = Number(timing.setTimeout(() => resolve7(true), Math.max(MIN_WAIT_TIME, maxContinueTimeoutMs)));
2531
+ new Promise((resolve8) => {
2532
+ timeoutId = Number(timing.setTimeout(() => resolve8(true), Math.max(MIN_WAIT_TIME, maxContinueTimeoutMs)));
2533
2533
  }),
2534
- new Promise((resolve7) => {
2534
+ new Promise((resolve8) => {
2535
2535
  httpRequest.on("continue", () => {
2536
2536
  timing.clearTimeout(timeoutId);
2537
- resolve7(true);
2537
+ resolve8(true);
2538
2538
  });
2539
2539
  httpRequest.on("response", () => {
2540
2540
  timing.clearTimeout(timeoutId);
2541
- resolve7(false);
2541
+ resolve8(false);
2542
2542
  });
2543
2543
  httpRequest.on("error", () => {
2544
2544
  timing.clearTimeout(timeoutId);
2545
- resolve7(false);
2545
+ resolve8(false);
2546
2546
  });
2547
2547
  })
2548
2548
  ]);
@@ -2614,13 +2614,13 @@ or increase socketAcquisitionWarningTimeout=(millis) in the NodeHttpHandler conf
2614
2614
  return socketWarningTimestamp;
2615
2615
  }
2616
2616
  constructor(options) {
2617
- this.configProvider = new Promise((resolve7, reject2) => {
2617
+ this.configProvider = new Promise((resolve8, reject2) => {
2618
2618
  if (typeof options === "function") {
2619
2619
  options().then((_options) => {
2620
- resolve7(this.resolveDefaultConfig(_options));
2620
+ resolve8(this.resolveDefaultConfig(_options));
2621
2621
  }).catch(reject2);
2622
2622
  } else {
2623
- resolve7(this.resolveDefaultConfig(options));
2623
+ resolve8(this.resolveDefaultConfig(options));
2624
2624
  }
2625
2625
  });
2626
2626
  }
@@ -2663,7 +2663,7 @@ or increase socketAcquisitionWarningTimeout=(millis) in the NodeHttpHandler conf
2663
2663
  const config = this.config;
2664
2664
  let writeRequestBodyPromise = void 0;
2665
2665
  const timeouts = [];
2666
- const resolve7 = async (arg) => {
2666
+ const resolve8 = async (arg) => {
2667
2667
  await writeRequestBodyPromise;
2668
2668
  timeouts.forEach(timing.clearTimeout);
2669
2669
  _resolve(arg);
@@ -2729,7 +2729,7 @@ or increase socketAcquisitionWarningTimeout=(millis) in the NodeHttpHandler conf
2729
2729
  headers: getTransformedHeaders(res.headers),
2730
2730
  body: res
2731
2731
  });
2732
- resolve7({ response: httpResponse });
2732
+ resolve8({ response: httpResponse });
2733
2733
  });
2734
2734
  req.on("error", (err) => {
2735
2735
  if (NODEJS_TIMEOUT_ERROR_CODES.includes(err.code)) {
@@ -2909,13 +2909,13 @@ or increase socketAcquisitionWarningTimeout=(millis) in the NodeHttpHandler conf
2909
2909
  return new _NodeHttp2Handler(instanceOrOptions);
2910
2910
  }
2911
2911
  constructor(options) {
2912
- this.configProvider = new Promise((resolve7, reject2) => {
2912
+ this.configProvider = new Promise((resolve8, reject2) => {
2913
2913
  if (typeof options === "function") {
2914
2914
  options().then((opts) => {
2915
- resolve7(opts || {});
2915
+ resolve8(opts || {});
2916
2916
  }).catch(reject2);
2917
2917
  } else {
2918
- resolve7(options || {});
2918
+ resolve8(options || {});
2919
2919
  }
2920
2920
  });
2921
2921
  }
@@ -2935,7 +2935,7 @@ or increase socketAcquisitionWarningTimeout=(millis) in the NodeHttpHandler conf
2935
2935
  return new Promise((_resolve, _reject) => {
2936
2936
  let fulfilled = false;
2937
2937
  let writeRequestBodyPromise = void 0;
2938
- const resolve7 = async (arg) => {
2938
+ const resolve8 = async (arg) => {
2939
2939
  await writeRequestBodyPromise;
2940
2940
  _resolve(arg);
2941
2941
  };
@@ -2991,7 +2991,7 @@ or increase socketAcquisitionWarningTimeout=(millis) in the NodeHttpHandler conf
2991
2991
  body: req
2992
2992
  });
2993
2993
  fulfilled = true;
2994
- resolve7({ response: httpResponse });
2994
+ resolve8({ response: httpResponse });
2995
2995
  if (disableConcurrentStreams) {
2996
2996
  session.close();
2997
2997
  this.connectionManager.deleteSession(authority, session);
@@ -3068,7 +3068,7 @@ or increase socketAcquisitionWarningTimeout=(millis) in the NodeHttpHandler conf
3068
3068
  if (isReadableStreamInstance(stream3)) {
3069
3069
  return collectReadableStream(stream3);
3070
3070
  }
3071
- return new Promise((resolve7, reject2) => {
3071
+ return new Promise((resolve8, reject2) => {
3072
3072
  const collector = new Collector();
3073
3073
  stream3.pipe(collector);
3074
3074
  stream3.on("error", (err) => {
@@ -3078,7 +3078,7 @@ or increase socketAcquisitionWarningTimeout=(millis) in the NodeHttpHandler conf
3078
3078
  collector.on("error", reject2);
3079
3079
  collector.on("finish", function() {
3080
3080
  const bytes = new Uint8Array(Buffer.concat(this.bufferedBytes));
3081
- resolve7(bytes);
3081
+ resolve8(bytes);
3082
3082
  });
3083
3083
  });
3084
3084
  };
@@ -3122,7 +3122,7 @@ var require_dist_cjs16 = __commonJS({
3122
3122
  return new Request(url, requestOptions);
3123
3123
  }
3124
3124
  function requestTimeout(timeoutInMs = 0) {
3125
- return new Promise((resolve7, reject2) => {
3125
+ return new Promise((resolve8, reject2) => {
3126
3126
  if (timeoutInMs) {
3127
3127
  setTimeout(() => {
3128
3128
  const timeoutError = new Error(`Request did not complete within ${timeoutInMs} ms`);
@@ -3240,7 +3240,7 @@ var require_dist_cjs16 = __commonJS({
3240
3240
  requestTimeout(requestTimeoutInMs)
3241
3241
  ];
3242
3242
  if (abortSignal) {
3243
- raceOfPromises.push(new Promise((resolve7, reject2) => {
3243
+ raceOfPromises.push(new Promise((resolve8, reject2) => {
3244
3244
  const onAbort = () => {
3245
3245
  const abortError = new Error("Request aborted");
3246
3246
  abortError.name = "AbortError";
@@ -3304,7 +3304,7 @@ var require_dist_cjs16 = __commonJS({
3304
3304
  return collected;
3305
3305
  }
3306
3306
  function readToBase64(blob) {
3307
- return new Promise((resolve7, reject2) => {
3307
+ return new Promise((resolve8, reject2) => {
3308
3308
  const reader = new FileReader();
3309
3309
  reader.onloadend = () => {
3310
3310
  if (reader.readyState !== 2) {
@@ -3313,7 +3313,7 @@ var require_dist_cjs16 = __commonJS({
3313
3313
  const result = reader.result ?? "";
3314
3314
  const commaIndex = result.indexOf(",");
3315
3315
  const dataOffset = commaIndex > -1 ? commaIndex + 1 : result.length;
3316
- resolve7(result.substring(dataOffset));
3316
+ resolve8(result.substring(dataOffset));
3317
3317
  };
3318
3318
  reader.onabort = () => reject2(new Error("Read aborted"));
3319
3319
  reader.onerror = () => reject2(reader.error);
@@ -4981,11 +4981,11 @@ function __metadata(metadataKey, metadataValue) {
4981
4981
  }
4982
4982
  function __awaiter(thisArg, _arguments, P, generator) {
4983
4983
  function adopt(value) {
4984
- return value instanceof P ? value : new P(function(resolve7) {
4985
- resolve7(value);
4984
+ return value instanceof P ? value : new P(function(resolve8) {
4985
+ resolve8(value);
4986
4986
  });
4987
4987
  }
4988
- return new (P || (P = Promise))(function(resolve7, reject2) {
4988
+ return new (P || (P = Promise))(function(resolve8, reject2) {
4989
4989
  function fulfilled(value) {
4990
4990
  try {
4991
4991
  step(generator.next(value));
@@ -5001,7 +5001,7 @@ function __awaiter(thisArg, _arguments, P, generator) {
5001
5001
  }
5002
5002
  }
5003
5003
  function step(result) {
5004
- result.done ? resolve7(result.value) : adopt(result.value).then(fulfilled, rejected);
5004
+ result.done ? resolve8(result.value) : adopt(result.value).then(fulfilled, rejected);
5005
5005
  }
5006
5006
  step((generator = generator.apply(thisArg, _arguments || [])).next());
5007
5007
  });
@@ -5192,14 +5192,14 @@ function __asyncValues(o5) {
5192
5192
  }, i5);
5193
5193
  function verb(n5) {
5194
5194
  i5[n5] = o5[n5] && function(v5) {
5195
- return new Promise(function(resolve7, reject2) {
5196
- v5 = o5[n5](v5), settle(resolve7, reject2, v5.done, v5.value);
5195
+ return new Promise(function(resolve8, reject2) {
5196
+ v5 = o5[n5](v5), settle(resolve8, reject2, v5.done, v5.value);
5197
5197
  });
5198
5198
  };
5199
5199
  }
5200
- function settle(resolve7, reject2, d5, v5) {
5200
+ function settle(resolve8, reject2, d5, v5) {
5201
5201
  Promise.resolve(v5).then(function(v6) {
5202
- resolve7({ value: v6, done: d5 });
5202
+ resolve8({ value: v6, done: d5 });
5203
5203
  }, reject2);
5204
5204
  }
5205
5205
  }
@@ -15600,7 +15600,7 @@ var require_dist_cjs37 = __commonJS({
15600
15600
  this.sockets[url] = (this.sockets[url] ?? []).filter((socket) => ![WebSocket.CLOSING, WebSocket.CLOSED].includes(socket.readyState));
15601
15601
  }
15602
15602
  waitForReady(socket, connectionTimeout) {
15603
- return new Promise((resolve7, reject2) => {
15603
+ return new Promise((resolve8, reject2) => {
15604
15604
  const timeout = setTimeout(() => {
15605
15605
  this.removeNotUsableSockets(socket.url);
15606
15606
  reject2({
@@ -15612,7 +15612,7 @@ var require_dist_cjs37 = __commonJS({
15612
15612
  }, connectionTimeout);
15613
15613
  socket.onopen = () => {
15614
15614
  clearTimeout(timeout);
15615
- resolve7();
15615
+ resolve8();
15616
15616
  };
15617
15617
  });
15618
15618
  }
@@ -15665,8 +15665,8 @@ var require_dist_cjs37 = __commonJS({
15665
15665
  }
15666
15666
  return { done: item.done, value: item.value };
15667
15667
  }
15668
- return new Promise((resolve7, reject2) => {
15669
- pendingResolve = resolve7;
15668
+ return new Promise((resolve8, reject2) => {
15669
+ pendingResolve = resolve8;
15670
15670
  pendingReject = reject2;
15671
15671
  });
15672
15672
  }
@@ -16879,7 +16879,7 @@ var require_dist_cjs46 = __commonJS({
16879
16879
  this.refillTokenBucket();
16880
16880
  if (amount > this.currentCapacity) {
16881
16881
  const delay = (amount - this.currentCapacity) / this.fillRate * 1e3;
16882
- await new Promise((resolve7) => _DefaultRateLimiter.setTimeoutFn(resolve7, delay));
16882
+ await new Promise((resolve8) => _DefaultRateLimiter.setTimeoutFn(resolve8, delay));
16883
16883
  }
16884
16884
  this.currentCapacity = this.currentCapacity - amount;
16885
16885
  }
@@ -17214,7 +17214,7 @@ var require_dist_cjs47 = __commonJS({
17214
17214
  const delayFromResponse = getDelayFromRetryAfterHeader(err.$response);
17215
17215
  const delay = Math.max(delayFromResponse || 0, delayFromDecider);
17216
17216
  totalDelay += delay;
17217
- await new Promise((resolve7) => setTimeout(resolve7, delay));
17217
+ await new Promise((resolve8) => setTimeout(resolve8, delay));
17218
17218
  continue;
17219
17219
  }
17220
17220
  if (!err.$metadata) {
@@ -17372,7 +17372,7 @@ var require_dist_cjs47 = __commonJS({
17372
17372
  attempts = retryToken.getRetryCount();
17373
17373
  const delay = retryToken.getRetryDelay();
17374
17374
  totalRetryDelay += delay;
17375
- await new Promise((resolve7) => setTimeout(resolve7, delay));
17375
+ await new Promise((resolve8) => setTimeout(resolve8, delay));
17376
17376
  }
17377
17377
  }
17378
17378
  } else {
@@ -17524,7 +17524,7 @@ var require_package2 = __commonJS({
17524
17524
  module2.exports = {
17525
17525
  name: "@aws-sdk/client-bedrock-runtime",
17526
17526
  description: "AWS SDK for JavaScript Bedrock Runtime Client for Node.js, Browser and React Native",
17527
- version: "3.994.0",
17527
+ version: "3.995.0",
17528
17528
  scripts: {
17529
17529
  build: "concurrently 'yarn:build:types' 'yarn:build:es' && yarn build:cjs",
17530
17530
  "build:cjs": "node ../../scripts/compilation/inline client-bedrock-runtime",
@@ -17554,11 +17554,11 @@ var require_package2 = __commonJS({
17554
17554
  "@aws-sdk/middleware-user-agent": "^3.972.11",
17555
17555
  "@aws-sdk/middleware-websocket": "^3.972.6",
17556
17556
  "@aws-sdk/region-config-resolver": "^3.972.3",
17557
- "@aws-sdk/token-providers": "3.994.0",
17557
+ "@aws-sdk/token-providers": "3.995.0",
17558
17558
  "@aws-sdk/types": "^3.973.1",
17559
- "@aws-sdk/util-endpoints": "3.994.0",
17559
+ "@aws-sdk/util-endpoints": "3.995.0",
17560
17560
  "@aws-sdk/util-user-agent-browser": "^3.972.3",
17561
- "@aws-sdk/util-user-agent-node": "^3.972.9",
17561
+ "@aws-sdk/util-user-agent-node": "^3.972.10",
17562
17562
  "@smithy/config-resolver": "^4.4.6",
17563
17563
  "@smithy/core": "^3.23.2",
17564
17564
  "@smithy/eventstream-serde-browser": "^4.2.8",
@@ -17687,7 +17687,7 @@ var require_dist_cjs49 = __commonJS({
17687
17687
  var nodeConfigProvider = require_dist_cjs43();
17688
17688
  var urlParser = require_dist_cjs22();
17689
17689
  function httpRequest(options) {
17690
- return new Promise((resolve7, reject2) => {
17690
+ return new Promise((resolve8, reject2) => {
17691
17691
  const req = http.request({
17692
17692
  method: "GET",
17693
17693
  ...options,
@@ -17712,7 +17712,7 @@ var require_dist_cjs49 = __commonJS({
17712
17712
  chunks.push(chunk);
17713
17713
  });
17714
17714
  res.on("end", () => {
17715
- resolve7(buffer.Buffer.concat(chunks));
17715
+ resolve8(buffer.Buffer.concat(chunks));
17716
17716
  req.destroy();
17717
17717
  });
17718
17718
  });
@@ -18132,7 +18132,7 @@ var require_retry_wrapper = __commonJS({
18132
18132
  try {
18133
18133
  return await toRetry();
18134
18134
  } catch (e5) {
18135
- await new Promise((resolve7) => setTimeout(resolve7, delayMs));
18135
+ await new Promise((resolve8) => setTimeout(resolve8, delayMs));
18136
18136
  }
18137
18137
  }
18138
18138
  return await toRetry();
@@ -18440,6 +18440,15 @@ var require_dist_cjs51 = __commonJS({
18440
18440
  var os4 = require("os");
18441
18441
  var process2 = require("process");
18442
18442
  var middlewareUserAgent = require_dist_cjs29();
18443
+ var getRuntimeUserAgentPair = () => {
18444
+ const runtimesToCheck = ["deno", "bun", "llrt"];
18445
+ for (const runtime of runtimesToCheck) {
18446
+ if (process2.versions[runtime]) {
18447
+ return [`md/${runtime}`, process2.versions[runtime]];
18448
+ }
18449
+ }
18450
+ return ["md/nodejs", process2.versions.node];
18451
+ };
18443
18452
  var crtAvailability = {
18444
18453
  isCrtAvailable: false
18445
18454
  };
@@ -18450,13 +18459,14 @@ var require_dist_cjs51 = __commonJS({
18450
18459
  return null;
18451
18460
  };
18452
18461
  var createDefaultUserAgentProvider5 = ({ serviceId, clientVersion }) => {
18462
+ const runtimeUserAgentPair = getRuntimeUserAgentPair();
18453
18463
  return async (config) => {
18454
18464
  const sections = [
18455
18465
  ["aws-sdk-js", clientVersion],
18456
18466
  ["ua", "2.1"],
18457
18467
  [`os/${os4.platform()}`, os4.release()],
18458
18468
  ["lang/js"],
18459
- ["md/nodejs", `${process2.versions.node}`]
18469
+ runtimeUserAgentPair
18460
18470
  ];
18461
18471
  const crtAvailable = isCrtAvailable();
18462
18472
  if (crtAvailable) {
@@ -24019,8 +24029,8 @@ var require_dist_cjs66 = __commonJS({
24019
24029
  systemClockOffsetProvider: this.systemClockOffsetProvider
24020
24030
  });
24021
24031
  let resolvePipeline;
24022
- const pipelineError = new Promise((resolve7, reject2) => {
24023
- resolvePipeline = () => resolve7(void 0);
24032
+ const pipelineError = new Promise((resolve8, reject2) => {
24033
+ resolvePipeline = () => resolve8(void 0);
24024
24034
  node_stream.pipeline(payloadStream, signingStream, request.body, (err) => {
24025
24035
  if (err) {
24026
24036
  reject2(new Error(`Pipeline error in @aws-sdk/eventstream-handler-node: ${err.message}`, { cause: err }));
@@ -24126,7 +24136,7 @@ var init_package2 = __esm({
24126
24136
  "node_modules/@aws-sdk/token-providers/node_modules/@aws-sdk/nested-clients/package.json"() {
24127
24137
  package_default2 = {
24128
24138
  name: "@aws-sdk/nested-clients",
24129
- version: "3.994.0",
24139
+ version: "3.995.0",
24130
24140
  description: "Nested clients for AWS SDK packages.",
24131
24141
  main: "./dist-cjs/index.js",
24132
24142
  module: "./dist-es/index.js",
@@ -24162,9 +24172,9 @@ var init_package2 = __esm({
24162
24172
  "@aws-sdk/middleware-user-agent": "^3.972.11",
24163
24173
  "@aws-sdk/region-config-resolver": "^3.972.3",
24164
24174
  "@aws-sdk/types": "^3.973.1",
24165
- "@aws-sdk/util-endpoints": "3.994.0",
24175
+ "@aws-sdk/util-endpoints": "3.995.0",
24166
24176
  "@aws-sdk/util-user-agent-browser": "^3.972.3",
24167
- "@aws-sdk/util-user-agent-node": "^3.972.9",
24177
+ "@aws-sdk/util-user-agent-node": "^3.972.10",
24168
24178
  "@smithy/config-resolver": "^4.4.6",
24169
24179
  "@smithy/core": "^3.23.2",
24170
24180
  "@smithy/fetch-http-handler": "^5.3.9",
@@ -25574,7 +25584,7 @@ var require_dist_cjs69 = __commonJS({
25574
25584
  streamEnded = true;
25575
25585
  });
25576
25586
  while (!generationEnded) {
25577
- const value = await new Promise((resolve7) => setTimeout(() => resolve7(records.shift()), 0));
25587
+ const value = await new Promise((resolve8) => setTimeout(() => resolve8(records.shift()), 0));
25578
25588
  if (value) {
25579
25589
  yield value;
25580
25590
  }
@@ -31837,7 +31847,7 @@ async function waitForFileLock(lockPath, binaryPath) {
31837
31847
  }
31838
31848
  } catch {
31839
31849
  }
31840
- await new Promise((resolve7) => setTimeout(resolve7, LOCK_POLL_INTERVAL_MS));
31850
+ await new Promise((resolve8) => setTimeout(resolve8, LOCK_POLL_INTERVAL_MS));
31841
31851
  }
31842
31852
  if (process.env.DEBUG === "1" || process.env.VERBOSE === "1") {
31843
31853
  console.log(`Timeout waiting for file lock`);
@@ -33186,7 +33196,7 @@ Cwd: ${cwd}`;
33186
33196
  }
33187
33197
  }
33188
33198
  function extractWithStdin(binaryPath, cliArgs, content, options, cwd) {
33189
- return new Promise((resolve7, reject2) => {
33199
+ return new Promise((resolve8, reject2) => {
33190
33200
  const childProcess = (0, import_child_process4.spawn)(binaryPath, ["extract", ...cliArgs], {
33191
33201
  stdio: ["pipe", "pipe", "pipe"],
33192
33202
  cwd
@@ -33209,7 +33219,7 @@ function extractWithStdin(binaryPath, cliArgs, content, options, cwd) {
33209
33219
  }
33210
33220
  try {
33211
33221
  const result = processExtractOutput(stdout, options);
33212
- resolve7(result);
33222
+ resolve8(result);
33213
33223
  } catch (error2) {
33214
33224
  reject2(error2);
33215
33225
  }
@@ -33318,6 +33328,7 @@ async function delegate({
33318
33328
  model = null,
33319
33329
  enableBash = false,
33320
33330
  bashConfig = null,
33331
+ allowEdit = false,
33321
33332
  architectureFileName = null,
33322
33333
  promptType = "code-researcher",
33323
33334
  allowedTools = null,
@@ -33397,6 +33408,8 @@ async function delegate({
33397
33408
  // Inherit from parent
33398
33409
  bashConfig,
33399
33410
  // Inherit from parent
33411
+ allowEdit,
33412
+ // Inherit from parent
33400
33413
  architectureFileName,
33401
33414
  allowedTools,
33402
33415
  disableTools,
@@ -33582,7 +33595,7 @@ var init_delegate = __esm({
33582
33595
  if (debug) {
33583
33596
  console.error(`[DelegationManager] Slot unavailable (${this.globalActive}/${this.maxConcurrent}), queuing... (queue size: ${this.waitQueue.length}, timeout: ${effectiveTimeout}ms)`);
33584
33597
  }
33585
- return new Promise((resolve7, reject2) => {
33598
+ return new Promise((resolve8, reject2) => {
33586
33599
  const entry = {
33587
33600
  resolve: null,
33588
33601
  // Will be wrapped below
@@ -33598,7 +33611,7 @@ var init_delegate = __esm({
33598
33611
  if (settled) return;
33599
33612
  settled = true;
33600
33613
  if (entry.timeoutId) clearTimeout(entry.timeoutId);
33601
- resolve7(value);
33614
+ resolve8(value);
33602
33615
  };
33603
33616
  entry.reject = (error2) => {
33604
33617
  if (settled) return;
@@ -33648,7 +33661,7 @@ var init_delegate = __esm({
33648
33661
  while (this.waitQueue.length > 0 && this.globalActive < this.maxConcurrent) {
33649
33662
  const next = this.waitQueue.shift();
33650
33663
  if (!next) break;
33651
- const { resolve: resolve7, reject: reject2, parentSessionId, queuedAt } = next;
33664
+ const { resolve: resolve8, reject: reject2, parentSessionId, queuedAt } = next;
33652
33665
  if (parentSessionId) {
33653
33666
  const sessionData = this.sessionDelegations.get(parentSessionId);
33654
33667
  const sessionCount = sessionData?.count || 0;
@@ -33665,12 +33678,12 @@ var init_delegate = __esm({
33665
33678
  const waitTime = Date.now() - queuedAt;
33666
33679
  console.error(`[DelegationManager] Granted slot from queue (waited ${waitTime}ms). Active: ${this.globalActive}/${this.maxConcurrent}`);
33667
33680
  }
33668
- toResolve.push(resolve7);
33681
+ toResolve.push(resolve8);
33669
33682
  }
33670
33683
  if (toResolve.length > 0 || toReject.length > 0) {
33671
33684
  setImmediate(() => {
33672
- for (const resolve7 of toResolve) {
33673
- resolve7(true);
33685
+ for (const resolve8 of toResolve) {
33686
+ resolve8(true);
33674
33687
  }
33675
33688
  for (const { reject: reject2, error: error2 } of toReject) {
33676
33689
  reject2(error2);
@@ -38305,6 +38318,400 @@ var init_zod = __esm({
38305
38318
  }
38306
38319
  });
38307
38320
 
38321
+ // src/tools/fuzzyMatch.js
38322
+ function findFuzzyMatch(content, searchString) {
38323
+ if (!searchString || searchString.trim().length === 0) {
38324
+ return null;
38325
+ }
38326
+ const normalizedContent = content.replace(/\r\n/g, "\n");
38327
+ const normalizedSearch = searchString.replace(/\r\n/g, "\n");
38328
+ const contentLines = normalizedContent.split("\n");
38329
+ const searchLines = normalizedSearch.split("\n");
38330
+ const trimmed = lineTrimmedMatch(contentLines, searchLines);
38331
+ if (trimmed) return { ...trimmed, strategy: "line-trimmed" };
38332
+ const normalized = whitespaceNormalizedMatch(normalizedContent, normalizedSearch);
38333
+ if (normalized) return { ...normalized, strategy: "whitespace-normalized" };
38334
+ const indentFlex = indentFlexibleMatch(contentLines, searchLines);
38335
+ if (indentFlex) return { ...indentFlex, strategy: "indent-flexible" };
38336
+ return null;
38337
+ }
38338
+ function lineTrimmedMatch(contentLines, searchLines) {
38339
+ if (searchLines.length === 0) return null;
38340
+ const trimmedSearchLines = searchLines.map((line) => line.trim());
38341
+ if (trimmedSearchLines.every((line) => line === "")) return null;
38342
+ const windowSize = searchLines.length;
38343
+ const matches = [];
38344
+ for (let i5 = 0; i5 <= contentLines.length - windowSize; i5++) {
38345
+ let allMatch = true;
38346
+ for (let j5 = 0; j5 < windowSize; j5++) {
38347
+ if (contentLines[i5 + j5].trim() !== trimmedSearchLines[j5]) {
38348
+ allMatch = false;
38349
+ break;
38350
+ }
38351
+ }
38352
+ if (allMatch) {
38353
+ const matchedText = contentLines.slice(i5, i5 + windowSize).join("\n");
38354
+ matches.push(matchedText);
38355
+ }
38356
+ }
38357
+ if (matches.length === 0) return null;
38358
+ return {
38359
+ matchedText: matches[0],
38360
+ count: matches.length
38361
+ };
38362
+ }
38363
+ function whitespaceNormalizedMatch(content, search2) {
38364
+ if (!search2 || search2.trim().length === 0) return null;
38365
+ const { normalized: normContent, indexMap: contentMap } = buildNormalizedMap(content);
38366
+ const { normalized: normSearch } = buildNormalizedMap(search2);
38367
+ if (normSearch.length === 0) return null;
38368
+ const matches = [];
38369
+ let searchStart = 0;
38370
+ while (searchStart <= normContent.length - normSearch.length) {
38371
+ const idx = normContent.indexOf(normSearch, searchStart);
38372
+ if (idx === -1) break;
38373
+ const originalStart = contentMap[idx];
38374
+ const originalEnd = contentMap[idx + normSearch.length - 1];
38375
+ let actualEnd = originalEnd + 1;
38376
+ while (actualEnd < content.length && /[ \t]/.test(content[actualEnd]) && (actualEnd === originalEnd + 1 || /[ \t]/.test(content[actualEnd - 1]))) {
38377
+ if (contentMap.indexOf(actualEnd) > idx + normSearch.length - 1 || contentMap.indexOf(actualEnd) === -1) {
38378
+ break;
38379
+ }
38380
+ actualEnd++;
38381
+ }
38382
+ const matchedText = content.substring(originalStart, actualEnd);
38383
+ matches.push(matchedText);
38384
+ searchStart = idx + 1;
38385
+ }
38386
+ if (matches.length === 0) return null;
38387
+ return {
38388
+ matchedText: matches[0],
38389
+ count: matches.length
38390
+ };
38391
+ }
38392
+ function buildNormalizedMap(str) {
38393
+ const normalized = [];
38394
+ const indexMap = [];
38395
+ let i5 = 0;
38396
+ while (i5 < str.length) {
38397
+ const ch = str[i5];
38398
+ if (ch === " " || ch === " ") {
38399
+ normalized.push(" ");
38400
+ indexMap.push(i5);
38401
+ while (i5 < str.length && (str[i5] === " " || str[i5] === " ")) {
38402
+ i5++;
38403
+ }
38404
+ } else {
38405
+ normalized.push(ch);
38406
+ indexMap.push(i5);
38407
+ i5++;
38408
+ }
38409
+ }
38410
+ return {
38411
+ normalized: normalized.join(""),
38412
+ indexMap
38413
+ };
38414
+ }
38415
+ function indentFlexibleMatch(contentLines, searchLines) {
38416
+ if (searchLines.length === 0) return null;
38417
+ if (searchLines.every((line) => line.trim() === "")) return null;
38418
+ const searchMinIndent = getMinIndent(searchLines);
38419
+ const strippedSearch = searchLines.map((line) => stripIndent(line, searchMinIndent));
38420
+ const windowSize = searchLines.length;
38421
+ const matches = [];
38422
+ for (let i5 = 0; i5 <= contentLines.length - windowSize; i5++) {
38423
+ const windowLines = contentLines.slice(i5, i5 + windowSize);
38424
+ const windowMinIndent = getMinIndent(windowLines);
38425
+ const strippedWindow = windowLines.map((line) => stripIndent(line, windowMinIndent));
38426
+ let allMatch = true;
38427
+ for (let j5 = 0; j5 < windowSize; j5++) {
38428
+ if (strippedWindow[j5] !== strippedSearch[j5]) {
38429
+ allMatch = false;
38430
+ break;
38431
+ }
38432
+ }
38433
+ if (allMatch) {
38434
+ const matchedText = windowLines.join("\n");
38435
+ matches.push(matchedText);
38436
+ }
38437
+ }
38438
+ if (matches.length === 0) return null;
38439
+ return {
38440
+ matchedText: matches[0],
38441
+ count: matches.length
38442
+ };
38443
+ }
38444
+ function getMinIndent(lines) {
38445
+ let min = Infinity;
38446
+ for (const line of lines) {
38447
+ if (line.trim() === "") continue;
38448
+ const match2 = line.match(/^([ \t]*)/);
38449
+ if (match2) {
38450
+ min = Math.min(min, match2[1].length);
38451
+ }
38452
+ }
38453
+ return min === Infinity ? 0 : min;
38454
+ }
38455
+ function stripIndent(line, amount) {
38456
+ if (line.trim() === "") return "";
38457
+ if (amount <= 0) return line;
38458
+ return line.substring(Math.min(amount, line.length));
38459
+ }
38460
+ var init_fuzzyMatch = __esm({
38461
+ "src/tools/fuzzyMatch.js"() {
38462
+ "use strict";
38463
+ }
38464
+ });
38465
+
38466
+ // src/tools/symbolEdit.js
38467
+ async function findSymbol(filePath, symbolName, cwd) {
38468
+ try {
38469
+ const result = await extract({
38470
+ files: [`${filePath}#${symbolName}`],
38471
+ format: "json",
38472
+ json: true,
38473
+ cwd
38474
+ });
38475
+ if (!result || !result.results || result.results.length === 0) {
38476
+ return null;
38477
+ }
38478
+ const match2 = result.results[0];
38479
+ return {
38480
+ startLine: match2.lines[0],
38481
+ // 1-indexed
38482
+ endLine: match2.lines[1],
38483
+ // 1-indexed
38484
+ code: match2.code,
38485
+ nodeType: match2.node_type,
38486
+ file: match2.file
38487
+ };
38488
+ } catch (error2) {
38489
+ if (process.env.DEBUG === "1") {
38490
+ console.error(`[SymbolEdit] findSymbol error for "${symbolName}" in ${filePath}: ${error2.message}`);
38491
+ }
38492
+ return null;
38493
+ }
38494
+ }
38495
+ async function findAllSymbols(filePath, symbolName, cwd) {
38496
+ try {
38497
+ const result = await extract({
38498
+ files: [`${filePath}#${symbolName}`],
38499
+ format: "json",
38500
+ json: true,
38501
+ cwd
38502
+ });
38503
+ if (!result || !result.results || result.results.length === 0) {
38504
+ return [];
38505
+ }
38506
+ return result.results.map((match2) => ({
38507
+ startLine: match2.lines[0],
38508
+ endLine: match2.lines[1],
38509
+ code: match2.code,
38510
+ nodeType: match2.node_type,
38511
+ file: match2.file,
38512
+ qualifiedName: match2.symbol_signature || symbolName
38513
+ }));
38514
+ } catch (error2) {
38515
+ if (process.env.DEBUG === "1") {
38516
+ console.error(`[SymbolEdit] findAllSymbols error for "${symbolName}" in ${filePath}: ${error2.message}`);
38517
+ }
38518
+ return [];
38519
+ }
38520
+ }
38521
+ function detectBaseIndent(code) {
38522
+ const lines = code.split("\n");
38523
+ for (const line of lines) {
38524
+ if (line.trim().length > 0) {
38525
+ const match2 = line.match(/^(\s*)/);
38526
+ return match2 ? match2[1] : "";
38527
+ }
38528
+ }
38529
+ return "";
38530
+ }
38531
+ function reindent(newContent, targetIndent) {
38532
+ const lines = newContent.split("\n");
38533
+ const sourceIndent = detectBaseIndent(newContent);
38534
+ return lines.map((line) => {
38535
+ if (line.trim().length === 0) {
38536
+ return "";
38537
+ }
38538
+ if (line.startsWith(sourceIndent)) {
38539
+ return targetIndent + line.slice(sourceIndent.length);
38540
+ }
38541
+ return line;
38542
+ }).join("\n");
38543
+ }
38544
+ var init_symbolEdit = __esm({
38545
+ "src/tools/symbolEdit.js"() {
38546
+ "use strict";
38547
+ init_extract();
38548
+ }
38549
+ });
38550
+
38551
+ // src/tools/hashline.js
38552
+ function computeLineHash(line) {
38553
+ const stripped = (line || "").replace(/\s+/g, "");
38554
+ let h5 = 5381;
38555
+ for (let i5 = 0; i5 < stripped.length; i5++) {
38556
+ h5 = (h5 << 5) + h5 + stripped.charCodeAt(i5) & 4294967295;
38557
+ }
38558
+ return ((h5 >>> 0) % 256).toString(16).padStart(2, "0");
38559
+ }
38560
+ function parseLineRef(ref2) {
38561
+ if (ref2 === void 0 || ref2 === null) return null;
38562
+ const str = String(ref2).trim();
38563
+ if (!str) return null;
38564
+ const hashMatch = str.match(/^(\d+):([0-9a-fA-F]{2})$/);
38565
+ if (hashMatch) {
38566
+ const line = parseInt(hashMatch[1], 10);
38567
+ if (line < 1 || !isFinite(line)) return null;
38568
+ return { line, hash: hashMatch[2].toLowerCase() };
38569
+ }
38570
+ const lineMatch = str.match(/^(\d+)$/);
38571
+ if (lineMatch) {
38572
+ const line = parseInt(lineMatch[1], 10);
38573
+ if (line < 1 || !isFinite(line)) return null;
38574
+ return { line, hash: null };
38575
+ }
38576
+ return null;
38577
+ }
38578
+ function validateLineHash(lineNum, hash, fileLines) {
38579
+ const idx = lineNum - 1;
38580
+ if (idx < 0 || idx >= fileLines.length) {
38581
+ return { valid: false, actualHash: "", actualContent: "" };
38582
+ }
38583
+ const actualContent = fileLines[idx];
38584
+ const actualHash = computeLineHash(actualContent);
38585
+ return {
38586
+ valid: actualHash === hash.toLowerCase(),
38587
+ actualHash,
38588
+ actualContent
38589
+ };
38590
+ }
38591
+ function annotateOutputWithHashes(output) {
38592
+ if (!output || typeof output !== "string") return output;
38593
+ return output.split("\n").map((line) => {
38594
+ const cleanLine = line.endsWith("\r") ? line.slice(0, -1) : line;
38595
+ const match2 = cleanLine.match(/^(\s*)(\d+)(\s*\|)(.*)$/);
38596
+ if (!match2) return line;
38597
+ const [, prefix, lineNum, pipeSection, content] = match2;
38598
+ const hash = computeLineHash(content);
38599
+ const cr = line.endsWith("\r") ? "\r" : "";
38600
+ return `${prefix}${lineNum}:${hash}${pipeSection}${content}${cr}`;
38601
+ }).join("\n");
38602
+ }
38603
+ function stripHashlinePrefixes(text) {
38604
+ if (!text || typeof text !== "string") return { cleaned: text || "", stripped: false };
38605
+ const lines = text.split("\n");
38606
+ if (lines.length === 0) return { cleaned: "", stripped: false };
38607
+ const nonEmptyLines = lines.filter((l5) => l5.trim().length > 0);
38608
+ if (nonEmptyLines.length === 0) return { cleaned: text, stripped: false };
38609
+ const prefixPattern = /^\s*\d+(?::[0-9a-fA-F]{2})?\s*\|\s?/;
38610
+ const matchCount = nonEmptyLines.filter((l5) => prefixPattern.test(l5)).length;
38611
+ if (matchCount / nonEmptyLines.length <= 0.5) {
38612
+ return { cleaned: text, stripped: false };
38613
+ }
38614
+ const cleaned = lines.map((line) => {
38615
+ if (line.trim().length === 0) return line;
38616
+ return line.replace(prefixPattern, "");
38617
+ }).join("\n");
38618
+ return { cleaned, stripped: true };
38619
+ }
38620
+ var init_hashline = __esm({
38621
+ "src/tools/hashline.js"() {
38622
+ "use strict";
38623
+ }
38624
+ });
38625
+
38626
+ // src/tools/lineEditHeuristics.js
38627
+ function stripEchoedBoundaries(newStr, fileLines, startLine, endLine, position) {
38628
+ const modifications = [];
38629
+ let lines = newStr.split("\n");
38630
+ if (lines.length === 0) return { result: newStr, modifications };
38631
+ if (position === "after") {
38632
+ const anchorIdx = startLine - 1;
38633
+ if (anchorIdx >= 0 && anchorIdx < fileLines.length) {
38634
+ const anchorTrimmed = fileLines[anchorIdx].trim();
38635
+ if (anchorTrimmed.length > 0 && lines.length > 0 && lines[0].trim() === anchorTrimmed) {
38636
+ lines = lines.slice(1);
38637
+ modifications.push("stripped echoed anchor line (insert-after)");
38638
+ }
38639
+ }
38640
+ } else if (position === "before") {
38641
+ const anchorIdx = startLine - 1;
38642
+ if (anchorIdx >= 0 && anchorIdx < fileLines.length) {
38643
+ const anchorTrimmed = fileLines[anchorIdx].trim();
38644
+ if (anchorTrimmed.length > 0 && lines.length > 0 && lines[lines.length - 1].trim() === anchorTrimmed) {
38645
+ lines = lines.slice(0, -1);
38646
+ modifications.push("stripped echoed anchor line (insert-before)");
38647
+ }
38648
+ }
38649
+ } else {
38650
+ const beforeIdx = startLine - 2;
38651
+ if (beforeIdx >= 0 && beforeIdx < fileLines.length) {
38652
+ const beforeTrimmed = fileLines[beforeIdx].trim();
38653
+ if (beforeTrimmed.length > 0 && lines.length > 0 && lines[0].trim() === beforeTrimmed) {
38654
+ lines = lines.slice(1);
38655
+ modifications.push("stripped echoed line before range");
38656
+ }
38657
+ }
38658
+ const afterIdx = endLine;
38659
+ if (afterIdx >= 0 && afterIdx < fileLines.length) {
38660
+ const afterTrimmed = fileLines[afterIdx].trim();
38661
+ if (afterTrimmed.length > 0 && lines.length > 0 && lines[lines.length - 1].trim() === afterTrimmed) {
38662
+ lines = lines.slice(0, -1);
38663
+ modifications.push("stripped echoed line after range");
38664
+ }
38665
+ }
38666
+ }
38667
+ return { result: lines.join("\n"), modifications };
38668
+ }
38669
+ function restoreIndentation(newStr, originalLines) {
38670
+ const modifications = [];
38671
+ if (!newStr || !originalLines || originalLines.length === 0) {
38672
+ return { result: newStr || "", modifications };
38673
+ }
38674
+ const originalCode = originalLines.join("\n");
38675
+ const targetIndent = detectBaseIndent(originalCode);
38676
+ const newIndent = detectBaseIndent(newStr);
38677
+ if (targetIndent !== newIndent) {
38678
+ const reindented = reindent(newStr, targetIndent);
38679
+ if (reindented !== newStr) {
38680
+ modifications.push(`reindented from "${newIndent}" to "${targetIndent}"`);
38681
+ return { result: reindented, modifications };
38682
+ }
38683
+ }
38684
+ return { result: newStr, modifications };
38685
+ }
38686
+ function cleanNewString(newStr, fileLines, startLine, endLine, position) {
38687
+ const modifications = [];
38688
+ if (!newStr && newStr !== "") return { cleaned: "", modifications };
38689
+ const { cleaned: afterPrefixes, stripped } = stripHashlinePrefixes(newStr);
38690
+ if (stripped) modifications.push("stripped line-number prefixes");
38691
+ const { result: afterEchoes, modifications: echoMods } = stripEchoedBoundaries(
38692
+ afterPrefixes,
38693
+ fileLines,
38694
+ startLine,
38695
+ endLine,
38696
+ position
38697
+ );
38698
+ modifications.push(...echoMods);
38699
+ if (!position) {
38700
+ const originalLines = fileLines.slice(startLine - 1, endLine);
38701
+ const { result: afterIndent, modifications: indentMods } = restoreIndentation(afterEchoes, originalLines);
38702
+ modifications.push(...indentMods);
38703
+ return { cleaned: afterIndent, modifications };
38704
+ }
38705
+ return { cleaned: afterEchoes, modifications };
38706
+ }
38707
+ var init_lineEditHeuristics = __esm({
38708
+ "src/tools/lineEditHeuristics.js"() {
38709
+ "use strict";
38710
+ init_symbolEdit();
38711
+ init_hashline();
38712
+ }
38713
+ });
38714
+
38308
38715
  // src/tools/edit.js
38309
38716
  function isPathAllowed(filePath, allowedFolders) {
38310
38717
  if (!allowedFolders || allowedFolders.length === 0) {
@@ -38328,6 +38735,174 @@ function parseFileToolOptions(options = {}) {
38328
38735
  workspaceRoot: options.workspaceRoot || options.cwd || allowedFolders.length > 0 && allowedFolders[0] || process.cwd()
38329
38736
  };
38330
38737
  }
38738
+ async function handleSymbolEdit({ resolvedPath: resolvedPath2, file_path, symbol: symbol15, new_string, position, debug, cwd, fileTracker }) {
38739
+ if (typeof symbol15 !== "string" || symbol15.trim() === "") {
38740
+ return 'Error editing file: Invalid symbol - must be a non-empty string. Provide the name of a function, class, method, or other named code definition (e.g. "myFunction" or "MyClass.myMethod"). To edit by text matching instead, use old_string + new_string.';
38741
+ }
38742
+ if (position !== void 0 && position !== null && position !== "before" && position !== "after") {
38743
+ return 'Error editing file: Invalid position - must be "before" or "after". Use position="before" to insert code above the symbol, or position="after" to insert code below it. Omit position entirely to replace the symbol with new_string.';
38744
+ }
38745
+ const allMatches = await findAllSymbols(resolvedPath2, symbol15, cwd || process.cwd());
38746
+ if (allMatches.length === 0) {
38747
+ return `Error editing file: Symbol "${symbol15}" not found in ${file_path}. Verify the symbol name matches a top-level function, class, method, or other named definition exactly as declared in the source. Use 'search' or 'extract' to inspect the file and find the correct symbol name. Alternatively, use old_string + new_string for text-based editing instead.`;
38748
+ }
38749
+ if (allMatches.length > 1) {
38750
+ const suggestions = allMatches.map(
38751
+ (m5) => ` - ${m5.qualifiedName} (${m5.nodeType}, line ${m5.startLine})`
38752
+ ).join("\n");
38753
+ return `Error editing ${file_path}: Found ${allMatches.length} symbols named "${symbol15}". Use a qualified name to specify which one:
38754
+ ${suggestions}
38755
+
38756
+ Example: <edit><file_path>${file_path}</file_path><symbol>${allMatches[0].qualifiedName}</symbol><new_string>...</new_string></edit>`;
38757
+ }
38758
+ const symbolInfo = allMatches[0];
38759
+ if (fileTracker) {
38760
+ const check = fileTracker.checkSymbolContent(resolvedPath2, symbol15, symbolInfo.code);
38761
+ if (!check.ok && check.reason === "stale") {
38762
+ return `Error editing ${file_path}: Symbol "${symbol15}" has changed since you last read it. Use extract to re-read the current content, then retry.
38763
+
38764
+ Example: <extract><targets>${file_path}#${symbol15}</targets></extract>`;
38765
+ }
38766
+ }
38767
+ const content = await import_fs4.promises.readFile(resolvedPath2, "utf-8");
38768
+ const lines = content.split("\n");
38769
+ if (position) {
38770
+ const refIndent = detectBaseIndent(symbolInfo.code);
38771
+ const reindented = reindent(new_string, refIndent);
38772
+ const newLines = reindented.split("\n");
38773
+ if (position === "after") {
38774
+ lines.splice(symbolInfo.endLine, 0, "", ...newLines);
38775
+ } else {
38776
+ lines.splice(symbolInfo.startLine - 1, 0, ...newLines, "");
38777
+ }
38778
+ await import_fs4.promises.writeFile(resolvedPath2, lines.join("\n"), "utf-8");
38779
+ if (fileTracker) {
38780
+ const updated = await findSymbol(resolvedPath2, symbol15, cwd || process.cwd());
38781
+ if (updated) {
38782
+ fileTracker.trackSymbolAfterWrite(resolvedPath2, symbol15, updated.code, updated.startLine, updated.endLine);
38783
+ }
38784
+ fileTracker.markFileSeen(resolvedPath2);
38785
+ }
38786
+ const insertLine = position === "after" ? symbolInfo.endLine + 1 : symbolInfo.startLine;
38787
+ if (debug) {
38788
+ console.error(`[Edit] Successfully inserted ${newLines.length} lines ${position} "${symbol15}" at line ${insertLine} in ${resolvedPath2}`);
38789
+ }
38790
+ return `Successfully inserted ${newLines.length} lines ${position} symbol "${symbol15}" in ${file_path} (at line ${insertLine})`;
38791
+ } else {
38792
+ const originalIndent = detectBaseIndent(symbolInfo.code);
38793
+ const reindented = reindent(new_string, originalIndent);
38794
+ const newLines = reindented.split("\n");
38795
+ lines.splice(symbolInfo.startLine - 1, symbolInfo.endLine - symbolInfo.startLine + 1, ...newLines);
38796
+ await import_fs4.promises.writeFile(resolvedPath2, lines.join("\n"), "utf-8");
38797
+ if (fileTracker) {
38798
+ const updated = await findSymbol(resolvedPath2, symbol15, cwd || process.cwd());
38799
+ if (updated) {
38800
+ fileTracker.trackSymbolAfterWrite(resolvedPath2, symbol15, updated.code, updated.startLine, updated.endLine);
38801
+ }
38802
+ fileTracker.markFileSeen(resolvedPath2);
38803
+ }
38804
+ if (debug) {
38805
+ console.error(`[Edit] Successfully replaced symbol "${symbol15}" in ${resolvedPath2} (lines ${symbolInfo.startLine}-${symbolInfo.endLine})`);
38806
+ }
38807
+ return `Successfully replaced symbol "${symbol15}" in ${file_path} (was lines ${symbolInfo.startLine}-${symbolInfo.endLine}, now ${newLines.length} lines)`;
38808
+ }
38809
+ }
38810
+ function buildLineEditResponse(file_path, startLine, endLine, newLineCount, updatedLines, insertOffset, action, heuristicMods) {
38811
+ const contextBefore = 1;
38812
+ const contextAfter = 1;
38813
+ const contextStart = Math.max(0, insertOffset - contextBefore);
38814
+ const contextEnd = Math.min(updatedLines.length, insertOffset + newLineCount + contextAfter);
38815
+ let context = "Context:\n";
38816
+ for (let i5 = contextStart; i5 < contextEnd; i5++) {
38817
+ const lineNum = i5 + 1;
38818
+ const hash = computeLineHash(updatedLines[i5]);
38819
+ const isNew = i5 >= insertOffset && i5 < insertOffset + newLineCount;
38820
+ const marker15 = isNew ? ">" : " ";
38821
+ context += `${marker15} ${lineNum}:${hash} | ${updatedLines[i5]}
38822
+ `;
38823
+ }
38824
+ let msg = `Successfully edited ${file_path} (${action})`;
38825
+ if (heuristicMods.length > 0) {
38826
+ msg += ` [auto-corrected: ${heuristicMods.join(", ")}]`;
38827
+ }
38828
+ msg += "\n" + context;
38829
+ return msg;
38830
+ }
38831
+ async function handleLineEdit({ resolvedPath: resolvedPath2, file_path, start_line, end_line, new_string, position, debug, fileTracker }) {
38832
+ const startRef = parseLineRef(start_line);
38833
+ if (!startRef) {
38834
+ return `Error editing file: Invalid start_line '${start_line}'. Use a line number (e.g. "42") or line:hash (e.g. "42:ab"). Line numbers are 1-indexed.`;
38835
+ }
38836
+ let endRef = null;
38837
+ if (end_line !== void 0 && end_line !== null) {
38838
+ endRef = parseLineRef(end_line);
38839
+ if (!endRef) {
38840
+ return `Error editing file: Invalid end_line '${end_line}'. Use a line number (e.g. "55") or line:hash (e.g. "55:cd"). Must be >= start_line.`;
38841
+ }
38842
+ }
38843
+ const startLine = startRef.line;
38844
+ const endLine = endRef ? endRef.line : startLine;
38845
+ if (endLine < startLine) {
38846
+ return `Error editing file: end_line (${endLine}) must be >= start_line (${startLine}).`;
38847
+ }
38848
+ if (position !== void 0 && position !== null && position !== "before" && position !== "after") {
38849
+ return 'Error editing file: Invalid position - must be "before" or "after". Use position="before" to insert before the line, or position="after" to insert after it.';
38850
+ }
38851
+ const content = await import_fs4.promises.readFile(resolvedPath2, "utf-8");
38852
+ const fileLines = content.split("\n");
38853
+ if (startLine > fileLines.length) {
38854
+ return `Error editing file: Line ${startLine} is beyond file length (${fileLines.length} lines). Use 'extract' to read the current file content.`;
38855
+ }
38856
+ if (endLine > fileLines.length) {
38857
+ return `Error editing file: Line ${endLine} is beyond file length (${fileLines.length} lines). Use 'extract' to read the current file content.`;
38858
+ }
38859
+ if (startRef.hash) {
38860
+ const validation = validateLineHash(startLine, startRef.hash, fileLines);
38861
+ if (!validation.valid) {
38862
+ return `Error editing file: Line ${startLine} has changed since last read. Expected hash '${startRef.hash}' but content is now: ${startLine}:${validation.actualHash} | ${validation.actualContent}. Use '${startLine}:${validation.actualHash}' instead.`;
38863
+ }
38864
+ }
38865
+ if (endRef && endRef.hash) {
38866
+ const validation = validateLineHash(endLine, endRef.hash, fileLines);
38867
+ if (!validation.valid) {
38868
+ return `Error editing file: Line ${endLine} has changed since last read. Expected hash '${endRef.hash}' but content is now: ${endLine}:${validation.actualHash} | ${validation.actualContent}. Use '${endLine}:${validation.actualHash}' instead.`;
38869
+ }
38870
+ }
38871
+ const { cleaned, modifications } = cleanNewString(new_string, fileLines, startLine, endLine, position);
38872
+ if (debug) {
38873
+ if (modifications.length > 0) {
38874
+ console.error(`[Edit] Heuristic corrections: ${modifications.join(", ")}`);
38875
+ }
38876
+ }
38877
+ const newLines = cleaned === "" ? [] : cleaned.split("\n");
38878
+ if (position === "after") {
38879
+ fileLines.splice(startLine, 0, ...newLines);
38880
+ await import_fs4.promises.writeFile(resolvedPath2, fileLines.join("\n"), "utf-8");
38881
+ if (fileTracker) await fileTracker.trackFileAfterWrite(resolvedPath2);
38882
+ const action = `${newLines.length} line${newLines.length !== 1 ? "s" : ""} inserted after line ${startLine}`;
38883
+ return buildLineEditResponse(file_path, startLine, startLine, newLines.length, fileLines, startLine, action, modifications);
38884
+ } else if (position === "before") {
38885
+ fileLines.splice(startLine - 1, 0, ...newLines);
38886
+ await import_fs4.promises.writeFile(resolvedPath2, fileLines.join("\n"), "utf-8");
38887
+ if (fileTracker) await fileTracker.trackFileAfterWrite(resolvedPath2);
38888
+ const action = `${newLines.length} line${newLines.length !== 1 ? "s" : ""} inserted before line ${startLine}`;
38889
+ return buildLineEditResponse(file_path, startLine, startLine, newLines.length, fileLines, startLine - 1, action, modifications);
38890
+ } else {
38891
+ const replacedCount = endLine - startLine + 1;
38892
+ fileLines.splice(startLine - 1, replacedCount, ...newLines);
38893
+ await import_fs4.promises.writeFile(resolvedPath2, fileLines.join("\n"), "utf-8");
38894
+ if (fileTracker) await fileTracker.trackFileAfterWrite(resolvedPath2);
38895
+ let action;
38896
+ if (newLines.length === 0) {
38897
+ action = `${replacedCount} line${replacedCount !== 1 ? "s" : ""} deleted (lines ${startLine}-${endLine})`;
38898
+ } else if (startLine === endLine) {
38899
+ action = `line ${startLine} replaced with ${newLines.length} line${newLines.length !== 1 ? "s" : ""}`;
38900
+ } else {
38901
+ action = `lines ${startLine}-${endLine} replaced with ${newLines.length} line${newLines.length !== 1 ? "s" : ""}`;
38902
+ }
38903
+ return buildLineEditResponse(file_path, startLine, endLine, newLines.length, fileLines, startLine - 1, action, modifications);
38904
+ }
38905
+ }
38331
38906
  var import_ai, import_fs4, import_path5, import_fs5, editTool, createTool, editSchema, createSchema, editDescription, createDescription, editToolDefinition, createToolDefinition;
38332
38907
  var init_edit = __esm({
38333
38908
  "src/tools/edit.js"() {
@@ -38337,24 +38912,31 @@ var init_edit = __esm({
38337
38912
  import_path5 = require("path");
38338
38913
  import_fs5 = require("fs");
38339
38914
  init_path_validation();
38915
+ init_fuzzyMatch();
38916
+ init_symbolEdit();
38917
+ init_hashline();
38918
+ init_lineEditHeuristics();
38340
38919
  editTool = (options = {}) => {
38341
38920
  const { debug, allowedFolders, cwd, workspaceRoot } = parseFileToolOptions(options);
38342
38921
  return (0, import_ai.tool)({
38343
38922
  name: "edit",
38344
- description: `Edit files using exact string replacement (Claude Code style).
38923
+ description: `Edit files using text replacement, AST-aware symbol operations, or line-targeted editing.
38345
38924
 
38346
- This tool performs exact string replacements in files. It requires the old_string to match exactly what's in the file, including all whitespace and indentation.
38925
+ Modes:
38926
+ 1. Text edit: Provide old_string + new_string to find and replace text (with fuzzy matching fallback)
38927
+ 2. Symbol replace: Provide symbol + new_string to replace an entire function/class/method by name
38928
+ 3. Symbol insert: Provide symbol + new_string + position to insert code before/after a symbol
38929
+ 4. Line-targeted edit: Provide start_line + new_string to edit by line number (from extract/search output)
38347
38930
 
38348
38931
  Parameters:
38349
38932
  - file_path: Path to the file to edit (absolute or relative)
38350
- - old_string: Exact text to find and replace (must be unique in the file unless replace_all is true)
38351
- - new_string: Text to replace with
38352
- - replace_all: (optional) Replace all occurrences instead of requiring uniqueness
38353
-
38354
- Important:
38355
- - The old_string must match EXACTLY including whitespace
38356
- - If old_string appears multiple times and replace_all is false, the edit will fail
38357
- - Use larger context around the string to ensure uniqueness when needed`,
38933
+ - new_string: Replacement text or new code content
38934
+ - old_string: (optional) Text to find and replace. If omitted, symbol or start_line must be provided.
38935
+ - replace_all: (optional) Replace all occurrences (text mode only)
38936
+ - symbol: (optional) Symbol name for AST-aware editing (e.g. "myFunction", "MyClass.myMethod")
38937
+ - position: (optional) "before" or "after" \u2014 insert code near a symbol or line instead of replacing it
38938
+ - start_line: (optional) Line reference (e.g. "42" or "42:ab") for line-targeted editing
38939
+ - end_line: (optional) End of line range, inclusive (e.g. "55" or "55:cd")`,
38358
38940
  inputSchema: {
38359
38941
  type: "object",
38360
38942
  properties: {
@@ -38364,30 +38946,44 @@ Important:
38364
38946
  },
38365
38947
  old_string: {
38366
38948
  type: "string",
38367
- description: "Exact text to find and replace"
38949
+ description: "Text to find and replace (for text-based editing)"
38368
38950
  },
38369
38951
  new_string: {
38370
38952
  type: "string",
38371
- description: "Text to replace with"
38953
+ description: "Replacement text or new code content"
38372
38954
  },
38373
38955
  replace_all: {
38374
38956
  type: "boolean",
38375
- description: "Replace all occurrences (default: false)",
38957
+ description: "Replace all occurrences (default: false, text mode only)",
38376
38958
  default: false
38959
+ },
38960
+ symbol: {
38961
+ type: "string",
38962
+ description: 'Symbol name for AST-aware editing (e.g. "myFunction", "MyClass.myMethod")'
38963
+ },
38964
+ position: {
38965
+ type: "string",
38966
+ enum: ["before", "after"],
38967
+ description: "Insert before/after symbol or line (requires symbol or start_line, omit to replace)"
38968
+ },
38969
+ start_line: {
38970
+ type: "string",
38971
+ description: 'Line reference for line-targeted editing (e.g. "42" or "42:ab" with hash)'
38972
+ },
38973
+ end_line: {
38974
+ type: "string",
38975
+ description: 'End of line range, inclusive (e.g. "55" or "55:cd"). Defaults to start_line.'
38377
38976
  }
38378
38977
  },
38379
- required: ["file_path", "old_string", "new_string"]
38978
+ required: ["file_path", "new_string"]
38380
38979
  },
38381
- execute: async ({ file_path, old_string, new_string, replace_all = false }) => {
38980
+ execute: async ({ file_path, old_string, new_string, replace_all = false, symbol: symbol15, position, start_line, end_line }) => {
38382
38981
  try {
38383
38982
  if (!file_path || typeof file_path !== "string" || file_path.trim() === "") {
38384
- return `Error editing file: Invalid file_path - must be a non-empty string`;
38385
- }
38386
- if (old_string === void 0 || old_string === null || typeof old_string !== "string") {
38387
- return `Error editing file: Invalid old_string - must be a string`;
38983
+ return `Error editing file: Invalid file_path - must be a non-empty string. Provide an absolute path or a path relative to the working directory (e.g. "src/main.js").`;
38388
38984
  }
38389
38985
  if (new_string === void 0 || new_string === null || typeof new_string !== "string") {
38390
- return `Error editing file: Invalid new_string - must be a string`;
38986
+ return `Error editing file: Invalid new_string - must be a string. Provide the replacement content as a string value (empty string "" is valid for deletions).`;
38391
38987
  }
38392
38988
  const resolvedPath2 = (0, import_path5.isAbsolute)(file_path) ? file_path : (0, import_path5.resolve)(cwd || process.cwd(), file_path);
38393
38989
  if (debug) {
@@ -38395,34 +38991,64 @@ Important:
38395
38991
  }
38396
38992
  if (!isPathAllowed(resolvedPath2, allowedFolders)) {
38397
38993
  const relativePath = toRelativePath(resolvedPath2, workspaceRoot);
38398
- return `Error editing file: Permission denied - ${relativePath} is outside allowed directories`;
38994
+ return `Error editing file: Permission denied - ${relativePath} is outside allowed directories. Use a file path within the project workspace.`;
38399
38995
  }
38400
38996
  if (!(0, import_fs5.existsSync)(resolvedPath2)) {
38401
- return `Error editing file: File not found - ${file_path}`;
38997
+ return `Error editing file: File not found - ${file_path}. Verify the path is correct and the file exists. Use 'search' to find files by name, or 'create' to make a new file.`;
38998
+ }
38999
+ if (options.fileTracker && !options.fileTracker.isFileSeen(resolvedPath2)) {
39000
+ const displayPath = toRelativePath(resolvedPath2, workspaceRoot);
39001
+ return `Error editing ${displayPath}: This file has not been read yet in this session. Use 'extract' to read the file first, then retry your edit. This ensures you are working with the current file content.
39002
+
39003
+ Example: <extract><targets>${displayPath}</targets></extract>`;
39004
+ }
39005
+ if (symbol15 !== void 0 && symbol15 !== null) {
39006
+ return await handleSymbolEdit({ resolvedPath: resolvedPath2, file_path, symbol: symbol15, new_string, position, debug, cwd, fileTracker: options.fileTracker });
39007
+ }
39008
+ if (start_line !== void 0 && start_line !== null) {
39009
+ return await handleLineEdit({ resolvedPath: resolvedPath2, file_path, start_line, end_line, new_string, position, debug, fileTracker: options.fileTracker });
39010
+ }
39011
+ if (old_string === void 0 || old_string === null) {
39012
+ return 'Error editing file: Must provide either old_string (for text edit), symbol (for AST-aware edit), or start_line (for line-targeted edit). For text editing: set old_string to the exact text to find and new_string to its replacement. For symbol editing: set symbol to a function/class/method name (e.g. "myFunction"). For line-targeted editing: set start_line to a line number from extract/search output (e.g. "42" or "42:ab").';
39013
+ }
39014
+ if (typeof old_string !== "string") {
39015
+ return `Error editing file: Invalid old_string - must be a string. Provide the exact text to find in the file, or use the symbol parameter instead for AST-aware editing by name.`;
38402
39016
  }
38403
39017
  const content = await import_fs4.promises.readFile(resolvedPath2, "utf-8");
39018
+ let matchTarget = old_string;
39019
+ let matchStrategy = "exact";
38404
39020
  if (!content.includes(old_string)) {
38405
- return `Error editing file: String not found - the specified old_string was not found in ${file_path}`;
39021
+ const fuzzy = findFuzzyMatch(content, old_string);
39022
+ if (!fuzzy) {
39023
+ return `Error editing file: String not found - the specified old_string was not found in ${file_path}. The text may have changed or differ from what you expected. Try: (1) Use 'search' or 'extract' to read the current file content and copy the exact text. (2) Use the symbol parameter to edit by function/class name instead. (3) Verify the file_path is correct.`;
39024
+ }
39025
+ matchTarget = fuzzy.matchedText;
39026
+ matchStrategy = fuzzy.strategy;
39027
+ if (debug) {
39028
+ console.error(`[Edit] Exact match failed, used ${matchStrategy} matching`);
39029
+ }
38406
39030
  }
38407
- const occurrences = content.split(old_string).length - 1;
39031
+ const occurrences = content.split(matchTarget).length - 1;
38408
39032
  if (!replace_all && occurrences > 1) {
38409
- return `Error editing file: Multiple occurrences found - the old_string appears ${occurrences} times. Use replace_all: true to replace all occurrences, or provide more context to make the string unique.`;
39033
+ return `Error editing file: Multiple occurrences found - the old_string appears ${occurrences} times in ${file_path}. To fix: (1) Set replace_all=true to replace all occurrences, or (2) Include more surrounding lines in old_string to make the match unique (add the full line or adjacent lines for context).`;
38410
39034
  }
38411
39035
  let newContent;
38412
39036
  if (replace_all) {
38413
- newContent = content.replaceAll(old_string, new_string);
39037
+ newContent = content.replaceAll(matchTarget, new_string);
38414
39038
  } else {
38415
- newContent = content.replace(old_string, new_string);
39039
+ newContent = content.replace(matchTarget, new_string);
38416
39040
  }
38417
39041
  if (newContent === content) {
38418
- return `Error editing file: No changes made - old_string and new_string might be the same`;
39042
+ return `Error editing file: No changes made - the replacement result is identical to the original. Verify that old_string and new_string are actually different. If fuzzy matching was used, the matched text may already equal new_string.`;
38419
39043
  }
38420
39044
  await import_fs4.promises.writeFile(resolvedPath2, newContent, "utf-8");
39045
+ if (options.fileTracker) await options.fileTracker.trackFileAfterWrite(resolvedPath2);
38421
39046
  const replacedCount = replace_all ? occurrences : 1;
38422
39047
  if (debug) {
38423
39048
  console.error(`[Edit] Successfully edited ${resolvedPath2}, replaced ${replacedCount} occurrence(s)`);
38424
39049
  }
38425
- return `Successfully edited ${file_path} (${replacedCount} replacement${replacedCount !== 1 ? "s" : ""})`;
39050
+ const strategyNote = matchStrategy !== "exact" ? `, matched via ${matchStrategy}` : "";
39051
+ return `Successfully edited ${file_path} (${replacedCount} replacement${replacedCount !== 1 ? "s" : ""}${strategyNote})`;
38426
39052
  } catch (error2) {
38427
39053
  console.error("[Edit] Error:", error2);
38428
39054
  return `Error editing file: ${error2.message}`;
@@ -38469,10 +39095,10 @@ Important:
38469
39095
  execute: async ({ file_path, content, overwrite = false }) => {
38470
39096
  try {
38471
39097
  if (!file_path || typeof file_path !== "string" || file_path.trim() === "") {
38472
- return `Error creating file: Invalid file_path - must be a non-empty string`;
39098
+ return `Error creating file: Invalid file_path - must be a non-empty string. Provide an absolute path or a path relative to the working directory (e.g. "src/newFile.js").`;
38473
39099
  }
38474
39100
  if (content === void 0 || content === null || typeof content !== "string") {
38475
- return `Error creating file: Invalid content - must be a string`;
39101
+ return `Error creating file: Invalid content - must be a string. Provide the file content as a string value (empty string "" is valid for an empty file).`;
38476
39102
  }
38477
39103
  const resolvedPath2 = (0, import_path5.isAbsolute)(file_path) ? file_path : (0, import_path5.resolve)(cwd || process.cwd(), file_path);
38478
39104
  if (debug) {
@@ -38480,15 +39106,17 @@ Important:
38480
39106
  }
38481
39107
  if (!isPathAllowed(resolvedPath2, allowedFolders)) {
38482
39108
  const relativePath = toRelativePath(resolvedPath2, workspaceRoot);
38483
- return `Error creating file: Permission denied - ${relativePath} is outside allowed directories`;
39109
+ return `Error creating file: Permission denied - ${relativePath} is outside allowed directories. Use a file path within the project workspace.`;
38484
39110
  }
38485
39111
  if ((0, import_fs5.existsSync)(resolvedPath2) && !overwrite) {
38486
39112
  return `Error creating file: File already exists - ${file_path}. Use overwrite: true to replace it.`;
38487
39113
  }
39114
+ const existed = (0, import_fs5.existsSync)(resolvedPath2);
38488
39115
  const dir = (0, import_path5.dirname)(resolvedPath2);
38489
39116
  await import_fs4.promises.mkdir(dir, { recursive: true });
38490
39117
  await import_fs4.promises.writeFile(resolvedPath2, content, "utf-8");
38491
- const action = (0, import_fs5.existsSync)(resolvedPath2) && overwrite ? "overwrote" : "created";
39118
+ if (options.fileTracker) await options.fileTracker.trackFileAfterWrite(resolvedPath2);
39119
+ const action = existed && overwrite ? "overwrote" : "created";
38492
39120
  const bytes = Buffer.byteLength(content, "utf-8");
38493
39121
  if (debug) {
38494
39122
  console.error(`[Create] Successfully ${action} ${resolvedPath2}`);
@@ -38510,18 +39138,35 @@ Important:
38510
39138
  },
38511
39139
  old_string: {
38512
39140
  type: "string",
38513
- description: "Exact text to find and replace"
39141
+ description: "Text to find and replace (for text-based editing)"
38514
39142
  },
38515
39143
  new_string: {
38516
39144
  type: "string",
38517
- description: "Text to replace with"
39145
+ description: "Replacement text or new code content"
38518
39146
  },
38519
39147
  replace_all: {
38520
39148
  type: "boolean",
38521
- description: "Replace all occurrences (default: false)"
39149
+ description: "Replace all occurrences (default: false, text mode only)"
39150
+ },
39151
+ symbol: {
39152
+ type: "string",
39153
+ description: 'Symbol name for AST-aware editing (e.g. "myFunction", "MyClass.myMethod")'
39154
+ },
39155
+ position: {
39156
+ type: "string",
39157
+ enum: ["before", "after"],
39158
+ description: "Insert before/after symbol or line (requires symbol or start_line, omit to replace)"
39159
+ },
39160
+ start_line: {
39161
+ type: "string",
39162
+ description: 'Line reference for line-targeted editing (e.g. "42" or "42:ab" with hash)'
39163
+ },
39164
+ end_line: {
39165
+ type: "string",
39166
+ description: 'End of line range, inclusive (e.g. "55" or "55:cd"). Defaults to start_line.'
38522
39167
  }
38523
39168
  },
38524
- required: ["file_path", "old_string", "new_string"]
39169
+ required: ["file_path", "new_string"]
38525
39170
  };
38526
39171
  createSchema = {
38527
39172
  type: "object",
@@ -38541,50 +39186,123 @@ Important:
38541
39186
  },
38542
39187
  required: ["file_path", "content"]
38543
39188
  };
38544
- editDescription = "Edit files using exact string replacement. Requires exact match including whitespace.";
39189
+ editDescription = "Edit files using text replacement, AST-aware symbol operations, or line-targeted editing. Supports fuzzy matching for text edits and optional hash-based integrity verification for line edits.";
38545
39190
  createDescription = "Create new files with specified content. Will create parent directories if needed.";
38546
39191
  editToolDefinition = `
38547
39192
  ## edit
38548
39193
  Description: ${editDescription}
38549
39194
 
38550
- When to use:
38551
- - For precise, surgical edits to existing files
38552
- - When you need to change specific lines or blocks of code
38553
- - For renaming functions, variables, or updating configuration values
38554
- - When the exact text to replace is known and unique (or use replace_all for multiple occurrences)
39195
+ Four editing modes \u2014 choose based on the scope of your change:
38555
39196
 
38556
- When NOT to use:
38557
- - For creating new files (use 'create' tool instead)
38558
- - When you cannot determine the exact text to replace
38559
- - When changes span multiple locations that would be better handled together
39197
+ 1. **Text edit** (old_string + new_string): For small, precise changes \u2014 fix a condition, rename a variable, update a value. Provide old_string copied verbatim from the file and new_string with the replacement. Fuzzy matching handles minor whitespace/indentation differences automatically, but always try to copy the exact text.
39198
+
39199
+ 2. **Symbol replace** (symbol + new_string): For replacing an entire function, class, or method by name. No need to quote the old code \u2014 just provide the symbol name and the full new implementation. Indentation is automatically adjusted to match the original. Prefer this mode when rewriting whole definitions.
39200
+
39201
+ 3. **Symbol insert** (symbol + new_string + position): For adding new code before or after an existing symbol. Set position to "before" or "after".
39202
+
39203
+ 4. **Line-targeted edit** (start_line + new_string): For precise edits using line numbers from extract/search output. Use start_line with a line number (e.g. "42") or line:hash (e.g. "42:ab") for integrity verification. Add end_line for multi-line ranges. Use position="before" or "after" to insert instead of replace.
38560
39204
 
38561
39205
  Parameters:
38562
39206
  - file_path: (required) Path to the file to edit
38563
- - old_string: (required) Exact text to find and replace (must match including whitespace, newlines, and indentation)
38564
- - new_string: (required) Text to replace with
38565
- - replace_all: (optional, default: false) Replace all occurrences if the string appears multiple times
38566
-
38567
- Important notes:
38568
- - The old_string MUST match EXACTLY, including all whitespace, indentation, and line breaks
38569
- - If old_string appears multiple times and replace_all is false, the tool will fail
38570
- - Always verify the exact formatting of the text you want to replace
39207
+ - new_string: (required) Replacement text or new code content
39208
+ - old_string: (optional) Text to find and replace \u2014 copy verbatim from the file, do not paraphrase or reformat
39209
+ - replace_all: (optional, default: false) Replace all occurrences of old_string (text mode only)
39210
+ - symbol: (optional) Name of a code symbol (e.g. "myFunction", "MyClass.myMethod") \u2014 must match a function, class, or method definition
39211
+ - position: (optional) "before" or "after" \u2014 insert new_string near the symbol or line instead of replacing it
39212
+ - start_line: (optional) Line reference for line-targeted editing (e.g. "42" or "42:ab")
39213
+ - end_line: (optional) End of line range, inclusive (e.g. "55" or "55:cd"). Defaults to start_line.
39214
+
39215
+ Mode selection rules (priority order):
39216
+ - If symbol is provided, symbol mode is used (old_string and start_line are ignored)
39217
+ - If start_line is provided (without symbol), line-targeted mode is used
39218
+ - If old_string is provided (without symbol or start_line), text mode is used
39219
+ - If none are provided, the tool returns an error with guidance
39220
+
39221
+ When to use each mode:
39222
+ - Small edits (a line or a few lines): use text mode with old_string
39223
+ - Replacing entire functions/classes/methods: use symbol mode \u2014 no exact text matching needed
39224
+ - Editing specific lines from extract/search output: use line-targeted mode with start_line
39225
+ - Editing inside large functions without rewriting them entirely: first use extract with the symbol target (e.g. "file.js#myFunction") to see the function with line numbers, then use start_line/end_line to edit specific lines within it
39226
+
39227
+ Error handling:
39228
+ - If an edit fails, read the error message carefully \u2014 it contains specific instructions for how to fix the call and retry
39229
+ - Common fixes: use 'search'/'extract' to get exact file content, add more context to old_string, switch between text and symbol modes
39230
+ - Line-targeted hash mismatch: the file changed since last read; the error provides updated line:hash references
38571
39231
 
38572
39232
  Examples:
39233
+
39234
+ Text edit (find and replace):
38573
39235
  <edit>
38574
39236
  <file_path>src/main.js</file_path>
38575
- <old_string>function oldName() {
38576
- return 42;
38577
- }</old_string>
38578
- <new_string>function newName() {
38579
- return 42;
38580
- }</new_string>
39237
+ <old_string>return false;</old_string>
39238
+ <new_string>return true;</new_string>
38581
39239
  </edit>
38582
39240
 
39241
+ Text edit with replace_all:
38583
39242
  <edit>
38584
39243
  <file_path>config.json</file_path>
38585
39244
  <old_string>"debug": false</old_string>
38586
39245
  <new_string>"debug": true</new_string>
38587
39246
  <replace_all>true</replace_all>
39247
+ </edit>
39248
+
39249
+ Symbol replace (rewrite entire function by name):
39250
+ <edit>
39251
+ <file_path>src/utils.js</file_path>
39252
+ <symbol>calculateTotal</symbol>
39253
+ <new_string>function calculateTotal(items) {
39254
+ return items.reduce((sum, item) => sum + item.price * item.quantity, 0);
39255
+ }</new_string>
39256
+ </edit>
39257
+
39258
+ Symbol insert (add new function after existing one):
39259
+ <edit>
39260
+ <file_path>src/utils.js</file_path>
39261
+ <symbol>calculateTotal</symbol>
39262
+ <position>after</position>
39263
+ <new_string>function calculateTax(total, rate) {
39264
+ return total * rate;
39265
+ }</new_string>
39266
+ </edit>
39267
+
39268
+ Line-targeted edit (replace a line):
39269
+ <edit>
39270
+ <file_path>src/main.js</file_path>
39271
+ <start_line>42</start_line>
39272
+ <new_string> return processItems(order.items);</new_string>
39273
+ </edit>
39274
+
39275
+ Line-targeted edit (replace a range of lines):
39276
+ <edit>
39277
+ <file_path>src/main.js</file_path>
39278
+ <start_line>42</start_line>
39279
+ <end_line>55</end_line>
39280
+ <new_string> // simplified implementation
39281
+ return processItems(order.items);</new_string>
39282
+ </edit>
39283
+
39284
+ Line-targeted edit with hash verification:
39285
+ <edit>
39286
+ <file_path>src/main.js</file_path>
39287
+ <start_line>42:ab</start_line>
39288
+ <end_line>55:cd</end_line>
39289
+ <new_string> return processItems(order.items);</new_string>
39290
+ </edit>
39291
+
39292
+ Line-targeted insert (add code after a line):
39293
+ <edit>
39294
+ <file_path>src/main.js</file_path>
39295
+ <start_line>42</start_line>
39296
+ <position>after</position>
39297
+ <new_string> const validated = validate(input);</new_string>
39298
+ </edit>
39299
+
39300
+ Line-targeted delete (remove lines):
39301
+ <edit>
39302
+ <file_path>src/main.js</file_path>
39303
+ <start_line>42</start_line>
39304
+ <end_line>45</end_line>
39305
+ <new_string></new_string>
38588
39306
  </edit>`;
38589
39307
  createToolDefinition = `
38590
39308
  ## create
@@ -39121,7 +39839,7 @@ function getValidParamsForTool(toolName) {
39121
39839
  };
39122
39840
  const schema = schemaMap[toolName];
39123
39841
  if (!schema) {
39124
- return ["path", "directory", "pattern", "recursive", "includeHidden", "task", "files", "autoCommits", "result"];
39842
+ return ["path", "directory", "pattern", "recursive", "includeHidden", "task", "files", "result"];
39125
39843
  }
39126
39844
  if (toolName === "attempt_completion") {
39127
39845
  return ["result"];
@@ -39242,7 +39960,6 @@ function detectUnrecognizedToolCall(xmlString, validTools) {
39242
39960
  "listSkills",
39243
39961
  "useSkill",
39244
39962
  "readImage",
39245
- "implement",
39246
39963
  "edit",
39247
39964
  "create",
39248
39965
  "delegate",
@@ -39617,6 +40334,8 @@ User: Read file inside the dependency
39617
40334
  </extract>
39618
40335
 
39619
40336
  </examples>
40337
+
40338
+ **Edit Integration:** The line numbers shown in extract output (e.g. "42 | code") can be used directly with the edit tool's start_line/end_line parameters for precise line-targeted editing. To edit inside a large function: extract it by symbol name first (e.g. "file.js#myFunction"), then use the line numbers from the output to make surgical edits with start_line/end_line.
39620
40339
  `;
39621
40340
  delegateToolDefinition = `
39622
40341
  ## delegate
@@ -39772,7 +40491,7 @@ Capabilities:
39772
40491
  `;
39773
40492
  searchDescription = "Search code in the repository. Free-form questions are accepted, but Elasticsearch-style keyword queries work best. Use this tool first for any code-related questions.";
39774
40493
  queryDescription = "Search code using ast-grep structural pattern matching. Use this tool to find specific code structures like functions, classes, or methods.";
39775
- extractDescription = "Extract code blocks from files based on file paths and optional line numbers. Use this tool to see complete context after finding relevant files.";
40494
+ extractDescription = "Extract code blocks from files based on file paths and optional line numbers. Use this tool to see complete context after finding relevant files. Line numbers from output can be used with edit start_line/end_line for precise editing.";
39776
40495
  delegateDescription = "Automatically delegate big distinct tasks to specialized probe subagents within the agentic loop. Used by AI agents to break down complex requests into focused, parallel tasks.";
39777
40496
  analyzeAllDescription = 'Answer questions that require analyzing ALL matching data in the codebase. Use for aggregate questions like "What features exist?", "List all API endpoints", "Count TODO comments". The AI automatically plans the search strategy, processes all results via map-reduce, and synthesizes a comprehensive answer. WARNING: Slower than search - only use when you need complete coverage.';
39778
40497
  DEFAULT_VALID_TOOLS = [
@@ -39787,7 +40506,6 @@ Capabilities:
39787
40506
  "useSkill",
39788
40507
  "listFiles",
39789
40508
  "searchFiles",
39790
- "implement",
39791
40509
  "bash",
39792
40510
  "task",
39793
40511
  "attempt_completion"
@@ -39912,6 +40630,7 @@ var init_vercel = __esm({
39912
40630
  init_analyzeAll();
39913
40631
  init_common2();
39914
40632
  init_error_types();
40633
+ init_hashline();
39915
40634
  CODE_SEARCH_SCHEMA = {
39916
40635
  type: "object",
39917
40636
  properties: {
@@ -39930,8 +40649,15 @@ var init_vercel = __esm({
39930
40649
  maxTokens = 2e4,
39931
40650
  debug = false,
39932
40651
  outline = false,
39933
- searchDelegate = false
40652
+ searchDelegate = false,
40653
+ hashLines = false
39934
40654
  } = options;
40655
+ const maybeAnnotate = (result) => {
40656
+ if (hashLines && typeof result === "string") {
40657
+ return annotateOutputWithHashes(result);
40658
+ }
40659
+ return result;
40660
+ };
39935
40661
  return (0, import_ai2.tool)({
39936
40662
  name: "search",
39937
40663
  description: searchDelegate ? `${searchDescription} (delegates code search to a subagent and returns extracted code blocks)` : searchDescription,
@@ -39973,7 +40699,12 @@ var init_vercel = __esm({
39973
40699
  };
39974
40700
  if (!searchDelegate) {
39975
40701
  try {
39976
- return await runRawSearch();
40702
+ const result = maybeAnnotate(await runRawSearch());
40703
+ if (options.fileTracker && typeof result === "string") {
40704
+ options.fileTracker.trackFilesFromOutput(result, options.cwd || ".").catch(() => {
40705
+ });
40706
+ }
40707
+ return result;
39977
40708
  } catch (error2) {
39978
40709
  console.error("Error executing search command:", error2);
39979
40710
  return formatErrorForAI(error2);
@@ -40016,7 +40747,12 @@ var init_vercel = __esm({
40016
40747
  if (debug) {
40017
40748
  console.error("Delegated search returned no targets; falling back to raw search");
40018
40749
  }
40019
- return await runRawSearch();
40750
+ const fallbackResult = maybeAnnotate(await runRawSearch());
40751
+ if (options.fileTracker && typeof fallbackResult === "string") {
40752
+ options.fileTracker.trackFilesFromOutput(fallbackResult, options.cwd || ".").catch(() => {
40753
+ });
40754
+ }
40755
+ return fallbackResult;
40020
40756
  }
40021
40757
  const resolutionBase = searchPaths[0] || options.cwd || ".";
40022
40758
  const resolvedTargets = targets.map((target) => resolveTargetPath(target, resolutionBase));
@@ -40031,13 +40767,18 @@ var init_vercel = __esm({
40031
40767
  const extractResult = await extract(extractOptions);
40032
40768
  if (resolutionBase && typeof extractResult === "string") {
40033
40769
  const wsPrefix = resolutionBase.endsWith("/") ? resolutionBase : resolutionBase + "/";
40034
- return extractResult.split(wsPrefix).join("");
40770
+ return maybeAnnotate(extractResult.split(wsPrefix).join(""));
40035
40771
  }
40036
- return extractResult;
40772
+ return maybeAnnotate(extractResult);
40037
40773
  } catch (error2) {
40038
40774
  console.error("Delegated search failed, falling back to raw search:", error2);
40039
40775
  try {
40040
- return await runRawSearch();
40776
+ const fallbackResult2 = maybeAnnotate(await runRawSearch());
40777
+ if (options.fileTracker && typeof fallbackResult2 === "string") {
40778
+ options.fileTracker.trackFilesFromOutput(fallbackResult2, options.cwd || ".").catch(() => {
40779
+ });
40780
+ }
40781
+ return fallbackResult2;
40041
40782
  } catch (fallbackError) {
40042
40783
  console.error("Error executing search command:", fallbackError);
40043
40784
  return formatErrorForAI(fallbackError);
@@ -40083,7 +40824,7 @@ var init_vercel = __esm({
40083
40824
  });
40084
40825
  };
40085
40826
  extractTool = (options = {}) => {
40086
- const { debug = false, outline = false } = options;
40827
+ const { debug = false, outline = false, hashLines = false } = options;
40087
40828
  return (0, import_ai2.tool)({
40088
40829
  name: "extract",
40089
40830
  description: extractDescription,
@@ -40100,6 +40841,7 @@ var init_vercel = __esm({
40100
40841
  }
40101
40842
  let tempFilePath = null;
40102
40843
  let extractOptions = { cwd: effectiveCwd };
40844
+ let extractFiles = null;
40103
40845
  if (input_content) {
40104
40846
  const { writeFileSync: writeFileSync2, unlinkSync } = await import("fs");
40105
40847
  const { join: join5 } = await import("path");
@@ -40123,13 +40865,13 @@ var init_vercel = __esm({
40123
40865
  };
40124
40866
  } else if (targets) {
40125
40867
  const parsedTargets = parseTargets(targets);
40126
- const files = parsedTargets.map((target) => resolveTargetPath(target, effectiveCwd));
40868
+ extractFiles = parsedTargets.map((target) => resolveTargetPath(target, effectiveCwd));
40127
40869
  let effectiveFormat = format2;
40128
40870
  if (outline && format2 === "outline-xml") {
40129
40871
  effectiveFormat = "xml";
40130
40872
  }
40131
40873
  extractOptions = {
40132
- files,
40874
+ files: extractFiles,
40133
40875
  cwd: effectiveCwd,
40134
40876
  allowTests: allow_tests ?? true,
40135
40877
  contextLines: context_lines,
@@ -40139,6 +40881,10 @@ var init_vercel = __esm({
40139
40881
  throw new Error("Either targets or input_content must be provided");
40140
40882
  }
40141
40883
  const results = await extract(extractOptions);
40884
+ if (options.fileTracker && extractFiles && extractFiles.length > 0) {
40885
+ options.fileTracker.trackFilesFromExtract(extractFiles, effectiveCwd).catch(() => {
40886
+ });
40887
+ }
40142
40888
  if (tempFilePath) {
40143
40889
  const { unlinkSync } = await import("fs");
40144
40890
  try {
@@ -40150,6 +40896,9 @@ var init_vercel = __esm({
40150
40896
  console.error(`Warning: Failed to remove temporary file: ${cleanupError.message}`);
40151
40897
  }
40152
40898
  }
40899
+ if (hashLines && typeof results === "string") {
40900
+ return annotateOutputWithHashes(results);
40901
+ }
40153
40902
  return results;
40154
40903
  } catch (error2) {
40155
40904
  console.error("Error executing extract command:", error2);
@@ -41497,7 +42246,7 @@ async function executeBashCommand(command, options = {}) {
41497
42246
  console.log(`[BashExecutor] Working directory: "${cwd}"`);
41498
42247
  console.log(`[BashExecutor] Timeout: ${timeout}ms`);
41499
42248
  }
41500
- return new Promise((resolve7, reject2) => {
42249
+ return new Promise((resolve8, reject2) => {
41501
42250
  const processEnv = {
41502
42251
  ...process.env,
41503
42252
  ...env
@@ -41514,7 +42263,7 @@ async function executeBashCommand(command, options = {}) {
41514
42263
  } else {
41515
42264
  const args = parseCommandForExecution(command);
41516
42265
  if (!args || args.length === 0) {
41517
- resolve7({
42266
+ resolve8({
41518
42267
  success: false,
41519
42268
  error: "Failed to parse command",
41520
42269
  stdout: "",
@@ -41599,7 +42348,7 @@ async function executeBashCommand(command, options = {}) {
41599
42348
  success = false;
41600
42349
  error2 = `Command exited with code ${code}`;
41601
42350
  }
41602
- resolve7({
42351
+ resolve8({
41603
42352
  success,
41604
42353
  error: error2,
41605
42354
  stdout: stdout.trim(),
@@ -41619,7 +42368,7 @@ async function executeBashCommand(command, options = {}) {
41619
42368
  if (debug) {
41620
42369
  console.log(`[BashExecutor] Spawn error:`, error2);
41621
42370
  }
41622
- resolve7({
42371
+ resolve8({
41623
42372
  success: false,
41624
42373
  error: `Failed to execute command: ${error2.message}`,
41625
42374
  stdout: "",
@@ -43031,14 +43780,14 @@ var require_executor = __commonJS({
43031
43780
  function asyncDone(callback) {
43032
43781
  let isInstant = false;
43033
43782
  let instant;
43034
- const p5 = new Promise((resolve7, reject2) => {
43783
+ const p5 = new Promise((resolve8, reject2) => {
43035
43784
  callback((err, result) => {
43036
43785
  if (err)
43037
43786
  reject2(err);
43038
43787
  else {
43039
43788
  isInstant = true;
43040
43789
  instant = result;
43041
- resolve7({ result });
43790
+ resolve8({ result });
43042
43791
  }
43043
43792
  });
43044
43793
  });
@@ -43061,10 +43810,10 @@ var require_executor = __commonJS({
43061
43810
  }
43062
43811
  async function execAsync4(ticks, tree, scope, context, doneOriginal, inLoopOrSwitch) {
43063
43812
  let done = doneOriginal;
43064
- const p5 = new Promise((resolve7) => {
43813
+ const p5 = new Promise((resolve8) => {
43065
43814
  done = (e5, r5) => {
43066
43815
  doneOriginal(e5, r5);
43067
- resolve7();
43816
+ resolve8();
43068
43817
  };
43069
43818
  });
43070
43819
  if (!_execNoneRecurse(ticks, tree, scope, context, done, true, inLoopOrSwitch) && utils.isLisp(tree)) {
@@ -51828,33 +52577,31 @@ var init_runtime = __esm({
51828
52577
  }
51829
52578
  });
51830
52579
 
51831
- // node_modules/balanced-match/index.js
51832
- var require_balanced_match = __commonJS({
51833
- "node_modules/balanced-match/index.js"(exports2, module2) {
51834
- "use strict";
51835
- module2.exports = balanced;
51836
- function balanced(a5, b5, str) {
51837
- if (a5 instanceof RegExp) a5 = maybeMatch(a5, str);
51838
- if (b5 instanceof RegExp) b5 = maybeMatch(b5, str);
51839
- var r5 = range2(a5, b5, str);
52580
+ // node_modules/balanced-match/dist/esm/index.js
52581
+ var balanced, maybeMatch, range2;
52582
+ var init_esm = __esm({
52583
+ "node_modules/balanced-match/dist/esm/index.js"() {
52584
+ balanced = (a5, b5, str) => {
52585
+ const ma = a5 instanceof RegExp ? maybeMatch(a5, str) : a5;
52586
+ const mb = b5 instanceof RegExp ? maybeMatch(b5, str) : b5;
52587
+ const r5 = ma !== null && mb != null && range2(ma, mb, str);
51840
52588
  return r5 && {
51841
52589
  start: r5[0],
51842
52590
  end: r5[1],
51843
52591
  pre: str.slice(0, r5[0]),
51844
- body: str.slice(r5[0] + a5.length, r5[1]),
51845
- post: str.slice(r5[1] + b5.length)
52592
+ body: str.slice(r5[0] + ma.length, r5[1]),
52593
+ post: str.slice(r5[1] + mb.length)
51846
52594
  };
51847
- }
51848
- function maybeMatch(reg, str) {
51849
- var m5 = str.match(reg);
52595
+ };
52596
+ maybeMatch = (reg, str) => {
52597
+ const m5 = str.match(reg);
51850
52598
  return m5 ? m5[0] : null;
51851
- }
51852
- balanced.range = range2;
51853
- function range2(a5, b5, str) {
51854
- var begs, beg, left, right, result;
51855
- var ai = str.indexOf(a5);
51856
- var bi = str.indexOf(b5, ai + 1);
51857
- var i5 = ai;
52599
+ };
52600
+ range2 = (a5, b5, str) => {
52601
+ let begs, beg, left, right = void 0, result;
52602
+ let ai = str.indexOf(a5);
52603
+ let bi = str.indexOf(b5, ai + 1);
52604
+ let i5 = ai;
51858
52605
  if (ai >= 0 && bi > 0) {
51859
52606
  if (a5 === b5) {
51860
52607
  return [ai, bi];
@@ -51862,14 +52609,16 @@ var require_balanced_match = __commonJS({
51862
52609
  begs = [];
51863
52610
  left = str.length;
51864
52611
  while (i5 >= 0 && !result) {
51865
- if (i5 == ai) {
52612
+ if (i5 === ai) {
51866
52613
  begs.push(i5);
51867
52614
  ai = str.indexOf(a5, i5 + 1);
51868
- } else if (begs.length == 1) {
51869
- result = [begs.pop(), bi];
52615
+ } else if (begs.length === 1) {
52616
+ const r5 = begs.pop();
52617
+ if (r5 !== void 0)
52618
+ result = [r5, bi];
51870
52619
  } else {
51871
52620
  beg = begs.pop();
51872
- if (beg < left) {
52621
+ if (beg !== void 0 && beg < left) {
51873
52622
  left = beg;
51874
52623
  right = bi;
51875
52624
  }
@@ -51877,163 +52626,179 @@ var require_balanced_match = __commonJS({
51877
52626
  }
51878
52627
  i5 = ai < bi && ai >= 0 ? ai : bi;
51879
52628
  }
51880
- if (begs.length) {
52629
+ if (begs.length && right !== void 0) {
51881
52630
  result = [left, right];
51882
52631
  }
51883
52632
  }
51884
52633
  return result;
51885
- }
52634
+ };
51886
52635
  }
51887
52636
  });
51888
52637
 
51889
- // node_modules/brace-expansion/index.js
51890
- var require_brace_expansion = __commonJS({
51891
- "node_modules/brace-expansion/index.js"(exports2, module2) {
51892
- var balanced = require_balanced_match();
51893
- module2.exports = expandTop;
51894
- var escSlash = "\0SLASH" + Math.random() + "\0";
51895
- var escOpen = "\0OPEN" + Math.random() + "\0";
51896
- var escClose = "\0CLOSE" + Math.random() + "\0";
51897
- var escComma = "\0COMMA" + Math.random() + "\0";
51898
- var escPeriod = "\0PERIOD" + Math.random() + "\0";
51899
- function numeric(str) {
51900
- return parseInt(str, 10) == str ? parseInt(str, 10) : str.charCodeAt(0);
51901
- }
51902
- function escapeBraces(str) {
51903
- return str.split("\\\\").join(escSlash).split("\\{").join(escOpen).split("\\}").join(escClose).split("\\,").join(escComma).split("\\.").join(escPeriod);
51904
- }
51905
- function unescapeBraces(str) {
51906
- return str.split(escSlash).join("\\").split(escOpen).join("{").split(escClose).join("}").split(escComma).join(",").split(escPeriod).join(".");
51907
- }
51908
- function parseCommaParts(str) {
51909
- if (!str)
51910
- return [""];
51911
- var parts = [];
51912
- var m5 = balanced("{", "}", str);
51913
- if (!m5)
51914
- return str.split(",");
51915
- var pre = m5.pre;
51916
- var body = m5.body;
51917
- var post = m5.post;
51918
- var p5 = pre.split(",");
51919
- p5[p5.length - 1] += "{" + body + "}";
51920
- var postParts = parseCommaParts(post);
51921
- if (post.length) {
51922
- p5[p5.length - 1] += postParts.shift();
51923
- p5.push.apply(p5, postParts);
51924
- }
51925
- parts.push.apply(parts, p5);
51926
- return parts;
51927
- }
51928
- function expandTop(str) {
51929
- if (!str)
51930
- return [];
51931
- if (str.substr(0, 2) === "{}") {
51932
- str = "\\{\\}" + str.substr(2);
51933
- }
51934
- return expand2(escapeBraces(str), true).map(unescapeBraces);
51935
- }
51936
- function embrace(str) {
51937
- return "{" + str + "}";
51938
- }
51939
- function isPadded(el) {
51940
- return /^-?0\d/.test(el);
51941
- }
51942
- function lte(i5, y2) {
51943
- return i5 <= y2;
51944
- }
51945
- function gte(i5, y2) {
51946
- return i5 >= y2;
52638
+ // node_modules/brace-expansion/dist/esm/index.js
52639
+ function numeric(str) {
52640
+ return !isNaN(str) ? parseInt(str, 10) : str.charCodeAt(0);
52641
+ }
52642
+ function escapeBraces(str) {
52643
+ return str.replace(slashPattern, escSlash).replace(openPattern, escOpen).replace(closePattern, escClose).replace(commaPattern, escComma).replace(periodPattern, escPeriod);
52644
+ }
52645
+ function unescapeBraces(str) {
52646
+ return str.replace(escSlashPattern, "\\").replace(escOpenPattern, "{").replace(escClosePattern, "}").replace(escCommaPattern, ",").replace(escPeriodPattern, ".");
52647
+ }
52648
+ function parseCommaParts(str) {
52649
+ if (!str) {
52650
+ return [""];
52651
+ }
52652
+ const parts = [];
52653
+ const m5 = balanced("{", "}", str);
52654
+ if (!m5) {
52655
+ return str.split(",");
52656
+ }
52657
+ const { pre, body, post } = m5;
52658
+ const p5 = pre.split(",");
52659
+ p5[p5.length - 1] += "{" + body + "}";
52660
+ const postParts = parseCommaParts(post);
52661
+ if (post.length) {
52662
+ ;
52663
+ p5[p5.length - 1] += postParts.shift();
52664
+ p5.push.apply(p5, postParts);
52665
+ }
52666
+ parts.push.apply(parts, p5);
52667
+ return parts;
52668
+ }
52669
+ function expand(str, options = {}) {
52670
+ if (!str) {
52671
+ return [];
52672
+ }
52673
+ const { max = EXPANSION_MAX } = options;
52674
+ if (str.slice(0, 2) === "{}") {
52675
+ str = "\\{\\}" + str.slice(2);
52676
+ }
52677
+ return expand_(escapeBraces(str), max, true).map(unescapeBraces);
52678
+ }
52679
+ function embrace(str) {
52680
+ return "{" + str + "}";
52681
+ }
52682
+ function isPadded(el) {
52683
+ return /^-?0\d/.test(el);
52684
+ }
52685
+ function lte(i5, y2) {
52686
+ return i5 <= y2;
52687
+ }
52688
+ function gte(i5, y2) {
52689
+ return i5 >= y2;
52690
+ }
52691
+ function expand_(str, max, isTop) {
52692
+ const expansions = [];
52693
+ const m5 = balanced("{", "}", str);
52694
+ if (!m5)
52695
+ return [str];
52696
+ const pre = m5.pre;
52697
+ const post = m5.post.length ? expand_(m5.post, max, false) : [""];
52698
+ if (/\$$/.test(m5.pre)) {
52699
+ for (let k5 = 0; k5 < post.length && k5 < max; k5++) {
52700
+ const expansion = pre + "{" + m5.body + "}" + post[k5];
52701
+ expansions.push(expansion);
51947
52702
  }
51948
- function expand2(str, isTop) {
51949
- var expansions = [];
51950
- var m5 = balanced("{", "}", str);
51951
- if (!m5) return [str];
51952
- var pre = m5.pre;
51953
- var post = m5.post.length ? expand2(m5.post, false) : [""];
51954
- if (/\$$/.test(m5.pre)) {
51955
- for (var k5 = 0; k5 < post.length; k5++) {
51956
- var expansion = pre + "{" + m5.body + "}" + post[k5];
51957
- expansions.push(expansion);
51958
- }
51959
- } else {
51960
- var isNumericSequence = /^-?\d+\.\.-?\d+(?:\.\.-?\d+)?$/.test(m5.body);
51961
- var isAlphaSequence = /^[a-zA-Z]\.\.[a-zA-Z](?:\.\.-?\d+)?$/.test(m5.body);
51962
- var isSequence = isNumericSequence || isAlphaSequence;
51963
- var isOptions = m5.body.indexOf(",") >= 0;
51964
- if (!isSequence && !isOptions) {
51965
- if (m5.post.match(/,(?!,).*\}/)) {
51966
- str = m5.pre + "{" + m5.body + escClose + m5.post;
51967
- return expand2(str);
51968
- }
51969
- return [str];
51970
- }
51971
- var n5;
51972
- if (isSequence) {
51973
- n5 = m5.body.split(/\.\./);
51974
- } else {
51975
- n5 = parseCommaParts(m5.body);
51976
- if (n5.length === 1) {
51977
- n5 = expand2(n5[0], false).map(embrace);
51978
- if (n5.length === 1) {
51979
- return post.map(function(p5) {
51980
- return m5.pre + n5[0] + p5;
51981
- });
51982
- }
52703
+ } else {
52704
+ const isNumericSequence = /^-?\d+\.\.-?\d+(?:\.\.-?\d+)?$/.test(m5.body);
52705
+ const isAlphaSequence = /^[a-zA-Z]\.\.[a-zA-Z](?:\.\.-?\d+)?$/.test(m5.body);
52706
+ const isSequence = isNumericSequence || isAlphaSequence;
52707
+ const isOptions = m5.body.indexOf(",") >= 0;
52708
+ if (!isSequence && !isOptions) {
52709
+ if (m5.post.match(/,(?!,).*\}/)) {
52710
+ str = m5.pre + "{" + m5.body + escClose + m5.post;
52711
+ return expand_(str, max, true);
52712
+ }
52713
+ return [str];
52714
+ }
52715
+ let n5;
52716
+ if (isSequence) {
52717
+ n5 = m5.body.split(/\.\./);
52718
+ } else {
52719
+ n5 = parseCommaParts(m5.body);
52720
+ if (n5.length === 1 && n5[0] !== void 0) {
52721
+ n5 = expand_(n5[0], max, false).map(embrace);
52722
+ if (n5.length === 1) {
52723
+ return post.map((p5) => m5.pre + n5[0] + p5);
52724
+ }
52725
+ }
52726
+ }
52727
+ let N;
52728
+ if (isSequence && n5[0] !== void 0 && n5[1] !== void 0) {
52729
+ const x5 = numeric(n5[0]);
52730
+ const y2 = numeric(n5[1]);
52731
+ const width = Math.max(n5[0].length, n5[1].length);
52732
+ let incr = n5.length === 3 && n5[2] !== void 0 ? Math.abs(numeric(n5[2])) : 1;
52733
+ let test = lte;
52734
+ const reverse = y2 < x5;
52735
+ if (reverse) {
52736
+ incr *= -1;
52737
+ test = gte;
52738
+ }
52739
+ const pad = n5.some(isPadded);
52740
+ N = [];
52741
+ for (let i5 = x5; test(i5, y2); i5 += incr) {
52742
+ let c5;
52743
+ if (isAlphaSequence) {
52744
+ c5 = String.fromCharCode(i5);
52745
+ if (c5 === "\\") {
52746
+ c5 = "";
51983
52747
  }
51984
- }
51985
- var N;
51986
- if (isSequence) {
51987
- var x5 = numeric(n5[0]);
51988
- var y2 = numeric(n5[1]);
51989
- var width = Math.max(n5[0].length, n5[1].length);
51990
- var incr = n5.length == 3 ? Math.abs(numeric(n5[2])) : 1;
51991
- var test = lte;
51992
- var reverse = y2 < x5;
51993
- if (reverse) {
51994
- incr *= -1;
51995
- test = gte;
51996
- }
51997
- var pad = n5.some(isPadded);
51998
- N = [];
51999
- for (var i5 = x5; test(i5, y2); i5 += incr) {
52000
- var c5;
52001
- if (isAlphaSequence) {
52002
- c5 = String.fromCharCode(i5);
52003
- if (c5 === "\\")
52004
- c5 = "";
52005
- } else {
52006
- c5 = String(i5);
52007
- if (pad) {
52008
- var need = width - c5.length;
52009
- if (need > 0) {
52010
- var z2 = new Array(need + 1).join("0");
52011
- if (i5 < 0)
52012
- c5 = "-" + z2 + c5.slice(1);
52013
- else
52014
- c5 = z2 + c5;
52015
- }
52748
+ } else {
52749
+ c5 = String(i5);
52750
+ if (pad) {
52751
+ const need = width - c5.length;
52752
+ if (need > 0) {
52753
+ const z2 = new Array(need + 1).join("0");
52754
+ if (i5 < 0) {
52755
+ c5 = "-" + z2 + c5.slice(1);
52756
+ } else {
52757
+ c5 = z2 + c5;
52016
52758
  }
52017
52759
  }
52018
- N.push(c5);
52019
- }
52020
- } else {
52021
- N = [];
52022
- for (var j5 = 0; j5 < n5.length; j5++) {
52023
- N.push.apply(N, expand2(n5[j5], false));
52024
52760
  }
52025
52761
  }
52026
- for (var j5 = 0; j5 < N.length; j5++) {
52027
- for (var k5 = 0; k5 < post.length; k5++) {
52028
- var expansion = pre + N[j5] + post[k5];
52029
- if (!isTop || isSequence || expansion)
52030
- expansions.push(expansion);
52031
- }
52762
+ N.push(c5);
52763
+ }
52764
+ } else {
52765
+ N = [];
52766
+ for (let j5 = 0; j5 < n5.length; j5++) {
52767
+ N.push.apply(N, expand_(n5[j5], max, false));
52768
+ }
52769
+ }
52770
+ for (let j5 = 0; j5 < N.length; j5++) {
52771
+ for (let k5 = 0; k5 < post.length && expansions.length < max; k5++) {
52772
+ const expansion = pre + N[j5] + post[k5];
52773
+ if (!isTop || isSequence || expansion) {
52774
+ expansions.push(expansion);
52032
52775
  }
52033
52776
  }
52034
- return expansions;
52035
52777
  }
52036
52778
  }
52779
+ return expansions;
52780
+ }
52781
+ var escSlash, escOpen, escClose, escComma, escPeriod, escSlashPattern, escOpenPattern, escClosePattern, escCommaPattern, escPeriodPattern, slashPattern, openPattern, closePattern, commaPattern, periodPattern, EXPANSION_MAX;
52782
+ var init_esm2 = __esm({
52783
+ "node_modules/brace-expansion/dist/esm/index.js"() {
52784
+ init_esm();
52785
+ escSlash = "\0SLASH" + Math.random() + "\0";
52786
+ escOpen = "\0OPEN" + Math.random() + "\0";
52787
+ escClose = "\0CLOSE" + Math.random() + "\0";
52788
+ escComma = "\0COMMA" + Math.random() + "\0";
52789
+ escPeriod = "\0PERIOD" + Math.random() + "\0";
52790
+ escSlashPattern = new RegExp(escSlash, "g");
52791
+ escOpenPattern = new RegExp(escOpen, "g");
52792
+ escClosePattern = new RegExp(escClose, "g");
52793
+ escCommaPattern = new RegExp(escComma, "g");
52794
+ escPeriodPattern = new RegExp(escPeriod, "g");
52795
+ slashPattern = /\\\\/g;
52796
+ openPattern = /\\{/g;
52797
+ closePattern = /\\}/g;
52798
+ commaPattern = /\\,/g;
52799
+ periodPattern = /\\./g;
52800
+ EXPANSION_MAX = 1e5;
52801
+ }
52037
52802
  });
52038
52803
 
52039
52804
  // node_modules/minimatch/dist/esm/assert-valid-pattern.js
@@ -52616,11 +53381,13 @@ var init_ast = __esm({
52616
53381
  let escaping = false;
52617
53382
  let re = "";
52618
53383
  let uflag = false;
53384
+ let inStar = false;
52619
53385
  for (let i5 = 0; i5 < glob2.length; i5++) {
52620
53386
  const c5 = glob2.charAt(i5);
52621
53387
  if (escaping) {
52622
53388
  escaping = false;
52623
53389
  re += (reSpecials.has(c5) ? "\\" : "") + c5;
53390
+ inStar = false;
52624
53391
  continue;
52625
53392
  }
52626
53393
  if (c5 === "\\") {
@@ -52638,16 +53405,19 @@ var init_ast = __esm({
52638
53405
  uflag = uflag || needUflag;
52639
53406
  i5 += consumed - 1;
52640
53407
  hasMagic2 = hasMagic2 || magic;
53408
+ inStar = false;
52641
53409
  continue;
52642
53410
  }
52643
53411
  }
52644
53412
  if (c5 === "*") {
52645
- if (noEmpty && glob2 === "*")
52646
- re += starNoEmpty;
52647
- else
52648
- re += star;
53413
+ if (inStar)
53414
+ continue;
53415
+ inStar = true;
53416
+ re += noEmpty && /^[*]+$/.test(glob2) ? starNoEmpty : star;
52649
53417
  hasMagic2 = true;
52650
53418
  continue;
53419
+ } else {
53420
+ inStar = false;
52651
53421
  }
52652
53422
  if (c5 === "?") {
52653
53423
  re += qmark;
@@ -52673,10 +53443,10 @@ var init_escape = __esm({
52673
53443
  });
52674
53444
 
52675
53445
  // node_modules/minimatch/dist/esm/index.js
52676
- var import_brace_expansion, minimatch, starDotExtRE, starDotExtTest, starDotExtTestDot, starDotExtTestNocase, starDotExtTestNocaseDot, starDotStarRE, starDotStarTest, starDotStarTestDot, dotStarRE, dotStarTest, starRE, starTest, starTestDot, qmarksRE, qmarksTestNocase, qmarksTestNocaseDot, qmarksTestDot, qmarksTest, qmarksTestNoExt, qmarksTestNoExtDot, defaultPlatform, path5, sep3, GLOBSTAR, qmark2, star2, twoStarDot, twoStarNoDot, filter, ext, defaults, braceExpand, makeRe, match, globMagic, regExpEscape2, Minimatch;
52677
- var init_esm = __esm({
53446
+ var minimatch, starDotExtRE, starDotExtTest, starDotExtTestDot, starDotExtTestNocase, starDotExtTestNocaseDot, starDotStarRE, starDotStarTest, starDotStarTestDot, dotStarRE, dotStarTest, starRE, starTest, starTestDot, qmarksRE, qmarksTestNocase, qmarksTestNocaseDot, qmarksTestDot, qmarksTest, qmarksTestNoExt, qmarksTestNoExtDot, defaultPlatform, path5, sep3, GLOBSTAR, qmark2, star2, twoStarDot, twoStarNoDot, filter, ext, defaults, braceExpand, makeRe, match, globMagic, regExpEscape2, Minimatch;
53447
+ var init_esm3 = __esm({
52678
53448
  "node_modules/minimatch/dist/esm/index.js"() {
52679
- import_brace_expansion = __toESM(require_brace_expansion(), 1);
53449
+ init_esm2();
52680
53450
  init_assert_valid_pattern();
52681
53451
  init_ast();
52682
53452
  init_escape();
@@ -52799,7 +53569,7 @@ var init_esm = __esm({
52799
53569
  if (options.nobrace || !/\{(?:(?!\{).)*\}/.test(pattern)) {
52800
53570
  return [pattern];
52801
53571
  }
52802
- return (0, import_brace_expansion.default)(pattern);
53572
+ return expand(pattern);
52803
53573
  };
52804
53574
  minimatch.braceExpand = braceExpand;
52805
53575
  makeRe = (pattern, options = {}) => new Minimatch(pattern, options).makeRe();
@@ -53405,7 +54175,7 @@ var init_esm = __esm({
53405
54175
 
53406
54176
  // node_modules/path-scurry/node_modules/lru-cache/dist/esm/index.js
53407
54177
  var perf, warned, PROCESS, emitWarning, AC, AS, shouldWarn, TYPE, isPosInt, getUintArray, ZeroArray, Stack, LRUCache;
53408
- var init_esm2 = __esm({
54178
+ var init_esm4 = __esm({
53409
54179
  "node_modules/path-scurry/node_modules/lru-cache/dist/esm/index.js"() {
53410
54180
  perf = typeof performance === "object" && performance && typeof performance.now === "function" ? performance : Date;
53411
54181
  warned = /* @__PURE__ */ new Set();
@@ -54779,7 +55549,7 @@ var init_esm2 = __esm({
54779
55549
 
54780
55550
  // node_modules/minipass/dist/esm/index.js
54781
55551
  var import_node_events, import_node_stream, import_node_string_decoder, proc, isStream, isReadable, isWritable, EOF, MAYBE_EMIT_END, EMITTED_END, EMITTING_END, EMITTED_ERROR, CLOSED, READ, FLUSH, FLUSHCHUNK, ENCODING, DECODER, FLOWING, PAUSED, RESUME, BUFFER, PIPES, BUFFERLENGTH, BUFFERPUSH, BUFFERSHIFT, OBJECTMODE, DESTROYED, ERROR, EMITDATA, EMITEND, EMITEND2, ASYNC, ABORT, ABORTED, SIGNAL, DATALISTENERS, DISCARDED, defer, nodefer, isEndish, isArrayBufferLike, isArrayBufferView, Pipe, PipeProxyErrors, isObjectModeOptions, isEncodingOptions, Minipass;
54782
- var init_esm3 = __esm({
55552
+ var init_esm5 = __esm({
54783
55553
  "node_modules/minipass/dist/esm/index.js"() {
54784
55554
  import_node_events = require("node:events");
54785
55555
  import_node_stream = __toESM(require("node:stream"), 1);
@@ -55509,10 +56279,10 @@ var init_esm3 = __esm({
55509
56279
  * Return a void Promise that resolves once the stream ends.
55510
56280
  */
55511
56281
  async promise() {
55512
- return new Promise((resolve7, reject2) => {
56282
+ return new Promise((resolve8, reject2) => {
55513
56283
  this.on(DESTROYED, () => reject2(new Error("stream destroyed")));
55514
56284
  this.on("error", (er) => reject2(er));
55515
- this.on("end", () => resolve7());
56285
+ this.on("end", () => resolve8());
55516
56286
  });
55517
56287
  }
55518
56288
  /**
@@ -55536,7 +56306,7 @@ var init_esm3 = __esm({
55536
56306
  return Promise.resolve({ done: false, value: res });
55537
56307
  if (this[EOF])
55538
56308
  return stop();
55539
- let resolve7;
56309
+ let resolve8;
55540
56310
  let reject2;
55541
56311
  const onerr = (er) => {
55542
56312
  this.off("data", ondata);
@@ -55550,19 +56320,19 @@ var init_esm3 = __esm({
55550
56320
  this.off("end", onend);
55551
56321
  this.off(DESTROYED, ondestroy);
55552
56322
  this.pause();
55553
- resolve7({ value, done: !!this[EOF] });
56323
+ resolve8({ value, done: !!this[EOF] });
55554
56324
  };
55555
56325
  const onend = () => {
55556
56326
  this.off("error", onerr);
55557
56327
  this.off("data", ondata);
55558
56328
  this.off(DESTROYED, ondestroy);
55559
56329
  stop();
55560
- resolve7({ done: true, value: void 0 });
56330
+ resolve8({ done: true, value: void 0 });
55561
56331
  };
55562
56332
  const ondestroy = () => onerr(new Error("stream destroyed"));
55563
56333
  return new Promise((res2, rej) => {
55564
56334
  reject2 = rej;
55565
- resolve7 = res2;
56335
+ resolve8 = res2;
55566
56336
  this.once(DESTROYED, ondestroy);
55567
56337
  this.once("error", onerr);
55568
56338
  this.once("end", onend);
@@ -55666,15 +56436,15 @@ var init_esm3 = __esm({
55666
56436
 
55667
56437
  // node_modules/path-scurry/dist/esm/index.js
55668
56438
  var import_node_path, import_node_url, import_fs7, actualFS, import_promises, realpathSync2, defaultFS, fsFromOption, uncDriveRegexp, uncToDrive, eitherSep, UNKNOWN, IFIFO, IFCHR, IFDIR, IFBLK, IFREG, IFLNK, IFSOCK, IFMT, IFMT_UNKNOWN, READDIR_CALLED, LSTAT_CALLED, ENOTDIR, ENOENT, ENOREADLINK, ENOREALPATH, ENOCHILD, TYPEMASK, entToType, normalizeCache, normalize, normalizeNocaseCache, normalizeNocase, ResolveCache, ChildrenCache, setAsCwd, PathBase, PathWin32, PathPosix, PathScurryBase, PathScurryWin32, PathScurryPosix, PathScurryDarwin, Path, PathScurry;
55669
- var init_esm4 = __esm({
56439
+ var init_esm6 = __esm({
55670
56440
  "node_modules/path-scurry/dist/esm/index.js"() {
55671
- init_esm2();
56441
+ init_esm4();
55672
56442
  import_node_path = require("node:path");
55673
56443
  import_node_url = require("node:url");
55674
56444
  import_fs7 = require("fs");
55675
56445
  actualFS = __toESM(require("node:fs"), 1);
55676
56446
  import_promises = require("node:fs/promises");
55677
- init_esm3();
56447
+ init_esm5();
55678
56448
  realpathSync2 = import_fs7.realpathSync.native;
55679
56449
  defaultFS = {
55680
56450
  lstatSync: import_fs7.lstatSync,
@@ -56546,9 +57316,9 @@ var init_esm4 = __esm({
56546
57316
  if (this.#asyncReaddirInFlight) {
56547
57317
  await this.#asyncReaddirInFlight;
56548
57318
  } else {
56549
- let resolve7 = () => {
57319
+ let resolve8 = () => {
56550
57320
  };
56551
- this.#asyncReaddirInFlight = new Promise((res) => resolve7 = res);
57321
+ this.#asyncReaddirInFlight = new Promise((res) => resolve8 = res);
56552
57322
  try {
56553
57323
  for (const e5 of await this.#fs.promises.readdir(fullpath, {
56554
57324
  withFileTypes: true
@@ -56561,7 +57331,7 @@ var init_esm4 = __esm({
56561
57331
  children.provisional = 0;
56562
57332
  }
56563
57333
  this.#asyncReaddirInFlight = void 0;
56564
- resolve7();
57334
+ resolve8();
56565
57335
  }
56566
57336
  return children.slice(0, children.provisional);
56567
57337
  }
@@ -57404,7 +58174,7 @@ var init_esm4 = __esm({
57404
58174
  var isPatternList, isGlobList, Pattern;
57405
58175
  var init_pattern = __esm({
57406
58176
  "node_modules/glob/dist/esm/pattern.js"() {
57407
- init_esm();
58177
+ init_esm3();
57408
58178
  isPatternList = (pl) => pl.length >= 1;
57409
58179
  isGlobList = (gl) => gl.length >= 1;
57410
58180
  Pattern = class _Pattern {
@@ -57575,7 +58345,7 @@ var init_pattern = __esm({
57575
58345
  var defaultPlatform2, Ignore;
57576
58346
  var init_ignore = __esm({
57577
58347
  "node_modules/glob/dist/esm/ignore.js"() {
57578
- init_esm();
58348
+ init_esm3();
57579
58349
  init_pattern();
57580
58350
  defaultPlatform2 = typeof process === "object" && process && typeof process.platform === "string" ? process.platform : "linux";
57581
58351
  Ignore = class {
@@ -57669,7 +58439,7 @@ var init_ignore = __esm({
57669
58439
  var HasWalkedCache, MatchRecord, SubWalks, Processor;
57670
58440
  var init_processor = __esm({
57671
58441
  "node_modules/glob/dist/esm/processor.js"() {
57672
- init_esm();
58442
+ init_esm3();
57673
58443
  HasWalkedCache = class _HasWalkedCache {
57674
58444
  store;
57675
58445
  constructor(store = /* @__PURE__ */ new Map()) {
@@ -57896,7 +58666,7 @@ var init_processor = __esm({
57896
58666
  var makeIgnore, GlobUtil, GlobWalker, GlobStream;
57897
58667
  var init_walker = __esm({
57898
58668
  "node_modules/glob/dist/esm/walker.js"() {
57899
- init_esm3();
58669
+ init_esm5();
57900
58670
  init_ignore();
57901
58671
  init_processor();
57902
58672
  makeIgnore = (ignore2, opts) => typeof ignore2 === "string" ? new Ignore([ignore2], opts) : Array.isArray(ignore2) ? new Ignore(ignore2, opts) : ignore2;
@@ -58231,9 +59001,9 @@ var init_walker = __esm({
58231
59001
  var import_node_url2, defaultPlatform3, Glob;
58232
59002
  var init_glob = __esm({
58233
59003
  "node_modules/glob/dist/esm/glob.js"() {
58234
- init_esm();
59004
+ init_esm3();
58235
59005
  import_node_url2 = require("node:url");
58236
- init_esm4();
59006
+ init_esm6();
58237
59007
  init_pattern();
58238
59008
  init_walker();
58239
59009
  defaultPlatform3 = typeof process === "object" && process && typeof process.platform === "string" ? process.platform : "linux";
@@ -58441,7 +59211,7 @@ var init_glob = __esm({
58441
59211
  var hasMagic;
58442
59212
  var init_has_magic = __esm({
58443
59213
  "node_modules/glob/dist/esm/has-magic.js"() {
58444
- init_esm();
59214
+ init_esm3();
58445
59215
  hasMagic = (pattern, options = {}) => {
58446
59216
  if (!Array.isArray(pattern)) {
58447
59217
  pattern = [pattern];
@@ -58475,12 +59245,12 @@ function globIterate(pattern, options = {}) {
58475
59245
  return new Glob(pattern, options).iterate();
58476
59246
  }
58477
59247
  var streamSync, stream, iterateSync, iterate, sync, glob;
58478
- var init_esm5 = __esm({
59248
+ var init_esm7 = __esm({
58479
59249
  "node_modules/glob/dist/esm/index.js"() {
58480
- init_esm();
59250
+ init_esm3();
58481
59251
  init_glob();
58482
59252
  init_has_magic();
58483
- init_esm();
59253
+ init_esm3();
58484
59254
  init_glob();
58485
59255
  init_has_magic();
58486
59256
  init_ignore();
@@ -59440,7 +60210,7 @@ var init_executePlan = __esm({
59440
60210
  init_query();
59441
60211
  init_extract();
59442
60212
  init_delegate();
59443
- init_esm5();
60213
+ init_esm7();
59444
60214
  init_bash();
59445
60215
  RAW_OUTPUT_START = "<<<RAW_OUTPUT>>>";
59446
60216
  RAW_OUTPUT_END = "<<<END_RAW_OUTPUT>>>";
@@ -59712,13 +60482,271 @@ var init_file_lister = __esm({
59712
60482
  }
59713
60483
  });
59714
60484
 
60485
+ // src/tools/fileTracker.js
60486
+ function computeContentHash(content) {
60487
+ const normalized = (content || "").split("\n").map((l5) => l5.trimEnd()).join("\n");
60488
+ return (0, import_crypto3.createHash)("sha256").update(normalized).digest("hex").slice(0, 16);
60489
+ }
60490
+ function extractFilePath(target) {
60491
+ const hashIdx = target.indexOf("#");
60492
+ if (hashIdx !== -1) {
60493
+ return target.slice(0, hashIdx);
60494
+ }
60495
+ const colonIdx = target.lastIndexOf(":");
60496
+ if (colonIdx !== -1) {
60497
+ const after = target.slice(colonIdx + 1);
60498
+ if (/^\d+(-\d+)?$/.test(after)) {
60499
+ return target.slice(0, colonIdx);
60500
+ }
60501
+ }
60502
+ return target;
60503
+ }
60504
+ function extractSymbolName(target) {
60505
+ const hashIdx = target.indexOf("#");
60506
+ if (hashIdx !== -1) {
60507
+ const symbol15 = target.slice(hashIdx + 1);
60508
+ return symbol15 || null;
60509
+ }
60510
+ return null;
60511
+ }
60512
+ function parseFilePathsFromOutput(output) {
60513
+ const paths = [];
60514
+ const regex = /^(?:File:\s+|---\s+)([^\s].*?)(?:\s+---)?$/gm;
60515
+ let match2;
60516
+ while ((match2 = regex.exec(output)) !== null) {
60517
+ const path9 = match2[1].trim();
60518
+ if (path9 && !path9.startsWith("Results") && !path9.startsWith("Page") && (path9.includes("/") || path9.includes(".") || path9.includes("\\"))) {
60519
+ paths.push(path9);
60520
+ }
60521
+ }
60522
+ return paths;
60523
+ }
60524
+ var import_crypto3, import_path10, FileTracker;
60525
+ var init_fileTracker = __esm({
60526
+ "src/tools/fileTracker.js"() {
60527
+ "use strict";
60528
+ import_crypto3 = require("crypto");
60529
+ import_path10 = require("path");
60530
+ init_symbolEdit();
60531
+ FileTracker = class {
60532
+ /**
60533
+ * @param {Object} [options]
60534
+ * @param {boolean} [options.debug=false] - Enable debug logging
60535
+ */
60536
+ constructor(options = {}) {
60537
+ this.debug = options.debug || false;
60538
+ this._seenFiles = /* @__PURE__ */ new Set();
60539
+ this._contentRecords = /* @__PURE__ */ new Map();
60540
+ }
60541
+ /**
60542
+ * Mark a file as "seen" — the LLM has read its content.
60543
+ * @param {string} resolvedPath - Absolute path to the file
60544
+ */
60545
+ markFileSeen(resolvedPath2) {
60546
+ this._seenFiles.add(resolvedPath2);
60547
+ if (this.debug) {
60548
+ console.error(`[FileTracker] Marked as seen: ${resolvedPath2}`);
60549
+ }
60550
+ }
60551
+ /**
60552
+ * Check if a file has been seen in this session.
60553
+ * @param {string} resolvedPath - Absolute path to the file
60554
+ * @returns {boolean}
60555
+ */
60556
+ isFileSeen(resolvedPath2) {
60557
+ return this._seenFiles.has(resolvedPath2);
60558
+ }
60559
+ /**
60560
+ * Store a content hash for a symbol in a file.
60561
+ * @param {string} resolvedPath - Absolute path to the file
60562
+ * @param {string} symbolName - Symbol name (e.g. "calculateTotal")
60563
+ * @param {string} code - The symbol's source code
60564
+ * @param {number} startLine - 1-indexed start line
60565
+ * @param {number} endLine - 1-indexed end line
60566
+ * @param {string} [source='extract'] - How the content was obtained
60567
+ */
60568
+ trackSymbolContent(resolvedPath2, symbolName, code, startLine, endLine, source = "extract") {
60569
+ const key = `${resolvedPath2}#${symbolName}`;
60570
+ const contentHash = computeContentHash(code);
60571
+ this._contentRecords.set(key, {
60572
+ contentHash,
60573
+ startLine,
60574
+ endLine,
60575
+ symbolName,
60576
+ source,
60577
+ timestamp: Date.now()
60578
+ });
60579
+ if (this.debug) {
60580
+ console.error(`[FileTracker] Tracked symbol ${key} (hash: ${contentHash}, lines ${startLine}-${endLine})`);
60581
+ }
60582
+ }
60583
+ /**
60584
+ * Look up a stored content record for a symbol.
60585
+ * @param {string} resolvedPath - Absolute path to the file
60586
+ * @param {string} symbolName - Symbol name
60587
+ * @returns {Object|null} The stored record or null
60588
+ */
60589
+ getSymbolRecord(resolvedPath2, symbolName) {
60590
+ return this._contentRecords.get(`${resolvedPath2}#${symbolName}`) || null;
60591
+ }
60592
+ /**
60593
+ * Check if a symbol's current content matches what was stored.
60594
+ * @param {string} resolvedPath - Absolute path to the file
60595
+ * @param {string} symbolName - Symbol name
60596
+ * @param {string} currentCode - The symbol's current source code (from findSymbol)
60597
+ * @returns {{ok: boolean, reason?: string, message?: string}}
60598
+ */
60599
+ checkSymbolContent(resolvedPath2, symbolName, currentCode) {
60600
+ const key = `${resolvedPath2}#${symbolName}`;
60601
+ const record = this._contentRecords.get(key);
60602
+ if (!record) {
60603
+ return { ok: true };
60604
+ }
60605
+ const currentHash = computeContentHash(currentCode);
60606
+ if (currentHash === record.contentHash) {
60607
+ return { ok: true };
60608
+ }
60609
+ return {
60610
+ ok: false,
60611
+ reason: "stale",
60612
+ message: `Symbol "${symbolName}" has changed since you last read it (hash: ${record.contentHash} \u2192 ${currentHash}).`
60613
+ };
60614
+ }
60615
+ /**
60616
+ * Track files from extract target strings.
60617
+ * Marks each file as seen. For #symbol targets, calls findSymbol to get and hash the code.
60618
+ * @param {string[]} targets - Array of extract targets (e.g. ["file.js#fn", "file.js:10-20"])
60619
+ * @param {string} cwd - Working directory for resolving relative paths
60620
+ */
60621
+ async trackFilesFromExtract(targets, cwd) {
60622
+ const seenPaths = /* @__PURE__ */ new Set();
60623
+ const symbolPromises = [];
60624
+ for (const target of targets) {
60625
+ const filePath = extractFilePath(target);
60626
+ const resolved = (0, import_path10.isAbsolute)(filePath) ? filePath : (0, import_path10.resolve)(cwd, filePath);
60627
+ if (!seenPaths.has(resolved)) {
60628
+ seenPaths.add(resolved);
60629
+ this.markFileSeen(resolved);
60630
+ }
60631
+ const symbolName = extractSymbolName(target);
60632
+ if (symbolName) {
60633
+ symbolPromises.push(
60634
+ findSymbol(resolved, symbolName, cwd).then((symbolInfo) => {
60635
+ if (symbolInfo) {
60636
+ this.trackSymbolContent(
60637
+ resolved,
60638
+ symbolName,
60639
+ symbolInfo.code,
60640
+ symbolInfo.startLine,
60641
+ symbolInfo.endLine,
60642
+ "extract"
60643
+ );
60644
+ }
60645
+ }).catch((err) => {
60646
+ if (this.debug) {
60647
+ console.error(`[FileTracker] Failed to track symbol "${symbolName}" in ${resolved}: ${err.message}`);
60648
+ }
60649
+ })
60650
+ );
60651
+ }
60652
+ }
60653
+ if (symbolPromises.length > 0) {
60654
+ await Promise.all(symbolPromises);
60655
+ }
60656
+ }
60657
+ /**
60658
+ * Track files discovered in probe search/extract output.
60659
+ * Parses "File: path" headers and "--- path ---" separators, marks each as "seen".
60660
+ * @param {string} output - Probe output text
60661
+ * @param {string} cwd - Working directory for resolving relative paths
60662
+ */
60663
+ async trackFilesFromOutput(output, cwd) {
60664
+ const paths = parseFilePathsFromOutput(output);
60665
+ for (const filePath of paths) {
60666
+ const resolved = (0, import_path10.isAbsolute)(filePath) ? filePath : (0, import_path10.resolve)(cwd, filePath);
60667
+ this.markFileSeen(resolved);
60668
+ }
60669
+ }
60670
+ /**
60671
+ * Check if a file is safe to edit (seen-check only).
60672
+ * Mode-specific content verification happens in edit handlers.
60673
+ * @param {string} resolvedPath - Absolute path to the file
60674
+ * @returns {{ok: boolean, reason?: string, message?: string}}
60675
+ */
60676
+ checkBeforeEdit(resolvedPath2) {
60677
+ if (!this._seenFiles.has(resolvedPath2)) {
60678
+ return {
60679
+ ok: false,
60680
+ reason: "untracked",
60681
+ message: "This file has not been read yet in this session. Use extract or search to read the file first."
60682
+ };
60683
+ }
60684
+ return { ok: true };
60685
+ }
60686
+ /**
60687
+ * Mark a file as seen after a successful write (backward compat).
60688
+ * Also invalidates content records for the file since its content changed.
60689
+ * @param {string} resolvedPath - Absolute path to the file
60690
+ */
60691
+ async trackFileAfterWrite(resolvedPath2) {
60692
+ this.markFileSeen(resolvedPath2);
60693
+ this.invalidateFileRecords(resolvedPath2);
60694
+ }
60695
+ /**
60696
+ * Update the stored hash for a symbol after a successful write.
60697
+ * Enables chained edits to the same symbol.
60698
+ * @param {string} resolvedPath - Absolute path to the file
60699
+ * @param {string} symbolName - Symbol name
60700
+ * @param {string} code - The symbol's new source code
60701
+ * @param {number} startLine - 1-indexed start line (new position)
60702
+ * @param {number} endLine - 1-indexed end line (new position)
60703
+ */
60704
+ trackSymbolAfterWrite(resolvedPath2, symbolName, code, startLine, endLine) {
60705
+ this.trackSymbolContent(resolvedPath2, symbolName, code, startLine, endLine, "edit");
60706
+ }
60707
+ /**
60708
+ * Remove all content records for a file.
60709
+ * Called after non-symbol edits (text/line mode) since those change content
60710
+ * without providing a symbol-level update.
60711
+ * @param {string} resolvedPath - Absolute path to the file
60712
+ */
60713
+ invalidateFileRecords(resolvedPath2) {
60714
+ const prefix = resolvedPath2 + "#";
60715
+ for (const key of this._contentRecords.keys()) {
60716
+ if (key.startsWith(prefix)) {
60717
+ this._contentRecords.delete(key);
60718
+ }
60719
+ }
60720
+ if (this.debug) {
60721
+ console.error(`[FileTracker] Invalidated content records for ${resolvedPath2}`);
60722
+ }
60723
+ }
60724
+ /**
60725
+ * Quick sync check if a file is being tracked (alias for isFileSeen).
60726
+ * @param {string} resolvedPath - Absolute path to the file
60727
+ * @returns {boolean}
60728
+ */
60729
+ isTracked(resolvedPath2) {
60730
+ return this.isFileSeen(resolvedPath2);
60731
+ }
60732
+ /**
60733
+ * Clear all tracking state.
60734
+ */
60735
+ clear() {
60736
+ this._seenFiles.clear();
60737
+ this._contentRecords.clear();
60738
+ }
60739
+ };
60740
+ }
60741
+ });
60742
+
59715
60743
  // src/agent/simpleTelemetry.js
59716
- var import_fs9, import_path10;
60744
+ var import_fs9, import_path11;
59717
60745
  var init_simpleTelemetry = __esm({
59718
60746
  "src/agent/simpleTelemetry.js"() {
59719
60747
  "use strict";
59720
60748
  import_fs9 = require("fs");
59721
- import_path10 = require("path");
60749
+ import_path11 = require("path");
59722
60750
  }
59723
60751
  });
59724
60752
 
@@ -59817,19 +60845,19 @@ function createWrappedTools(baseTools) {
59817
60845
  }
59818
60846
  return wrappedTools;
59819
60847
  }
59820
- var import_child_process8, import_util12, import_crypto3, import_events, import_fs10, import_fs11, import_path11, toolCallEmitter, activeToolExecutions, wrapToolWithEmitter, listFilesTool, searchFilesTool, listFilesToolInstance, searchFilesToolInstance;
60848
+ var import_child_process8, import_util12, import_crypto4, import_events, import_fs10, import_fs11, import_path12, toolCallEmitter, activeToolExecutions, wrapToolWithEmitter, listFilesTool, searchFilesTool, listFilesToolInstance, searchFilesToolInstance;
59821
60849
  var init_probeTool = __esm({
59822
60850
  "src/agent/probeTool.js"() {
59823
60851
  "use strict";
59824
60852
  init_index();
59825
60853
  import_child_process8 = require("child_process");
59826
60854
  import_util12 = require("util");
59827
- import_crypto3 = require("crypto");
60855
+ import_crypto4 = require("crypto");
59828
60856
  import_events = require("events");
59829
60857
  import_fs10 = __toESM(require("fs"), 1);
59830
60858
  import_fs11 = require("fs");
59831
- import_path11 = __toESM(require("path"), 1);
59832
- init_esm5();
60859
+ import_path12 = __toESM(require("path"), 1);
60860
+ init_esm7();
59833
60861
  init_symlink_utils();
59834
60862
  toolCallEmitter = new import_events.EventEmitter();
59835
60863
  activeToolExecutions = /* @__PURE__ */ new Map();
@@ -59839,7 +60867,7 @@ var init_probeTool = __esm({
59839
60867
  // Spread schema, description etc.
59840
60868
  execute: async (params) => {
59841
60869
  const debug = process.env.DEBUG === "1";
59842
- const toolSessionId = params.sessionId || (0, import_crypto3.randomUUID)();
60870
+ const toolSessionId = params.sessionId || (0, import_crypto4.randomUUID)();
59843
60871
  if (debug) {
59844
60872
  console.log(`[DEBUG] probeTool: Executing ${toolName} for session ${toolSessionId}`);
59845
60873
  }
@@ -59917,17 +60945,17 @@ var init_probeTool = __esm({
59917
60945
  execute: async (params) => {
59918
60946
  const { directory = ".", workingDirectory } = params;
59919
60947
  const baseCwd = workingDirectory || process.cwd();
59920
- const secureBaseDir = import_path11.default.resolve(baseCwd);
60948
+ const secureBaseDir = import_path12.default.resolve(baseCwd);
59921
60949
  const isDependencyPath = directory.startsWith("/dep/") || directory.startsWith("go:") || directory.startsWith("js:") || directory.startsWith("rust:");
59922
60950
  let targetDir;
59923
- if (import_path11.default.isAbsolute(directory)) {
59924
- targetDir = import_path11.default.resolve(directory);
59925
- if (!isDependencyPath && !targetDir.startsWith(secureBaseDir + import_path11.default.sep) && targetDir !== secureBaseDir) {
60951
+ if (import_path12.default.isAbsolute(directory)) {
60952
+ targetDir = import_path12.default.resolve(directory);
60953
+ if (!isDependencyPath && !targetDir.startsWith(secureBaseDir + import_path12.default.sep) && targetDir !== secureBaseDir) {
59926
60954
  throw new Error(`Path traversal attempt detected. Cannot access directory outside workspace: ${directory}`);
59927
60955
  }
59928
60956
  } else {
59929
- targetDir = import_path11.default.resolve(secureBaseDir, directory);
59930
- if (!isDependencyPath && !targetDir.startsWith(secureBaseDir + import_path11.default.sep) && targetDir !== secureBaseDir) {
60957
+ targetDir = import_path12.default.resolve(secureBaseDir, directory);
60958
+ if (!isDependencyPath && !targetDir.startsWith(secureBaseDir + import_path12.default.sep) && targetDir !== secureBaseDir) {
59931
60959
  throw new Error(`Path traversal attempt detected. Access denied: ${directory}`);
59932
60960
  }
59933
60961
  }
@@ -59944,7 +60972,7 @@ var init_probeTool = __esm({
59944
60972
  return `${(size / (1024 * 1024 * 1024)).toFixed(1)}G`;
59945
60973
  };
59946
60974
  const entries = await Promise.all(files.map(async (file) => {
59947
- const fullPath = import_path11.default.join(targetDir, file.name);
60975
+ const fullPath = import_path12.default.join(targetDir, file.name);
59948
60976
  const entryType = await getEntryType(file, fullPath);
59949
60977
  return {
59950
60978
  name: file.name,
@@ -59981,17 +61009,17 @@ var init_probeTool = __esm({
59981
61009
  throw new Error("Pattern is required for file search");
59982
61010
  }
59983
61011
  const baseCwd = workingDirectory || process.cwd();
59984
- const secureBaseDir = import_path11.default.resolve(baseCwd);
61012
+ const secureBaseDir = import_path12.default.resolve(baseCwd);
59985
61013
  const isDependencyPath = directory.startsWith("/dep/") || directory.startsWith("go:") || directory.startsWith("js:") || directory.startsWith("rust:");
59986
61014
  let targetDir;
59987
- if (import_path11.default.isAbsolute(directory)) {
59988
- targetDir = import_path11.default.resolve(directory);
59989
- if (!isDependencyPath && !targetDir.startsWith(secureBaseDir + import_path11.default.sep) && targetDir !== secureBaseDir) {
61015
+ if (import_path12.default.isAbsolute(directory)) {
61016
+ targetDir = import_path12.default.resolve(directory);
61017
+ if (!isDependencyPath && !targetDir.startsWith(secureBaseDir + import_path12.default.sep) && targetDir !== secureBaseDir) {
59990
61018
  throw new Error(`Path traversal attempt detected. Cannot access directory outside workspace: ${directory}`);
59991
61019
  }
59992
61020
  } else {
59993
- targetDir = import_path11.default.resolve(secureBaseDir, directory);
59994
- if (!isDependencyPath && !targetDir.startsWith(secureBaseDir + import_path11.default.sep) && targetDir !== secureBaseDir) {
61021
+ targetDir = import_path12.default.resolve(secureBaseDir, directory);
61022
+ if (!isDependencyPath && !targetDir.startsWith(secureBaseDir + import_path12.default.sep) && targetDir !== secureBaseDir) {
59995
61023
  throw new Error(`Path traversal attempt detected. Access denied: ${directory}`);
59996
61024
  }
59997
61025
  }
@@ -60568,6 +61596,7 @@ var init_index = __esm({
60568
61596
  init_executePlan();
60569
61597
  init_bash();
60570
61598
  init_edit();
61599
+ init_fileTracker();
60571
61600
  init_ProbeAgent();
60572
61601
  init_simpleTelemetry();
60573
61602
  init_probeTool();
@@ -60749,39 +61778,14 @@ function parseXmlToolCallWithThinking(xmlString, validTools) {
60749
61778
  const toolCall = parseXmlToolCall(cleanedXmlString, validTools);
60750
61779
  return toolCall ? { ...toolCall, thinkingContent } : null;
60751
61780
  }
60752
- var import_crypto4, implementToolDefinition, listFilesToolDefinition, searchFilesToolDefinition, listSkillsToolDefinition, useSkillToolDefinition, readImageToolDefinition;
61781
+ var import_crypto5, listFilesToolDefinition, searchFilesToolDefinition, listSkillsToolDefinition, useSkillToolDefinition, readImageToolDefinition;
60753
61782
  var init_tools2 = __esm({
60754
61783
  "src/agent/tools.js"() {
60755
61784
  "use strict";
60756
61785
  init_index();
60757
- import_crypto4 = require("crypto");
61786
+ import_crypto5 = require("crypto");
60758
61787
  init_xmlParsingUtils();
60759
61788
  init_tasks();
60760
- implementToolDefinition = `
60761
- ## implement
60762
- Description: Implement a given task. Can modify files. Can be used ONLY if task explicitly stated that something requires modification or implementation.
60763
-
60764
- Parameters:
60765
- - task: (required) The task description. Should be as detailed as possible, ideally pointing to exact files which needs be modified or created.
60766
- - autoCommits: (optional) Whether to enable auto-commits in aider. Default is false.
60767
-
60768
- Usage Example:
60769
-
60770
- <examples>
60771
-
60772
- User: Can you implement a function to calculate Fibonacci numbers in main.js?
60773
- <implement>
60774
- <task>Implement a recursive function to calculate the nth Fibonacci number in main.js</task>
60775
- </implement>
60776
-
60777
- User: Can you implement a function to calculate Fibonacci numbers in main.js with auto-commits?
60778
- <implement>
60779
- <task>Implement a recursive function to calculate the nth Fibonacci number in main.js</task>
60780
- <autoCommits>true</autoCommits>
60781
- </implement>
60782
-
60783
- </examples>
60784
- `;
60785
61789
  listFilesToolDefinition = `
60786
61790
  ## listFiles
60787
61791
  Description: List files and directories in a specified location.
@@ -60905,7 +61909,7 @@ function createMockProvider() {
60905
61909
  provider: "mock",
60906
61910
  // Mock the doGenerate method used by Vercel AI SDK
60907
61911
  doGenerate: async ({ messages, tools: tools2 }) => {
60908
- await new Promise((resolve7) => setTimeout(resolve7, 10));
61912
+ await new Promise((resolve8) => setTimeout(resolve8, 10));
60909
61913
  return {
60910
61914
  text: "This is a mock response for testing",
60911
61915
  toolCalls: [],
@@ -66108,23 +67112,23 @@ var init_regexp_parser = __esm({
66108
67112
  return ASSERT_NEVER_REACH_HERE();
66109
67113
  }
66110
67114
  quantifier(isBacktracking = false) {
66111
- let range2 = void 0;
67115
+ let range3 = void 0;
66112
67116
  const begin = this.idx;
66113
67117
  switch (this.popChar()) {
66114
67118
  case "*":
66115
- range2 = {
67119
+ range3 = {
66116
67120
  atLeast: 0,
66117
67121
  atMost: Infinity
66118
67122
  };
66119
67123
  break;
66120
67124
  case "+":
66121
- range2 = {
67125
+ range3 = {
66122
67126
  atLeast: 1,
66123
67127
  atMost: Infinity
66124
67128
  };
66125
67129
  break;
66126
67130
  case "?":
66127
- range2 = {
67131
+ range3 = {
66128
67132
  atLeast: 0,
66129
67133
  atMost: 1
66130
67134
  };
@@ -66133,7 +67137,7 @@ var init_regexp_parser = __esm({
66133
67137
  const atLeast = this.integerIncludingZero();
66134
67138
  switch (this.popChar()) {
66135
67139
  case "}":
66136
- range2 = {
67140
+ range3 = {
66137
67141
  atLeast,
66138
67142
  atMost: atLeast
66139
67143
  };
@@ -66142,12 +67146,12 @@ var init_regexp_parser = __esm({
66142
67146
  let atMost;
66143
67147
  if (this.isDigit()) {
66144
67148
  atMost = this.integerIncludingZero();
66145
- range2 = {
67149
+ range3 = {
66146
67150
  atLeast,
66147
67151
  atMost
66148
67152
  };
66149
67153
  } else {
66150
- range2 = {
67154
+ range3 = {
66151
67155
  atLeast,
66152
67156
  atMost: Infinity
66153
67157
  };
@@ -66155,25 +67159,25 @@ var init_regexp_parser = __esm({
66155
67159
  this.consumeChar("}");
66156
67160
  break;
66157
67161
  }
66158
- if (isBacktracking === true && range2 === void 0) {
67162
+ if (isBacktracking === true && range3 === void 0) {
66159
67163
  return void 0;
66160
67164
  }
66161
- ASSERT_EXISTS(range2);
67165
+ ASSERT_EXISTS(range3);
66162
67166
  break;
66163
67167
  }
66164
- if (isBacktracking === true && range2 === void 0) {
67168
+ if (isBacktracking === true && range3 === void 0) {
66165
67169
  return void 0;
66166
67170
  }
66167
- if (ASSERT_EXISTS(range2)) {
67171
+ if (ASSERT_EXISTS(range3)) {
66168
67172
  if (this.peekChar(0) === "?") {
66169
67173
  this.consumeChar("?");
66170
- range2.greedy = false;
67174
+ range3.greedy = false;
66171
67175
  } else {
66172
- range2.greedy = true;
67176
+ range3.greedy = true;
66173
67177
  }
66174
- range2.type = "Quantifier";
66175
- range2.loc = this.loc(begin);
66176
- return range2;
67178
+ range3.type = "Quantifier";
67179
+ range3.loc = this.loc(begin);
67180
+ return range3;
66177
67181
  }
66178
67182
  }
66179
67183
  atom() {
@@ -66875,18 +67879,18 @@ function firstCharOptimizedIndices(ast, result, ignoreCase) {
66875
67879
  if (typeof code === "number") {
66876
67880
  addOptimizedIdxToResult(code, result, ignoreCase);
66877
67881
  } else {
66878
- const range2 = code;
67882
+ const range3 = code;
66879
67883
  if (ignoreCase === true) {
66880
- for (let rangeCode = range2.from; rangeCode <= range2.to; rangeCode++) {
67884
+ for (let rangeCode = range3.from; rangeCode <= range3.to; rangeCode++) {
66881
67885
  addOptimizedIdxToResult(rangeCode, result, ignoreCase);
66882
67886
  }
66883
67887
  } else {
66884
- for (let rangeCode = range2.from; rangeCode <= range2.to && rangeCode < minOptimizationVal; rangeCode++) {
67888
+ for (let rangeCode = range3.from; rangeCode <= range3.to && rangeCode < minOptimizationVal; rangeCode++) {
66885
67889
  addOptimizedIdxToResult(rangeCode, result, ignoreCase);
66886
67890
  }
66887
- if (range2.to >= minOptimizationVal) {
66888
- const minUnOptVal = range2.from >= minOptimizationVal ? range2.from : minOptimizationVal;
66889
- const maxUnOptVal = range2.to;
67891
+ if (range3.to >= minOptimizationVal) {
67892
+ const minUnOptVal = range3.from >= minOptimizationVal ? range3.from : minOptimizationVal;
67893
+ const maxUnOptVal = range3.to;
66890
67894
  const minOptIdx = charCodeToOptimizedIndex(minUnOptVal);
66891
67895
  const maxOptIdx = charCodeToOptimizedIndex(maxUnOptVal);
66892
67896
  for (let currOptIdx = minOptIdx; currOptIdx <= maxOptIdx; currOptIdx++) {
@@ -66947,8 +67951,8 @@ function findCode(setNode, targetCharCodes) {
66947
67951
  if (typeof codeOrRange === "number") {
66948
67952
  return includes_default(targetCharCodes, codeOrRange);
66949
67953
  } else {
66950
- const range2 = codeOrRange;
66951
- return find_default(targetCharCodes, (targetCode) => range2.from <= targetCode && targetCode <= range2.to) !== void 0;
67954
+ const range3 = codeOrRange;
67955
+ return find_default(targetCharCodes, (targetCode) => range3.from <= targetCode && targetCode <= range3.to) !== void 0;
66952
67956
  }
66953
67957
  });
66954
67958
  }
@@ -84853,8 +85857,8 @@ var require_createRange = __commonJS({
84853
85857
  var require_range = __commonJS({
84854
85858
  "node_modules/lodash/range.js"(exports2, module2) {
84855
85859
  var createRange = require_createRange();
84856
- var range2 = createRange();
84857
- module2.exports = range2;
85860
+ var range3 = createRange();
85861
+ module2.exports = range3;
84858
85862
  }
84859
85863
  });
84860
85864
 
@@ -94095,7 +95099,7 @@ var require_compile = __commonJS({
94095
95099
  const schOrFunc = root2.refs[ref2];
94096
95100
  if (schOrFunc)
94097
95101
  return schOrFunc;
94098
- let _sch = resolve7.call(this, root2, ref2);
95102
+ let _sch = resolve8.call(this, root2, ref2);
94099
95103
  if (_sch === void 0) {
94100
95104
  const schema = (_a16 = root2.localRefs) === null || _a16 === void 0 ? void 0 : _a16[ref2];
94101
95105
  const { schemaId } = this.opts;
@@ -94122,7 +95126,7 @@ var require_compile = __commonJS({
94122
95126
  function sameSchemaEnv(s1, s22) {
94123
95127
  return s1.schema === s22.schema && s1.root === s22.root && s1.baseId === s22.baseId;
94124
95128
  }
94125
- function resolve7(root2, ref2) {
95129
+ function resolve8(root2, ref2) {
94126
95130
  let sch;
94127
95131
  while (typeof (sch = this.refs[ref2]) == "string")
94128
95132
  ref2 = sch;
@@ -94697,7 +95701,7 @@ var require_fast_uri = __commonJS({
94697
95701
  }
94698
95702
  return uri;
94699
95703
  }
94700
- function resolve7(baseURI, relativeURI, options) {
95704
+ function resolve8(baseURI, relativeURI, options) {
94701
95705
  const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
94702
95706
  const resolved = resolveComponent(parse9(baseURI, schemelessOptions), parse9(relativeURI, schemelessOptions), schemelessOptions, true);
94703
95707
  schemelessOptions.skipEscape = true;
@@ -94924,7 +95928,7 @@ var require_fast_uri = __commonJS({
94924
95928
  var fastUri = {
94925
95929
  SCHEMES,
94926
95930
  normalize: normalize3,
94927
- resolve: resolve7,
95931
+ resolve: resolve8,
94928
95932
  resolveComponent,
94929
95933
  equal,
94930
95934
  serialize,
@@ -99447,13 +100451,13 @@ function loadMCPConfiguration() {
99447
100451
  // Environment variable path
99448
100452
  process.env.MCP_CONFIG_PATH,
99449
100453
  // Local project paths
99450
- (0, import_path12.join)(process.cwd(), ".mcp", "config.json"),
99451
- (0, import_path12.join)(process.cwd(), "mcp.config.json"),
100454
+ (0, import_path13.join)(process.cwd(), ".mcp", "config.json"),
100455
+ (0, import_path13.join)(process.cwd(), "mcp.config.json"),
99452
100456
  // Home directory paths
99453
- (0, import_path12.join)((0, import_os3.homedir)(), ".config", "probe", "mcp.json"),
99454
- (0, import_path12.join)((0, import_os3.homedir)(), ".mcp", "config.json"),
100457
+ (0, import_path13.join)((0, import_os3.homedir)(), ".config", "probe", "mcp.json"),
100458
+ (0, import_path13.join)((0, import_os3.homedir)(), ".mcp", "config.json"),
99455
100459
  // Claude-style config location
99456
- (0, import_path12.join)((0, import_os3.homedir)(), "Library", "Application Support", "Claude", "mcp_config.json")
100460
+ (0, import_path13.join)((0, import_os3.homedir)(), "Library", "Application Support", "Claude", "mcp_config.json")
99457
100461
  ].filter(Boolean);
99458
100462
  let config = null;
99459
100463
  for (const configPath of configPaths) {
@@ -99580,16 +100584,16 @@ function parseEnabledServers(config) {
99580
100584
  }
99581
100585
  return servers;
99582
100586
  }
99583
- var import_fs12, import_path12, import_os3, import_url4, __filename4, __dirname4, DEFAULT_TIMEOUT, MAX_TIMEOUT, DEFAULT_CONFIG;
100587
+ var import_fs12, import_path13, import_os3, import_url4, __filename4, __dirname4, DEFAULT_TIMEOUT, MAX_TIMEOUT, DEFAULT_CONFIG;
99584
100588
  var init_config = __esm({
99585
100589
  "src/agent/mcp/config.js"() {
99586
100590
  "use strict";
99587
100591
  import_fs12 = require("fs");
99588
- import_path12 = require("path");
100592
+ import_path13 = require("path");
99589
100593
  import_os3 = require("os");
99590
100594
  import_url4 = require("url");
99591
100595
  __filename4 = (0, import_url4.fileURLToPath)("file:///");
99592
- __dirname4 = (0, import_path12.dirname)(__filename4);
100596
+ __dirname4 = (0, import_path13.dirname)(__filename4);
99593
100597
  DEFAULT_TIMEOUT = 3e4;
99594
100598
  MAX_TIMEOUT = (() => {
99595
100599
  if (process.env.MCP_MAX_TIMEOUT) {
@@ -99603,7 +100607,7 @@ var init_config = __esm({
99603
100607
  // Example probe server configuration
99604
100608
  "probe-local": {
99605
100609
  command: "node",
99606
- args: [(0, import_path12.join)(__dirname4, "../../../examples/chat/mcpServer.js")],
100610
+ args: [(0, import_path13.join)(__dirname4, "../../../examples/chat/mcpServer.js")],
99607
100611
  transport: "stdio",
99608
100612
  enabled: false
99609
100613
  },
@@ -105186,7 +106190,7 @@ var require_compose_scalar = __commonJS({
105186
106190
  var resolveBlockScalar = require_resolve_block_scalar();
105187
106191
  var resolveFlowScalar = require_resolve_flow_scalar();
105188
106192
  function composeScalar(ctx, token, tagToken, onError) {
105189
- const { value, type, comment, range: range2 } = token.type === "block-scalar" ? resolveBlockScalar.resolveBlockScalar(ctx, token, onError) : resolveFlowScalar.resolveFlowScalar(token, ctx.options.strict, onError);
106193
+ const { value, type, comment, range: range3 } = token.type === "block-scalar" ? resolveBlockScalar.resolveBlockScalar(ctx, token, onError) : resolveFlowScalar.resolveFlowScalar(token, ctx.options.strict, onError);
105190
106194
  const tagName = tagToken ? ctx.directives.tagName(tagToken.source, (msg) => onError(tagToken, "TAG_RESOLVE_FAILED", msg)) : null;
105191
106195
  let tag2;
105192
106196
  if (ctx.options.stringKeys && ctx.atKey) {
@@ -105206,7 +106210,7 @@ var require_compose_scalar = __commonJS({
105206
106210
  onError(tagToken ?? token, "TAG_RESOLVE_FAILED", msg);
105207
106211
  scalar = new Scalar.Scalar(value);
105208
106212
  }
105209
- scalar.range = range2;
106213
+ scalar.range = range3;
105210
106214
  scalar.source = value;
105211
106215
  if (type)
105212
106216
  scalar.type = type;
@@ -107797,17 +108801,17 @@ async function parseSkillFile(skillFilePath, directoryName) {
107797
108801
  description,
107798
108802
  skillFilePath,
107799
108803
  directoryName,
107800
- sourceDir: (0, import_path13.dirname)(skillFilePath)
108804
+ sourceDir: (0, import_path14.dirname)(skillFilePath)
107801
108805
  },
107802
108806
  error: null
107803
108807
  };
107804
108808
  }
107805
- var import_promises2, import_path13, import_yaml, SKILL_NAME_REGEX, MAX_SKILL_NAME_LENGTH, MAX_DESCRIPTION_CHARS;
108809
+ var import_promises2, import_path14, import_yaml, SKILL_NAME_REGEX, MAX_SKILL_NAME_LENGTH, MAX_DESCRIPTION_CHARS;
107806
108810
  var init_parser7 = __esm({
107807
108811
  "src/agent/skills/parser.js"() {
107808
108812
  "use strict";
107809
108813
  import_promises2 = require("fs/promises");
107810
- import_path13 = require("path");
108814
+ import_path14 = require("path");
107811
108815
  import_yaml = __toESM(require_dist(), 1);
107812
108816
  SKILL_NAME_REGEX = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
107813
108817
  MAX_SKILL_NAME_LENGTH = 64;
@@ -107817,12 +108821,12 @@ var init_parser7 = __esm({
107817
108821
 
107818
108822
  // src/agent/skills/registry.js
107819
108823
  function isPathInside(basePath, targetPath) {
107820
- const base2 = (0, import_path14.resolve)(basePath);
107821
- const target = (0, import_path14.resolve)(targetPath);
107822
- const rel = (0, import_path14.relative)(base2, target);
108824
+ const base2 = (0, import_path15.resolve)(basePath);
108825
+ const target = (0, import_path15.resolve)(targetPath);
108826
+ const rel = (0, import_path15.relative)(base2, target);
107823
108827
  if (rel === "") return true;
107824
- if (rel === ".." || rel.startsWith(`..${import_path14.sep}`)) return false;
107825
- if ((0, import_path14.isAbsolute)(rel)) return false;
108828
+ if (rel === ".." || rel.startsWith(`..${import_path15.sep}`)) return false;
108829
+ if ((0, import_path15.isAbsolute)(rel)) return false;
107826
108830
  return true;
107827
108831
  }
107828
108832
  function isSafeEntryName(name14) {
@@ -107830,19 +108834,19 @@ function isSafeEntryName(name14) {
107830
108834
  if (name14.includes("\0")) return false;
107831
108835
  return !name14.includes("/") && !name14.includes("\\");
107832
108836
  }
107833
- var import_fs13, import_promises3, import_path14, DEFAULT_SKILL_DIRS, SKILL_FILE_NAME, SkillRegistry;
108837
+ var import_fs13, import_promises3, import_path15, DEFAULT_SKILL_DIRS, SKILL_FILE_NAME, SkillRegistry;
107834
108838
  var init_registry = __esm({
107835
108839
  "src/agent/skills/registry.js"() {
107836
108840
  "use strict";
107837
108841
  import_fs13 = require("fs");
107838
108842
  import_promises3 = require("fs/promises");
107839
- import_path14 = require("path");
108843
+ import_path15 = require("path");
107840
108844
  init_parser7();
107841
108845
  DEFAULT_SKILL_DIRS = [".claude/skills", ".codex/skills", "skills", ".skills"];
107842
108846
  SKILL_FILE_NAME = "SKILL.md";
107843
108847
  SkillRegistry = class {
107844
108848
  constructor({ repoRoot, skillDirs = DEFAULT_SKILL_DIRS, debug = false } = {}) {
107845
- this.repoRoot = repoRoot ? (0, import_path14.resolve)(repoRoot) : process.cwd();
108849
+ this.repoRoot = repoRoot ? (0, import_path15.resolve)(repoRoot) : process.cwd();
107846
108850
  this.repoRootReal = null;
107847
108851
  this.skillDirs = Array.isArray(skillDirs) && skillDirs.length > 0 ? skillDirs : DEFAULT_SKILL_DIRS;
107848
108852
  this.debug = debug;
@@ -107896,8 +108900,8 @@ var init_registry = __esm({
107896
108900
  }
107897
108901
  }
107898
108902
  async _resolveSkillDir(skillDir) {
107899
- const resolved = (0, import_path14.isAbsolute)(skillDir) ? (0, import_path14.resolve)(skillDir) : (0, import_path14.resolve)(this.repoRoot, skillDir);
107900
- const repoRoot = this.repoRootReal || (0, import_path14.resolve)(this.repoRoot);
108903
+ const resolved = (0, import_path15.isAbsolute)(skillDir) ? (0, import_path15.resolve)(skillDir) : (0, import_path15.resolve)(this.repoRoot, skillDir);
108904
+ const repoRoot = this.repoRootReal || (0, import_path15.resolve)(this.repoRoot);
107901
108905
  const resolvedReal = await this._resolveRealPath(resolved);
107902
108906
  if (!resolvedReal) return null;
107903
108907
  if (!isPathInside(repoRoot, resolvedReal)) {
@@ -107928,8 +108932,8 @@ var init_registry = __esm({
107928
108932
  }
107929
108933
  continue;
107930
108934
  }
107931
- const skillFolder = (0, import_path14.join)(dirPath, entry.name);
107932
- const skillFilePath = (0, import_path14.join)(skillFolder, SKILL_FILE_NAME);
108935
+ const skillFolder = (0, import_path15.join)(dirPath, entry.name);
108936
+ const skillFilePath = (0, import_path15.join)(skillFolder, SKILL_FILE_NAME);
107933
108937
  let skillStat;
107934
108938
  try {
107935
108939
  skillStat = await (0, import_promises3.lstat)(skillFilePath);
@@ -108087,7 +109091,7 @@ function extractErrorInfo(error2) {
108087
109091
  };
108088
109092
  }
108089
109093
  function sleep(ms) {
108090
- return new Promise((resolve7) => setTimeout(resolve7, ms));
109094
+ return new Promise((resolve8) => setTimeout(resolve8, ms));
108091
109095
  }
108092
109096
  var DEFAULT_RETRYABLE_ERRORS, RetryManager;
108093
109097
  var init_RetryManager = __esm({
@@ -108867,9 +109871,9 @@ async function truncateIfNeeded(content, tokenCounter, sessionId, maxTokens) {
108867
109871
  let tempFilePath = null;
108868
109872
  let fileError = null;
108869
109873
  try {
108870
- const tempDir = (0, import_path15.join)((0, import_os4.tmpdir)(), "probe-output");
109874
+ const tempDir = (0, import_path16.join)((0, import_os4.tmpdir)(), "probe-output");
108871
109875
  await (0, import_promises4.mkdir)(tempDir, { recursive: true });
108872
- tempFilePath = (0, import_path15.join)(tempDir, `tool-output-${sessionId || "unknown"}-${(0, import_crypto5.randomUUID)()}.txt`);
109876
+ tempFilePath = (0, import_path16.join)(tempDir, `tool-output-${sessionId || "unknown"}-${(0, import_crypto6.randomUUID)()}.txt`);
108873
109877
  await (0, import_promises4.writeFile)(tempFilePath, content, "utf8");
108874
109878
  } catch (err) {
108875
109879
  fileError = err.message || "Unknown file system error";
@@ -108917,14 +109921,14 @@ ${truncatedBody}
108917
109921
  error: fileError || void 0
108918
109922
  };
108919
109923
  }
108920
- var import_promises4, import_os4, import_path15, import_crypto5, DEFAULT_MAX_OUTPUT_TOKENS, CHARS_PER_TOKEN2, TAIL_TOKENS, MIN_LIMIT_FOR_TAIL;
109924
+ var import_promises4, import_os4, import_path16, import_crypto6, DEFAULT_MAX_OUTPUT_TOKENS, CHARS_PER_TOKEN2, TAIL_TOKENS, MIN_LIMIT_FOR_TAIL;
108921
109925
  var init_outputTruncator = __esm({
108922
109926
  "src/agent/outputTruncator.js"() {
108923
109927
  "use strict";
108924
109928
  import_promises4 = require("fs/promises");
108925
109929
  import_os4 = require("os");
108926
- import_path15 = require("path");
108927
- import_crypto5 = require("crypto");
109930
+ import_path16 = require("path");
109931
+ import_crypto6 = require("crypto");
108928
109932
  DEFAULT_MAX_OUTPUT_TOKENS = 2e4;
108929
109933
  CHARS_PER_TOKEN2 = 4;
108930
109934
  TAIL_TOKENS = 1e3;
@@ -108933,13 +109937,13 @@ var init_outputTruncator = __esm({
108933
109937
  });
108934
109938
 
108935
109939
  // src/agent/mcp/built-in-server.js
108936
- var import_http, import_events2, import_crypto6, import_server, import_sse2, import_streamableHttp, import_types3, InMemoryEventStore, BuiltInMCPServer;
109940
+ var import_http, import_events2, import_crypto7, import_server, import_sse2, import_streamableHttp, import_types3, InMemoryEventStore, BuiltInMCPServer;
108937
109941
  var init_built_in_server = __esm({
108938
109942
  "src/agent/mcp/built-in-server.js"() {
108939
109943
  "use strict";
108940
109944
  import_http = require("http");
108941
109945
  import_events2 = require("events");
108942
- import_crypto6 = require("crypto");
109946
+ import_crypto7 = require("crypto");
108943
109947
  import_server = require("@modelcontextprotocol/sdk/server/index.js");
108944
109948
  import_sse2 = require("@modelcontextprotocol/sdk/server/sse.js");
108945
109949
  import_streamableHttp = require("@modelcontextprotocol/sdk/server/streamableHttp.js");
@@ -109015,7 +110019,7 @@ var init_built_in_server = __esm({
109015
110019
  }
109016
110020
  });
109017
110021
  this.registerHandlers();
109018
- return new Promise((resolve7, reject2) => {
110022
+ return new Promise((resolve8, reject2) => {
109019
110023
  this.httpServer.listen(this.port, this.host, async () => {
109020
110024
  const address = this.httpServer.address();
109021
110025
  this.port = address.port;
@@ -109025,7 +110029,7 @@ var init_built_in_server = __esm({
109025
110029
  console.log(`[MCP] Messages endpoint: http://${this.host}:${this.port}/messages`);
109026
110030
  }
109027
110031
  this.emit("ready", { host: this.host, port: this.port });
109028
- resolve7({ host: this.host, port: this.port });
110032
+ resolve8({ host: this.host, port: this.port });
109029
110033
  });
109030
110034
  this.httpServer.on("error", reject2);
109031
110035
  });
@@ -109183,7 +110187,7 @@ var init_built_in_server = __esm({
109183
110187
  }
109184
110188
  const eventStore = new InMemoryEventStore();
109185
110189
  transport = new import_streamableHttp.StreamableHTTPServerTransport({
109186
- sessionIdGenerator: () => (0, import_crypto6.randomUUID)(),
110190
+ sessionIdGenerator: () => (0, import_crypto7.randomUUID)(),
109187
110191
  eventStore,
109188
110192
  // Enable resumability
109189
110193
  onsessioninitialized: (newSessionId) => {
@@ -109244,7 +110248,7 @@ var init_built_in_server = __esm({
109244
110248
  * Parse request body as JSON
109245
110249
  */
109246
110250
  async parseRequestBody(req) {
109247
- return new Promise((resolve7, reject2) => {
110251
+ return new Promise((resolve8, reject2) => {
109248
110252
  let body = "";
109249
110253
  req.on("data", (chunk) => {
109250
110254
  body += chunk.toString();
@@ -109252,7 +110256,7 @@ var init_built_in_server = __esm({
109252
110256
  req.on("end", () => {
109253
110257
  try {
109254
110258
  const parsed = body ? JSON.parse(body) : null;
109255
- resolve7(parsed);
110259
+ resolve8(parsed);
109256
110260
  } catch (error2) {
109257
110261
  reject2(error2);
109258
110262
  }
@@ -109559,12 +110563,12 @@ data: ${JSON.stringify(data3)}
109559
110563
  }
109560
110564
  this.connections.clear();
109561
110565
  if (this.httpServer) {
109562
- return new Promise((resolve7) => {
110566
+ return new Promise((resolve8) => {
109563
110567
  this.httpServer.close(() => {
109564
110568
  if (this.debug) {
109565
110569
  console.log("[MCP] Built-in server stopped");
109566
110570
  }
109567
- resolve7();
110571
+ resolve8();
109568
110572
  });
109569
110573
  });
109570
110574
  }
@@ -109646,7 +110650,7 @@ __export(enhanced_claude_code_exports, {
109646
110650
  async function createEnhancedClaudeCLIEngine(options = {}) {
109647
110651
  const { agent, systemPrompt, customPrompt, debug, sessionId, allowedTools, timeout = 12e4 } = options;
109648
110652
  const session = new Session(
109649
- sessionId || (0, import_crypto7.randomBytes)(8).toString("hex"),
110653
+ sessionId || (0, import_crypto8.randomBytes)(8).toString("hex"),
109650
110654
  debug
109651
110655
  );
109652
110656
  let mcpServer = null;
@@ -109663,12 +110667,12 @@ async function createEnhancedClaudeCLIEngine(options = {}) {
109663
110667
  console.log("[DEBUG] Built-in MCP server started");
109664
110668
  console.log("[DEBUG] MCP URL:", `http://${host}:${port}/mcp`);
109665
110669
  }
109666
- mcpConfigPath = import_path16.default.join(import_os5.default.tmpdir(), `probe-mcp-${session.id}.json`);
110670
+ mcpConfigPath = import_path17.default.join(import_os5.default.tmpdir(), `probe-mcp-${session.id}.json`);
109667
110671
  const mcpConfig = {
109668
110672
  mcpServers: {
109669
110673
  probe: {
109670
110674
  command: "node",
109671
- args: [import_path16.default.join(process.cwd(), "mcp-probe-server.js")],
110675
+ args: [import_path17.default.join(process.cwd(), "mcp-probe-server.js")],
109672
110676
  env: {
109673
110677
  PROBE_WORKSPACE: process.cwd(),
109674
110678
  DEBUG: debug ? "true" : "false"
@@ -109893,8 +110897,8 @@ ${opts.schema}`;
109893
110897
  break;
109894
110898
  }
109895
110899
  } else if (!processEnded) {
109896
- await new Promise((resolve7) => {
109897
- resolver = resolve7;
110900
+ await new Promise((resolve8) => {
110901
+ resolver = resolve8;
109898
110902
  });
109899
110903
  }
109900
110904
  }
@@ -110093,14 +111097,14 @@ function combinePrompts(systemPrompt, customPrompt, agent) {
110093
111097
  }
110094
111098
  return systemPrompt || "";
110095
111099
  }
110096
- var import_child_process9, import_crypto7, import_promises5, import_path16, import_os5, import_events3;
111100
+ var import_child_process9, import_crypto8, import_promises5, import_path17, import_os5, import_events3;
110097
111101
  var init_enhanced_claude_code = __esm({
110098
111102
  "src/agent/engines/enhanced-claude-code.js"() {
110099
111103
  "use strict";
110100
111104
  import_child_process9 = require("child_process");
110101
- import_crypto7 = require("crypto");
111105
+ import_crypto8 = require("crypto");
110102
111106
  import_promises5 = __toESM(require("fs/promises"), 1);
110103
- import_path16 = __toESM(require("path"), 1);
111107
+ import_path17 = __toESM(require("path"), 1);
110104
111108
  import_os5 = __toESM(require("os"), 1);
110105
111109
  import_events3 = require("events");
110106
111110
  init_built_in_server();
@@ -110116,7 +111120,7 @@ __export(codex_exports, {
110116
111120
  async function createCodexEngine(options = {}) {
110117
111121
  const { agent, systemPrompt, customPrompt, debug, sessionId, allowedTools, model } = options;
110118
111122
  const session = new Session(
110119
- sessionId || (0, import_crypto8.randomBytes)(8).toString("hex"),
111123
+ sessionId || (0, import_crypto9.randomBytes)(8).toString("hex"),
110120
111124
  debug
110121
111125
  );
110122
111126
  let mcpServer = null;
@@ -110158,12 +111162,12 @@ async function createCodexEngine(options = {}) {
110158
111162
  }
110159
111163
  }
110160
111164
  if (message.id !== void 0 && pendingRequests.has(message.id)) {
110161
- const { resolve: resolve7, reject: reject2 } = pendingRequests.get(message.id);
111165
+ const { resolve: resolve8, reject: reject2 } = pendingRequests.get(message.id);
110162
111166
  pendingRequests.delete(message.id);
110163
111167
  if (message.error) {
110164
111168
  reject2(new Error(message.error.message || JSON.stringify(message.error)));
110165
111169
  } else {
110166
- resolve7(message.result);
111170
+ resolve8(message.result);
110167
111171
  }
110168
111172
  }
110169
111173
  if (message.method === "codex/event" && message.params) {
@@ -110184,7 +111188,7 @@ async function createCodexEngine(options = {}) {
110184
111188
  });
110185
111189
  }
110186
111190
  function sendRequest(method, params = {}) {
110187
- return new Promise((resolve7, reject2) => {
111191
+ return new Promise((resolve8, reject2) => {
110188
111192
  const id = ++requestId;
110189
111193
  const request = {
110190
111194
  jsonrpc: "2.0",
@@ -110192,7 +111196,7 @@ async function createCodexEngine(options = {}) {
110192
111196
  method,
110193
111197
  params
110194
111198
  };
110195
- pendingRequests.set(id, { resolve: resolve7, reject: reject2 });
111199
+ pendingRequests.set(id, { resolve: resolve8, reject: reject2 });
110196
111200
  setTimeout(() => {
110197
111201
  if (pendingRequests.has(id)) {
110198
111202
  pendingRequests.delete(id);
@@ -110255,7 +111259,7 @@ ${prompt}`;
110255
111259
  const reqId = requestId + 1;
110256
111260
  let fullResponse = "";
110257
111261
  let gotSessionId = false;
110258
- const eventPromise = new Promise((resolve7) => {
111262
+ const eventPromise = new Promise((resolve8) => {
110259
111263
  eventHandlers.set(reqId, (eventParams) => {
110260
111264
  const msg = eventParams.msg;
110261
111265
  if (msg.type === "session_configured" && msg.session_id && !gotSessionId) {
@@ -110275,7 +111279,7 @@ ${prompt}`;
110275
111279
  });
110276
111280
  setTimeout(() => {
110277
111281
  eventHandlers.delete(reqId);
110278
- resolve7();
111282
+ resolve8();
110279
111283
  }, 6e5);
110280
111284
  });
110281
111285
  const resultPromise = sendRequest("tools/call", {
@@ -110371,12 +111375,12 @@ function combinePrompts2(systemPrompt, customPrompt, agent) {
110371
111375
  }
110372
111376
  return systemPrompt || "";
110373
111377
  }
110374
- var import_child_process10, import_crypto8, import_readline;
111378
+ var import_child_process10, import_crypto9, import_readline;
110375
111379
  var init_codex = __esm({
110376
111380
  "src/agent/engines/codex.js"() {
110377
111381
  "use strict";
110378
111382
  import_child_process10 = require("child_process");
110379
- import_crypto8 = require("crypto");
111383
+ import_crypto9 = require("crypto");
110380
111384
  import_readline = require("readline");
110381
111385
  init_built_in_server();
110382
111386
  init_Session();
@@ -110482,7 +111486,7 @@ Your content here
110482
111486
 
110483
111487
  Do NOT wrap in other tags like <api_call>, <tool_name>, <function>, etc.`;
110484
111488
  }
110485
- var import_dotenv2, import_anthropic2, import_openai2, import_google2, import_ai6, import_crypto9, import_events4, import_fs14, import_promises6, import_path17, ENGINE_ACTIVITY_TIMEOUT_DEFAULT, ENGINE_ACTIVITY_TIMEOUT_MIN, ENGINE_ACTIVITY_TIMEOUT_MAX, MAX_TOOL_ITERATIONS, MAX_HISTORY_MESSAGES, MAX_IMAGE_FILE_SIZE, ProbeAgent;
111489
+ var import_dotenv2, import_anthropic2, import_openai2, import_google2, import_ai6, import_crypto10, import_events4, import_fs14, import_promises6, import_path18, ENGINE_ACTIVITY_TIMEOUT_DEFAULT, ENGINE_ACTIVITY_TIMEOUT_MIN, ENGINE_ACTIVITY_TIMEOUT_MAX, MAX_TOOL_ITERATIONS, MAX_HISTORY_MESSAGES, MAX_IMAGE_FILE_SIZE, ProbeAgent;
110486
111490
  var init_ProbeAgent = __esm({
110487
111491
  "src/agent/ProbeAgent.js"() {
110488
111492
  import_dotenv2 = __toESM(require_main(), 1);
@@ -110491,17 +111495,18 @@ var init_ProbeAgent = __esm({
110491
111495
  import_google2 = require("@ai-sdk/google");
110492
111496
  init_dist3();
110493
111497
  import_ai6 = require("ai");
110494
- import_crypto9 = require("crypto");
111498
+ import_crypto10 = require("crypto");
110495
111499
  import_events4 = require("events");
110496
111500
  import_fs14 = require("fs");
110497
111501
  import_promises6 = require("fs/promises");
110498
- import_path17 = require("path");
111502
+ import_path18 = require("path");
110499
111503
  init_tokenCounter();
110500
111504
  init_InMemoryStorageAdapter();
110501
111505
  init_HookManager();
110502
111506
  init_imageConfig();
110503
111507
  init_tools2();
110504
111508
  init_common2();
111509
+ init_fileTracker();
110505
111510
  init_probeTool();
110506
111511
  init_mockProvider();
110507
111512
  init_index();
@@ -110543,7 +111548,7 @@ var init_ProbeAgent = __esm({
110543
111548
  * @param {string} [options.customPrompt] - Custom prompt to replace the default system message
110544
111549
  * @param {string} [options.systemPrompt] - Alias for customPrompt; takes precedence when both are provided
110545
111550
  * @param {string} [options.promptType] - Predefined prompt type (code-explorer, code-searcher, architect, code-review, support)
110546
- * @param {boolean} [options.allowEdit=false] - Allow the use of the 'implement' tool
111551
+ * @param {boolean} [options.allowEdit=false] - Allow the use of the 'edit' and 'create' tools
110547
111552
  * @param {boolean} [options.enableDelegate=false] - Enable the delegate tool for task distribution to subagents
110548
111553
  * @param {boolean} [options.enableExecutePlan=false] - Enable the execute_plan DSL orchestration tool
110549
111554
  * @param {string} [options.architectureFileName] - Architecture context filename to embed from repo root (defaults to AGENTS.md with CLAUDE.md fallback; ARCHITECTURE.md is always included when present)
@@ -110588,10 +111593,11 @@ var init_ProbeAgent = __esm({
110588
111593
  * @param {number} [options.maxOperationTimeout] - Maximum timeout in ms for the entire operation including all retries and fallbacks (default: 300000 or MAX_OPERATION_TIMEOUT env var). This is the absolute maximum time for streamTextWithRetryAndFallback.
110589
111594
  */
110590
111595
  constructor(options = {}) {
110591
- this.sessionId = options.sessionId || (0, import_crypto9.randomUUID)();
111596
+ this.sessionId = options.sessionId || (0, import_crypto10.randomUUID)();
110592
111597
  this.customPrompt = options.systemPrompt || options.customPrompt || null;
110593
111598
  this.promptType = options.promptType || "code-explorer";
110594
111599
  this.allowEdit = !!options.allowEdit;
111600
+ this.hashLines = options.hashLines !== void 0 ? !!options.hashLines : this.allowEdit;
110595
111601
  this.enableDelegate = !!options.enableDelegate;
110596
111602
  this.enableExecutePlan = !!options.enableExecutePlan;
110597
111603
  this.debug = options.debug || process.env.DEBUG === "1";
@@ -110653,7 +111659,8 @@ var init_ProbeAgent = __esm({
110653
111659
  if (this.debug) {
110654
111660
  console.log(`[DEBUG] Generated session ID for agent: ${this.sessionId}`);
110655
111661
  console.log(`[DEBUG] Maximum tool iterations configured: ${MAX_TOOL_ITERATIONS}`);
110656
- console.log(`[DEBUG] Allow Edit (implement tool): ${this.allowEdit}`);
111662
+ console.log(`[DEBUG] Allow Edit: ${this.allowEdit}`);
111663
+ console.log(`[DEBUG] Hash Lines: ${this.hashLines}`);
110657
111664
  console.log(`[DEBUG] Search delegation enabled: ${this.searchDelegate}`);
110658
111665
  console.log(`[DEBUG] Workspace root: ${this.workspaceRoot}`);
110659
111666
  console.log(`[DEBUG] Working directory (cwd): ${this.cwd}`);
@@ -111038,9 +112045,12 @@ var init_ProbeAgent = __esm({
111038
112045
  cwd: this.cwd,
111039
112046
  workspaceRoot: this.workspaceRoot,
111040
112047
  allowedFolders: this.allowedFolders,
112048
+ // File state tracking for safe multi-edit workflows (only when editing is enabled)
112049
+ fileTracker: this.allowEdit ? new FileTracker({ debug: this.debug }) : null,
111041
112050
  outline: this.outline,
111042
112051
  searchDelegate: this.searchDelegate,
111043
112052
  allowEdit: this.allowEdit,
112053
+ hashLines: this.hashLines,
111044
112054
  enableDelegate: this.enableDelegate,
111045
112055
  enableExecutePlan: this.enableExecutePlan,
111046
112056
  enableBash: this.enableBash,
@@ -111111,7 +112121,7 @@ var init_ProbeAgent = __esm({
111111
112121
  if (!imagePath) {
111112
112122
  throw new Error("Image path is required");
111113
112123
  }
111114
- const filename = (0, import_path17.basename)(imagePath);
112124
+ const filename = (0, import_path18.basename)(imagePath);
111115
112125
  const extension = filename.toLowerCase().split(".").pop();
111116
112126
  if (!extension || !SUPPORTED_IMAGE_EXTENSIONS.includes(extension)) {
111117
112127
  throw new Error(`Invalid or unsupported image extension: ${extension}. Supported formats: ${SUPPORTED_IMAGE_EXTENSIONS.join(", ")}`);
@@ -111825,7 +112835,7 @@ var init_ProbeAgent = __esm({
111825
112835
  let resolvedPath2 = imagePath;
111826
112836
  if (!imagePath.includes("/") && !imagePath.includes("\\")) {
111827
112837
  for (const dir of listFilesDirectories) {
111828
- const potentialPath = (0, import_path17.resolve)(dir, imagePath);
112838
+ const potentialPath = (0, import_path18.resolve)(dir, imagePath);
111829
112839
  const loaded = await this.loadImageIfValid(potentialPath);
111830
112840
  if (loaded) {
111831
112841
  if (this.debug) {
@@ -111850,7 +112860,7 @@ var init_ProbeAgent = __esm({
111850
112860
  let match2;
111851
112861
  while ((match2 = fileHeaderPattern.exec(content)) !== null) {
111852
112862
  const filePath = match2[1].trim();
111853
- const dir = (0, import_path17.dirname)(filePath);
112863
+ const dir = (0, import_path18.dirname)(filePath);
111854
112864
  if (dir && dir !== ".") {
111855
112865
  directories.push(dir);
111856
112866
  if (this.debug) {
@@ -111895,17 +112905,17 @@ var init_ProbeAgent = __esm({
111895
112905
  const allowedDirs = this.allowedFolders && this.allowedFolders.length > 0 ? this.allowedFolders : [process.cwd()];
111896
112906
  let absolutePath;
111897
112907
  let isPathAllowed2 = false;
111898
- if ((0, import_path17.isAbsolute)(imagePath)) {
111899
- absolutePath = safeRealpath((0, import_path17.resolve)(imagePath));
112908
+ if ((0, import_path18.isAbsolute)(imagePath)) {
112909
+ absolutePath = safeRealpath((0, import_path18.resolve)(imagePath));
111900
112910
  isPathAllowed2 = allowedDirs.some((dir) => {
111901
112911
  const resolvedDir = safeRealpath(dir);
111902
- return absolutePath === resolvedDir || absolutePath.startsWith(resolvedDir + import_path17.sep);
112912
+ return absolutePath === resolvedDir || absolutePath.startsWith(resolvedDir + import_path18.sep);
111903
112913
  });
111904
112914
  } else {
111905
112915
  for (const dir of allowedDirs) {
111906
112916
  const resolvedDir = safeRealpath(dir);
111907
- const resolvedPath2 = safeRealpath((0, import_path17.resolve)(dir, imagePath));
111908
- if (resolvedPath2 === resolvedDir || resolvedPath2.startsWith(resolvedDir + import_path17.sep)) {
112917
+ const resolvedPath2 = safeRealpath((0, import_path18.resolve)(dir, imagePath));
112918
+ if (resolvedPath2 === resolvedDir || resolvedPath2.startsWith(resolvedDir + import_path18.sep)) {
111909
112919
  absolutePath = resolvedPath2;
111910
112920
  isPathAllowed2 = true;
111911
112921
  break;
@@ -112093,8 +113103,8 @@ var init_ProbeAgent = __esm({
112093
113103
  const hasConfiguredName = !!configuredName;
112094
113104
  let guidanceCandidates = [];
112095
113105
  if (hasConfiguredName) {
112096
- const targetName = (0, import_path17.basename)(configuredName);
112097
- if (configuredName !== targetName || configuredName.includes("/") || configuredName.includes("\\") || configuredName.includes("..") || (0, import_path17.isAbsolute)(configuredName)) {
113106
+ const targetName = (0, import_path18.basename)(configuredName);
113107
+ if (configuredName !== targetName || configuredName.includes("/") || configuredName.includes("\\") || configuredName.includes("..") || (0, import_path18.isAbsolute)(configuredName)) {
112098
113108
  console.warn(`[WARN] Invalid architectureFileName (must be a simple filename): ${configuredName}`);
112099
113109
  } else if (targetName) {
112100
113110
  const targetLower = targetName.toLowerCase();
@@ -112161,7 +113171,7 @@ var init_ProbeAgent = __esm({
112161
113171
  pushEntry(architectureMatch);
112162
113172
  const contexts = [];
112163
113173
  for (const entry of uniqueEntries) {
112164
- const filePath = (0, import_path17.resolve)(rootDirectory, entry.name);
113174
+ const filePath = (0, import_path18.resolve)(rootDirectory, entry.name);
112165
113175
  try {
112166
113176
  const content = await (0, import_promises6.readFile)(filePath, "utf8");
112167
113177
  let kind = "other";
@@ -112226,10 +113236,10 @@ ${this.architectureContext.content}
112226
113236
  }
112227
113237
  _getSkillsRepoRoot() {
112228
113238
  if (this.workspaceRoot) {
112229
- return (0, import_path17.resolve)(this.workspaceRoot);
113239
+ return (0, import_path18.resolve)(this.workspaceRoot);
112230
113240
  }
112231
113241
  if (this.allowedFolders && this.allowedFolders.length > 0) {
112232
- return (0, import_path17.resolve)(this.allowedFolders[0]);
113242
+ return (0, import_path18.resolve)(this.allowedFolders[0]);
112233
113243
  }
112234
113244
  return process.cwd();
112235
113245
  }
@@ -112418,10 +113428,6 @@ Workspace: ${this.allowedFolders.join(", ")}`;
112418
113428
  }
112419
113429
  if (isToolAllowed("readImage")) {
112420
113430
  toolDefinitions += `${readImageToolDefinition}
112421
- `;
112422
- }
112423
- if (this.allowEdit && isToolAllowed("implement")) {
112424
- toolDefinitions += `${implementToolDefinition}
112425
113431
  `;
112426
113432
  }
112427
113433
  if (this.allowEdit && isToolAllowed("edit")) {
@@ -112503,7 +113509,7 @@ The configuration is loaded from src/config.js lines 15-25 which contains the da
112503
113509
  availableToolsList += "- query: Search code using structural AST patterns.\n";
112504
113510
  }
112505
113511
  if (isToolAllowed("extract")) {
112506
- availableToolsList += "- extract: Extract specific code blocks or lines from files.\n";
113512
+ availableToolsList += '- extract: Extract specific code blocks or lines from files. Use with symbol targets (e.g. "file.js#funcName") to get line numbers for line-targeted editing.\n';
112507
113513
  }
112508
113514
  if (isToolAllowed("listFiles")) {
112509
113515
  availableToolsList += "- listFiles: List files and directories in a specified location.\n";
@@ -112520,11 +113526,8 @@ The configuration is loaded from src/config.js lines 15-25 which contains the da
112520
113526
  if (isToolAllowed("readImage")) {
112521
113527
  availableToolsList += "- readImage: Read and load an image file for AI analysis.\n";
112522
113528
  }
112523
- if (this.allowEdit && isToolAllowed("implement")) {
112524
- availableToolsList += "- implement: Implement a feature or fix a bug using aider.\n";
112525
- }
112526
113529
  if (this.allowEdit && isToolAllowed("edit")) {
112527
- availableToolsList += "- edit: Edit files using exact string replacement.\n";
113530
+ availableToolsList += "- edit: Edit files using text replacement, AST-aware symbol operations, or line-targeted editing.\n";
112528
113531
  }
112529
113532
  if (this.allowEdit && isToolAllowed("create")) {
112530
113533
  availableToolsList += "- create: Create new files with specified content.\n";
@@ -112612,8 +113615,14 @@ Follow these instructions carefully:
112612
113615
  8. Once the task is fully completed, use the '<attempt_completion>' tool to provide the final result. This is the ONLY way to signal completion.
112613
113616
  9. Prefer concise and focused search queries. Use specific keywords and phrases to narrow down results.${this.allowEdit ? `
112614
113617
  10. When modifying files, choose the appropriate tool:
112615
- - Use 'edit' for precise changes to existing files (requires exact string match)
112616
- - Use 'create' for new files or complete file rewrites` : ""}
113618
+ - Use 'edit' for all code modifications:
113619
+ * For small changes (a line or a few lines), use old_string + new_string \u2014 copy old_string verbatim from the file.
113620
+ * For rewriting entire functions/classes/methods, use the symbol parameter instead (no exact text matching needed).
113621
+ * For editing specific lines from search/extract output, use start_line (and optionally end_line) with the line numbers shown in the output.${this.hashLines ? ' Line references include content hashes (e.g. "42:ab") for integrity verification.' : ""}
113622
+ * For editing inside large functions: first use extract with the symbol target (e.g. "file.js#myFunction") to see the function with line numbers${this.hashLines ? " and hashes" : ""}, then use start_line/end_line to surgically edit specific lines within it.
113623
+ - Use 'create' for new files or complete file rewrites.
113624
+ - If an edit fails, read the error message \u2014 it tells you exactly how to fix the call and retry.
113625
+ - The system tracks which files you've seen via search/extract. If you try to edit a file you haven't read, or one that changed since you last read it, the edit will fail with instructions to re-read first. Always use extract before editing to ensure you have current file content.` : ""}
112617
113626
  </instructions>
112618
113627
  `;
112619
113628
  let systemMessage = "";
@@ -113113,8 +114122,11 @@ You are working with a workspace. Available paths: ${workspaceDesc}
113113
114122
  if (this.enableSkills && this.allowedTools.isEnabled("useSkill")) validTools.push("useSkill");
113114
114123
  if (this.allowedTools.isEnabled("readImage")) validTools.push("readImage");
113115
114124
  validTools.push("attempt_completion");
113116
- if (this.allowEdit && this.allowedTools.isEnabled("implement")) {
113117
- validTools.push("implement", "edit", "create");
114125
+ if (this.allowEdit && this.allowedTools.isEnabled("edit")) {
114126
+ validTools.push("edit");
114127
+ }
114128
+ if (this.allowEdit && this.allowedTools.isEnabled("create")) {
114129
+ validTools.push("create");
113118
114130
  }
113119
114131
  if (this.enableBash && this.allowedTools.isEnabled("bash")) {
113120
114132
  validTools.push("bash");
@@ -113336,10 +114348,10 @@ ${errorXml}
113336
114348
  try {
113337
114349
  let resolvedWorkingDirectory = this.workspaceRoot || this.cwd || this.allowedFolders && this.allowedFolders[0] || process.cwd();
113338
114350
  if (params.workingDirectory) {
113339
- const requestedDir = safeRealpath((0, import_path17.isAbsolute)(params.workingDirectory) ? (0, import_path17.resolve)(params.workingDirectory) : (0, import_path17.resolve)(resolvedWorkingDirectory, params.workingDirectory));
114351
+ const requestedDir = safeRealpath((0, import_path18.isAbsolute)(params.workingDirectory) ? (0, import_path18.resolve)(params.workingDirectory) : (0, import_path18.resolve)(resolvedWorkingDirectory, params.workingDirectory));
113340
114352
  const isWithinAllowed = !this.allowedFolders || this.allowedFolders.length === 0 || this.allowedFolders.some((folder) => {
113341
114353
  const resolvedFolder = safeRealpath(folder);
113342
- return requestedDir === resolvedFolder || requestedDir.startsWith(resolvedFolder + import_path17.sep);
114354
+ return requestedDir === resolvedFolder || requestedDir.startsWith(resolvedFolder + import_path18.sep);
113343
114355
  });
113344
114356
  if (isWithinAllowed) {
113345
114357
  resolvedWorkingDirectory = requestedDir;
@@ -113407,6 +114419,8 @@ ${errorXml}
113407
114419
  // Inherit bash enablement
113408
114420
  bashConfig: this.bashConfig,
113409
114421
  // Inherit bash configuration
114422
+ allowEdit: this.allowEdit,
114423
+ // Inherit edit/create permission
113410
114424
  allowedTools: allowedToolsForDelegate,
113411
114425
  // Inherit allowed tools from parent
113412
114426
  debug: this.debug,
@@ -113479,7 +114493,7 @@ ${errorXml}
113479
114493
  currentMessages.push({ role: "assistant", content: assistantResponseContent });
113480
114494
  let toolResultContent = typeof toolResult === "string" ? toolResult : JSON.stringify(toolResult, null, 2);
113481
114495
  if (this.workspaceRoot && toolResultContent) {
113482
- const wsPrefix = this.workspaceRoot.endsWith(import_path17.sep) ? this.workspaceRoot : this.workspaceRoot + import_path17.sep;
114496
+ const wsPrefix = this.workspaceRoot.endsWith(import_path18.sep) ? this.workspaceRoot : this.workspaceRoot + import_path18.sep;
113483
114497
  toolResultContent = toolResultContent.split(wsPrefix).join("");
113484
114498
  }
113485
114499
  const { cleanedContent, extractedBlocks } = extractRawOutputBlocks(toolResultContent);
@@ -114329,7 +115343,7 @@ Convert your previous response content into actual JSON data that follows this s
114329
115343
  */
114330
115344
  clone(options = {}) {
114331
115345
  const {
114332
- sessionId = (0, import_crypto9.randomUUID)(),
115346
+ sessionId = (0, import_crypto10.randomUUID)(),
114333
115347
  stripInternalMessages = true,
114334
115348
  keepSystemMessage = true,
114335
115349
  deepCopy = true,