@morphllm/morphsdk 0.2.145 → 0.2.146

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 (205) hide show
  1. package/dist/{chunk-HBIW2XV2.js → chunk-4PBUB77N.js} +2 -2
  2. package/dist/{chunk-SUE4GYA2.js → chunk-BDHKL3MT.js} +2 -2
  3. package/dist/{chunk-S54SPKX3.js → chunk-BIQ7234U.js} +2 -2
  4. package/dist/{chunk-I3J46TSB.js → chunk-DKODF3YG.js} +4 -5
  5. package/dist/chunk-DKODF3YG.js.map +1 -0
  6. package/dist/{chunk-MRPASJBX.js → chunk-E45FW5EK.js} +2 -2
  7. package/dist/{chunk-BXRJYLRS.js → chunk-E4YKEKGW.js} +2 -2
  8. package/dist/{chunk-G23BI5CQ.js → chunk-EU7OLX4Z.js} +2 -2
  9. package/dist/chunk-EUHNJMWL.js +409 -0
  10. package/dist/chunk-EUHNJMWL.js.map +1 -0
  11. package/dist/{chunk-HE7K2QNQ.js → chunk-FBOJJ3UY.js} +17 -17
  12. package/dist/{chunk-HYRHI2UL.js → chunk-FIVYDIHX.js} +1 -1
  13. package/dist/{chunk-GXM3G7Z4.js → chunk-FYO46OT6.js} +2 -2
  14. package/dist/{chunk-GHPQYSSF.js → chunk-GJUB3ECP.js} +2 -2
  15. package/dist/{chunk-4Y2NM6JD.js → chunk-HZOTLGJH.js} +2 -42
  16. package/dist/chunk-HZOTLGJH.js.map +1 -0
  17. package/dist/{chunk-MTJ3PR4M.js → chunk-I7SFRYTX.js} +2 -2
  18. package/dist/{chunk-PX7ODEML.js → chunk-J2HIK4GB.js} +2 -2
  19. package/dist/{chunk-RZXS4ADX.js → chunk-JSWNBCGS.js} +2 -2
  20. package/dist/{chunk-GXCWKYGU.js → chunk-KYKRRF7E.js} +2 -2
  21. package/dist/{chunk-N7TTZIBK.js → chunk-MMBQKN4G.js} +2 -2
  22. package/dist/{chunk-B3AKP3RA.js → chunk-NF2QWJDY.js} +2 -31
  23. package/dist/chunk-NF2QWJDY.js.map +1 -0
  24. package/dist/{chunk-JMUAQQJU.js → chunk-NKUSUSVI.js} +3 -3
  25. package/dist/{chunk-VRV5UYTN.js → chunk-OV57JBMB.js} +2 -2
  26. package/dist/{chunk-EPIOAODF.js → chunk-Q36MNOFA.js} +2 -2
  27. package/dist/{chunk-JRBU4UNP.js → chunk-QRSWXP4K.js} +2 -2
  28. package/dist/{chunk-KELRCMA6.js → chunk-SJYAKVSS.js} +2 -2
  29. package/dist/{chunk-KELRCMA6.js.map → chunk-SJYAKVSS.js.map} +1 -1
  30. package/dist/{chunk-IRWHN55G.js → chunk-T564HFSH.js} +1 -1
  31. package/dist/{chunk-6CFKWZK3.js → chunk-UVNENJ6H.js} +3 -3
  32. package/dist/{chunk-5FCXLQJU.js → chunk-UYPWKQKV.js} +2 -2
  33. package/dist/{chunk-BAF33L6C.js → chunk-V73GO5AJ.js} +2 -2
  34. package/dist/chunk-VCKJ22DX.js +131 -0
  35. package/dist/chunk-VCKJ22DX.js.map +1 -0
  36. package/dist/{chunk-XL7R3XN5.js → chunk-VZ6VYRQB.js} +2 -2
  37. package/dist/{chunk-4LWMPKSB.js → chunk-YIETFYCL.js} +44 -71
  38. package/dist/chunk-YIETFYCL.js.map +1 -0
  39. package/dist/client.cjs +438 -426
  40. package/dist/client.cjs.map +1 -1
  41. package/dist/client.js +27 -26
  42. package/dist/edge.cjs +1 -1
  43. package/dist/edge.cjs.map +1 -1
  44. package/dist/edge.js +4 -4
  45. package/dist/{finish-Ddj1MPGt.d.ts → finish-DBKuo8yj.d.ts} +1 -1
  46. package/dist/index.cjs +438 -445
  47. package/dist/index.cjs.map +1 -1
  48. package/dist/index.js +29 -29
  49. package/dist/modelrouter/core.cjs +1 -1
  50. package/dist/modelrouter/core.cjs.map +1 -1
  51. package/dist/modelrouter/core.js +3 -3
  52. package/dist/modelrouter/index.cjs +1 -1
  53. package/dist/modelrouter/index.cjs.map +1 -1
  54. package/dist/modelrouter/index.js +3 -3
  55. package/dist/subagents/anthropic.cjs +434 -422
  56. package/dist/subagents/anthropic.cjs.map +1 -1
  57. package/dist/subagents/anthropic.js +9 -8
  58. package/dist/subagents/vercel.cjs +434 -422
  59. package/dist/subagents/vercel.cjs.map +1 -1
  60. package/dist/subagents/vercel.js +9 -8
  61. package/dist/tools/browser/anthropic.cjs +1 -1
  62. package/dist/tools/browser/anthropic.cjs.map +1 -1
  63. package/dist/tools/browser/anthropic.js +5 -5
  64. package/dist/tools/browser/core.cjs +1 -1
  65. package/dist/tools/browser/core.cjs.map +1 -1
  66. package/dist/tools/browser/core.js +4 -4
  67. package/dist/tools/browser/index.cjs +1 -1
  68. package/dist/tools/browser/index.cjs.map +1 -1
  69. package/dist/tools/browser/index.js +7 -7
  70. package/dist/tools/browser/openai.cjs +1 -1
  71. package/dist/tools/browser/openai.cjs.map +1 -1
  72. package/dist/tools/browser/openai.js +5 -5
  73. package/dist/tools/browser/profiles/core.cjs +1 -1
  74. package/dist/tools/browser/profiles/core.cjs.map +1 -1
  75. package/dist/tools/browser/profiles/core.js +3 -3
  76. package/dist/tools/browser/profiles/index.cjs +1 -1
  77. package/dist/tools/browser/profiles/index.cjs.map +1 -1
  78. package/dist/tools/browser/profiles/index.js +3 -3
  79. package/dist/tools/browser/vercel.cjs +1 -1
  80. package/dist/tools/browser/vercel.cjs.map +1 -1
  81. package/dist/tools/browser/vercel.js +5 -5
  82. package/dist/tools/codebase_search/anthropic.cjs +1 -1
  83. package/dist/tools/codebase_search/anthropic.cjs.map +1 -1
  84. package/dist/tools/codebase_search/anthropic.js +4 -4
  85. package/dist/tools/codebase_search/core.cjs +1 -1
  86. package/dist/tools/codebase_search/core.cjs.map +1 -1
  87. package/dist/tools/codebase_search/core.js +3 -3
  88. package/dist/tools/codebase_search/index.cjs +1 -1
  89. package/dist/tools/codebase_search/index.cjs.map +1 -1
  90. package/dist/tools/codebase_search/index.js +6 -6
  91. package/dist/tools/codebase_search/openai.cjs +1 -1
  92. package/dist/tools/codebase_search/openai.cjs.map +1 -1
  93. package/dist/tools/codebase_search/openai.js +4 -4
  94. package/dist/tools/codebase_search/vercel.cjs +1 -1
  95. package/dist/tools/codebase_search/vercel.cjs.map +1 -1
  96. package/dist/tools/codebase_search/vercel.js +4 -4
  97. package/dist/tools/fastapply/anthropic.cjs +1 -1
  98. package/dist/tools/fastapply/anthropic.cjs.map +1 -1
  99. package/dist/tools/fastapply/anthropic.js +4 -4
  100. package/dist/tools/fastapply/apply.cjs +1 -1
  101. package/dist/tools/fastapply/apply.cjs.map +1 -1
  102. package/dist/tools/fastapply/apply.js +2 -2
  103. package/dist/tools/fastapply/core.cjs +1 -1
  104. package/dist/tools/fastapply/core.cjs.map +1 -1
  105. package/dist/tools/fastapply/core.js +3 -3
  106. package/dist/tools/fastapply/index.cjs +1 -1
  107. package/dist/tools/fastapply/index.cjs.map +1 -1
  108. package/dist/tools/fastapply/index.js +6 -6
  109. package/dist/tools/fastapply/openai.cjs +1 -1
  110. package/dist/tools/fastapply/openai.cjs.map +1 -1
  111. package/dist/tools/fastapply/openai.js +4 -4
  112. package/dist/tools/fastapply/vercel.cjs +1 -1
  113. package/dist/tools/fastapply/vercel.cjs.map +1 -1
  114. package/dist/tools/fastapply/vercel.js +4 -4
  115. package/dist/tools/index.cjs +1 -1
  116. package/dist/tools/index.cjs.map +1 -1
  117. package/dist/tools/index.js +6 -6
  118. package/dist/tools/utils/resilience.cjs +1 -1
  119. package/dist/tools/utils/resilience.cjs.map +1 -1
  120. package/dist/tools/utils/resilience.js +2 -2
  121. package/dist/tools/warp_grep/agent/config.cjs +3 -4
  122. package/dist/tools/warp_grep/agent/config.cjs.map +1 -1
  123. package/dist/tools/warp_grep/agent/config.d.ts +1 -2
  124. package/dist/tools/warp_grep/agent/config.js +1 -1
  125. package/dist/tools/warp_grep/agent/parser.cjs +121 -52
  126. package/dist/tools/warp_grep/agent/parser.cjs.map +1 -1
  127. package/dist/tools/warp_grep/agent/parser.d.ts +5 -12
  128. package/dist/tools/warp_grep/agent/parser.js +3 -7
  129. package/dist/tools/warp_grep/agent/runner.cjs +416 -335
  130. package/dist/tools/warp_grep/agent/runner.cjs.map +1 -1
  131. package/dist/tools/warp_grep/agent/runner.d.ts +3 -6
  132. package/dist/tools/warp_grep/agent/runner.js +6 -5
  133. package/dist/tools/warp_grep/agent/types.cjs.map +1 -1
  134. package/dist/tools/warp_grep/agent/types.d.ts +3 -22
  135. package/dist/tools/warp_grep/anthropic.cjs +434 -422
  136. package/dist/tools/warp_grep/anthropic.cjs.map +1 -1
  137. package/dist/tools/warp_grep/anthropic.js +9 -8
  138. package/dist/tools/warp_grep/client.cjs +434 -422
  139. package/dist/tools/warp_grep/client.cjs.map +1 -1
  140. package/dist/tools/warp_grep/client.js +8 -7
  141. package/dist/tools/warp_grep/gemini.cjs +434 -422
  142. package/dist/tools/warp_grep/gemini.cjs.map +1 -1
  143. package/dist/tools/warp_grep/gemini.js +8 -7
  144. package/dist/tools/warp_grep/gemini.js.map +1 -1
  145. package/dist/tools/warp_grep/harness.cjs +176 -164
  146. package/dist/tools/warp_grep/harness.cjs.map +1 -1
  147. package/dist/tools/warp_grep/harness.d.ts +38 -17
  148. package/dist/tools/warp_grep/harness.js +14 -15
  149. package/dist/tools/warp_grep/harness.js.map +1 -1
  150. package/dist/tools/warp_grep/index.cjs +434 -441
  151. package/dist/tools/warp_grep/index.cjs.map +1 -1
  152. package/dist/tools/warp_grep/index.d.ts +1 -1
  153. package/dist/tools/warp_grep/index.js +10 -10
  154. package/dist/tools/warp_grep/openai.cjs +434 -422
  155. package/dist/tools/warp_grep/openai.cjs.map +1 -1
  156. package/dist/tools/warp_grep/openai.js +9 -8
  157. package/dist/tools/warp_grep/providers/local.cjs +2 -43
  158. package/dist/tools/warp_grep/providers/local.cjs.map +1 -1
  159. package/dist/tools/warp_grep/providers/local.d.ts +1 -5
  160. package/dist/tools/warp_grep/providers/local.js +2 -2
  161. package/dist/tools/warp_grep/providers/remote.cjs +2 -32
  162. package/dist/tools/warp_grep/providers/remote.cjs.map +1 -1
  163. package/dist/tools/warp_grep/providers/remote.d.ts +1 -9
  164. package/dist/tools/warp_grep/providers/remote.js +2 -2
  165. package/dist/tools/warp_grep/providers/types.cjs.map +1 -1
  166. package/dist/tools/warp_grep/providers/types.d.ts +1 -14
  167. package/dist/tools/warp_grep/vercel.cjs +434 -422
  168. package/dist/tools/warp_grep/vercel.cjs.map +1 -1
  169. package/dist/tools/warp_grep/vercel.js +9 -8
  170. package/dist/version.cjs +1 -1
  171. package/dist/version.cjs.map +1 -1
  172. package/dist/version.js +1 -1
  173. package/package.json +1 -1
  174. package/dist/chunk-4LWMPKSB.js.map +0 -1
  175. package/dist/chunk-4Y2NM6JD.js.map +0 -1
  176. package/dist/chunk-B3AKP3RA.js.map +0 -1
  177. package/dist/chunk-CMSHXALI.js +0 -60
  178. package/dist/chunk-CMSHXALI.js.map +0 -1
  179. package/dist/chunk-I3J46TSB.js.map +0 -1
  180. package/dist/chunk-OPEQQGST.js +0 -396
  181. package/dist/chunk-OPEQQGST.js.map +0 -1
  182. /package/dist/{chunk-HBIW2XV2.js.map → chunk-4PBUB77N.js.map} +0 -0
  183. /package/dist/{chunk-SUE4GYA2.js.map → chunk-BDHKL3MT.js.map} +0 -0
  184. /package/dist/{chunk-S54SPKX3.js.map → chunk-BIQ7234U.js.map} +0 -0
  185. /package/dist/{chunk-MRPASJBX.js.map → chunk-E45FW5EK.js.map} +0 -0
  186. /package/dist/{chunk-BXRJYLRS.js.map → chunk-E4YKEKGW.js.map} +0 -0
  187. /package/dist/{chunk-G23BI5CQ.js.map → chunk-EU7OLX4Z.js.map} +0 -0
  188. /package/dist/{chunk-HE7K2QNQ.js.map → chunk-FBOJJ3UY.js.map} +0 -0
  189. /package/dist/{chunk-HYRHI2UL.js.map → chunk-FIVYDIHX.js.map} +0 -0
  190. /package/dist/{chunk-GXM3G7Z4.js.map → chunk-FYO46OT6.js.map} +0 -0
  191. /package/dist/{chunk-GHPQYSSF.js.map → chunk-GJUB3ECP.js.map} +0 -0
  192. /package/dist/{chunk-MTJ3PR4M.js.map → chunk-I7SFRYTX.js.map} +0 -0
  193. /package/dist/{chunk-PX7ODEML.js.map → chunk-J2HIK4GB.js.map} +0 -0
  194. /package/dist/{chunk-RZXS4ADX.js.map → chunk-JSWNBCGS.js.map} +0 -0
  195. /package/dist/{chunk-GXCWKYGU.js.map → chunk-KYKRRF7E.js.map} +0 -0
  196. /package/dist/{chunk-N7TTZIBK.js.map → chunk-MMBQKN4G.js.map} +0 -0
  197. /package/dist/{chunk-JMUAQQJU.js.map → chunk-NKUSUSVI.js.map} +0 -0
  198. /package/dist/{chunk-VRV5UYTN.js.map → chunk-OV57JBMB.js.map} +0 -0
  199. /package/dist/{chunk-EPIOAODF.js.map → chunk-Q36MNOFA.js.map} +0 -0
  200. /package/dist/{chunk-JRBU4UNP.js.map → chunk-QRSWXP4K.js.map} +0 -0
  201. /package/dist/{chunk-IRWHN55G.js.map → chunk-T564HFSH.js.map} +0 -0
  202. /package/dist/{chunk-6CFKWZK3.js.map → chunk-UVNENJ6H.js.map} +0 -0
  203. /package/dist/{chunk-5FCXLQJU.js.map → chunk-UYPWKQKV.js.map} +0 -0
  204. /package/dist/{chunk-BAF33L6C.js.map → chunk-V73GO5AJ.js.map} +0 -0
  205. /package/dist/{chunk-XL7R3XN5.js.map → chunk-VZ6VYRQB.js.map} +0 -0
package/dist/index.cjs CHANGED
@@ -36,7 +36,7 @@ var init_package = __esm({
36
36
  "package.json"() {
37
37
  package_default = {
38
38
  name: "@morphllm/morphsdk",
39
- version: "0.2.145",
39
+ version: "0.2.146",
40
40
  description: "TypeScript SDK and CLI for Morph Fast Apply integration",
41
41
  type: "module",
42
42
  main: "./dist/index.cjs",
@@ -416,12 +416,11 @@ var init_config = __esm({
416
416
  return isNaN(parsed) || parsed <= 0 ? defaultMs : parsed;
417
417
  };
418
418
  AGENT_CONFIG = {
419
- MAX_TURNS: 6,
419
+ MAX_TURNS: 4,
420
420
  /** Default timeout for model calls. Can be overridden via MORPH_WARP_GREP_TIMEOUT env var (in ms) */
421
421
  TIMEOUT_MS: parseEnvTimeout(process.env.MORPH_WARP_GREP_TIMEOUT, 3e4),
422
- MAX_CONTEXT_CHARS: 321600,
422
+ MAX_CONTEXT_CHARS: 54e4,
423
423
  MAX_OUTPUT_LINES: 200,
424
- MAX_LIST_RESULTS: 500,
425
424
  MAX_READ_LINES: 800,
426
425
  MAX_LIST_DEPTH: 3,
427
426
  LIST_TIMEOUT_MS: 2e3
@@ -506,7 +505,7 @@ var init_config = __esm({
506
505
  ".*"
507
506
  ];
508
507
  DEFAULT_EXCLUDES = (process.env.MORPH_WARP_GREP_EXCLUDE || "").split(",").map((s) => s.trim()).filter(Boolean).concat(BUILTIN_EXCLUDES);
509
- DEFAULT_MODEL = "morph-warp-grep-v2.1";
508
+ DEFAULT_MODEL = "morph-warp-grep-v2";
510
509
  }
511
510
  });
512
511
 
@@ -579,19 +578,19 @@ var init_ripgrep = __esm({
579
578
 
580
579
  // tools/warp_grep/utils/paths.ts
581
580
  function resolveUnderRepo(repoRoot, targetPath) {
582
- const absRoot = import_path5.default.resolve(repoRoot);
583
- const resolved = import_path5.default.resolve(absRoot, targetPath);
581
+ const absRoot = import_path4.default.resolve(repoRoot);
582
+ const resolved = import_path4.default.resolve(absRoot, targetPath);
584
583
  ensureWithinRepo(absRoot, resolved);
585
584
  return resolved;
586
585
  }
587
586
  function ensureWithinRepo(repoRoot, absTarget) {
588
- const rel = import_path5.default.relative(import_path5.default.resolve(repoRoot), import_path5.default.resolve(absTarget));
589
- if (rel.startsWith("..") || import_path5.default.isAbsolute(rel)) {
587
+ const rel = import_path4.default.relative(import_path4.default.resolve(repoRoot), import_path4.default.resolve(absTarget));
588
+ if (rel.startsWith("..") || import_path4.default.isAbsolute(rel)) {
590
589
  throw new Error(`Path outside repository root: ${absTarget}`);
591
590
  }
592
591
  }
593
592
  function toRepoRelative(repoRoot, absPath) {
594
- return import_path5.default.relative(import_path5.default.resolve(repoRoot), import_path5.default.resolve(absPath));
593
+ return import_path4.default.relative(import_path4.default.resolve(repoRoot), import_path4.default.resolve(absPath));
595
594
  }
596
595
  function isSymlink(p) {
597
596
  try {
@@ -602,7 +601,7 @@ function isSymlink(p) {
602
601
  }
603
602
  }
604
603
  function fixPathRepetition(fullPath) {
605
- const segments = fullPath.split(import_path5.default.sep).filter(Boolean);
604
+ const segments = fullPath.split(import_path4.default.sep).filter(Boolean);
606
605
  if (segments.length < 2) return null;
607
606
  for (let len = Math.floor(segments.length / 2); len >= 1; len--) {
608
607
  for (let i = 0; i <= segments.length - 2 * len; i++) {
@@ -610,7 +609,7 @@ function fixPathRepetition(fullPath) {
610
609
  const second = segments.slice(i + len, i + 2 * len);
611
610
  if (first.every((seg, idx) => seg === second[idx])) {
612
611
  const fixed = [...segments.slice(0, i), ...segments.slice(i + len)];
613
- return import_path5.default.sep + fixed.join(import_path5.default.sep);
612
+ return import_path4.default.sep + fixed.join(import_path4.default.sep);
614
613
  }
615
614
  }
616
615
  }
@@ -634,12 +633,12 @@ function isTextualFile(filePath, maxBytes = 2e6) {
634
633
  return false;
635
634
  }
636
635
  }
637
- var import_fs, import_path5;
636
+ var import_fs, import_path4;
638
637
  var init_paths = __esm({
639
638
  "tools/warp_grep/utils/paths.ts"() {
640
639
  "use strict";
641
640
  import_fs = __toESM(require("fs"), 1);
642
- import_path5 = __toESM(require("path"), 1);
641
+ import_path4 = __toESM(require("path"), 1);
643
642
  }
644
643
  });
645
644
 
@@ -670,12 +669,12 @@ function shouldSkip2(name, allowNames) {
670
669
  }
671
670
  return false;
672
671
  }
673
- var import_promises2, import_path6, SKIP_NAMES2, SKIP_EXTENSIONS2, LocalRipgrepProvider;
672
+ var import_promises2, import_path5, SKIP_NAMES2, SKIP_EXTENSIONS2, LocalRipgrepProvider;
674
673
  var init_local = __esm({
675
674
  "tools/warp_grep/providers/local.ts"() {
676
675
  "use strict";
677
676
  import_promises2 = __toESM(require("fs/promises"), 1);
678
- import_path6 = __toESM(require("path"), 1);
677
+ import_path5 = __toESM(require("path"), 1);
679
678
  init_ripgrep();
680
679
  init_paths();
681
680
  init_files();
@@ -777,7 +776,7 @@ var init_local = __esm({
777
776
  }
778
777
  const stat = await import_promises2.default.stat(abs).catch(() => null);
779
778
  if (!stat) return { lines: [] };
780
- const targetArg = abs === import_path6.default.resolve(this.repoRoot) ? "." : toRepoRelative(this.repoRoot, abs);
779
+ const targetArg = abs === import_path5.default.resolve(this.repoRoot) ? "." : toRepoRelative(this.repoRoot, abs);
781
780
  const contextLines = params.context_lines !== void 0 ? String(params.context_lines) : "1";
782
781
  const args = [
783
782
  "--no-config",
@@ -932,7 +931,7 @@ Details: ${res.stderr}` : ""}`
932
931
  if (timedOut || results.length >= maxResults) break;
933
932
  if (shouldSkip2(entry.name, allowNames)) continue;
934
933
  if (regex && !regex.test(entry.name)) continue;
935
- const full = import_path6.default.join(dir, entry.name);
934
+ const full = import_path5.default.join(dir, entry.name);
936
935
  const isDir = entry.isDirectory();
937
936
  results.push({
938
937
  name: entry.name,
@@ -948,46 +947,6 @@ Details: ${res.stderr}` : ""}`
948
947
  await walk(abs, 0);
949
948
  return results;
950
949
  }
951
- async glob(params) {
952
- let abs;
953
- try {
954
- abs = params.path ? resolveUnderRepo(this.repoRoot, params.path) : this.repoRoot;
955
- } catch (err) {
956
- return { files: [], searchDir: this.repoRoot, totalFound: 0, error: `[PATH ERROR] ${err instanceof Error ? err.message : String(err)}` };
957
- }
958
- const stat = await import_promises2.default.stat(abs).catch(() => null);
959
- if (!stat || !stat.isDirectory()) {
960
- return { files: [], searchDir: abs, totalFound: 0, error: `[PATH ERROR] Directory not found: ${params.path || "."}` };
961
- }
962
- const targetArg = abs === import_path6.default.resolve(this.repoRoot) ? "." : toRepoRelative(this.repoRoot, abs);
963
- const args = [
964
- "--no-config",
965
- "--files",
966
- "--color=never",
967
- "-g",
968
- params.pattern,
969
- ...this.excludes.filter((e) => !this.allowNames?.has(e)).flatMap((e) => ["-g", `!${e}`]),
970
- targetArg || "."
971
- ];
972
- const res = await runRipgrep(args, { cwd: this.repoRoot });
973
- if (res.exitCode === -1) {
974
- return { files: [], searchDir: abs, totalFound: 0, error: `[RIPGREP NOT AVAILABLE] ripgrep (rg) is required for glob search.` };
975
- }
976
- if (res.exitCode !== 0 && res.exitCode !== 1) {
977
- return { files: [], searchDir: abs, totalFound: 0, error: `[GLOB ERROR] glob failed with exit code ${res.exitCode}${res.stderr ? `: ${res.stderr}` : ""}` };
978
- }
979
- const absRoot = import_path6.default.resolve(this.repoRoot);
980
- const relFiles = (res.stdout || "").trim().split(/\r?\n/).filter((l) => l.length > 0);
981
- const absFiles = relFiles.map((f) => import_path6.default.resolve(absRoot, f));
982
- const withMtime = [];
983
- for (const f of absFiles) {
984
- const s = await import_promises2.default.stat(f).catch(() => null);
985
- withMtime.push({ file: f, mtime: s?.mtimeMs ?? 0 });
986
- }
987
- withMtime.sort((a, b) => b.mtime - a.mtime);
988
- const totalFound = withMtime.length;
989
- return { files: withMtime.slice(0, 100).map((f) => f.file), searchDir: abs, totalFound };
990
- }
991
950
  };
992
951
  }
993
952
  });
@@ -2556,58 +2515,131 @@ async function checkHealth(config = {}) {
2556
2515
  init_config();
2557
2516
 
2558
2517
  // tools/warp_grep/agent/parser.ts
2559
- function parseReadLines(linesStr) {
2560
- const ranges = [];
2561
- for (const rangeStr of linesStr.split(",")) {
2562
- const trimmed = rangeStr.trim();
2563
- if (!trimmed) continue;
2564
- const parts = trimmed.split("-").map((v) => parseInt(v.trim(), 10));
2565
- if (parts.length >= 2 && Number.isFinite(parts[0]) && Number.isFinite(parts[1])) {
2566
- ranges.push([parts[0], parts[1]]);
2567
- } else if (Number.isFinite(parts[0])) {
2568
- ranges.push([parts[0], parts[0]]);
2569
- }
2570
- }
2571
- if (ranges.length === 1) return { start: ranges[0][0], end: ranges[0][1] };
2572
- if (ranges.length > 1) return { lines: ranges };
2573
- return {};
2518
+ var VALID_COMMANDS = ["list_directory", "ripgrep", "read", "finish"];
2519
+ function isValidCommand(name) {
2520
+ return VALID_COMMANDS.includes(name);
2574
2521
  }
2575
- function parseFinishFiles(filesStr) {
2576
- const files = [];
2577
- for (const line of filesStr.trim().split(/\s+/)) {
2578
- const trimmed = line.trim();
2579
- if (!trimmed) continue;
2580
- const colonIdx = trimmed.indexOf(":");
2581
- if (colonIdx === -1) {
2582
- files.push({ path: trimmed, lines: "*" });
2583
- continue;
2584
- }
2585
- const filePath = trimmed.slice(0, colonIdx);
2586
- const rangesPart = trimmed.slice(colonIdx + 1);
2587
- if (!rangesPart.trim() || rangesPart.trim() === "*") {
2588
- files.push({ path: filePath, lines: "*" });
2589
- continue;
2590
- }
2591
- const ranges = [];
2592
- for (const rangeStr of rangesPart.split(",")) {
2593
- const rt = rangeStr.trim();
2594
- if (!rt) continue;
2595
- const parts = rt.split("-").map((v) => parseInt(v.trim(), 10));
2596
- if (parts.length >= 2 && Number.isFinite(parts[0]) && Number.isFinite(parts[1])) {
2597
- ranges.push([parts[0], parts[1]]);
2598
- } else if (Number.isFinite(parts[0])) {
2599
- ranges.push([parts[0], parts[0]]);
2522
+ function parseQwen3ToolCalls(text) {
2523
+ const tools = [];
2524
+ const toolCallRegex = /<tool_call>\s*<function=([a-z_][a-z0-9_]*)>([\s\S]*?)<\/function>\s*<\/tool_call>/gi;
2525
+ let match;
2526
+ while ((match = toolCallRegex.exec(text)) !== null) {
2527
+ const funcName = match[1].toLowerCase();
2528
+ const body = match[2];
2529
+ if (!isValidCommand(funcName)) continue;
2530
+ const params = {};
2531
+ const paramRegex = /<parameter=([a-z_][a-z0-9_]*)>([\s\S]*?)<\/parameter>/gi;
2532
+ let paramMatch;
2533
+ while ((paramMatch = paramRegex.exec(body)) !== null) {
2534
+ params[paramMatch[1].toLowerCase()] = paramMatch[2].trim();
2535
+ }
2536
+ if (funcName === "ripgrep") {
2537
+ const pattern = params.pattern;
2538
+ if (!pattern) continue;
2539
+ const args = {
2540
+ pattern,
2541
+ path: params.path || ".",
2542
+ ...params.glob && { glob: params.glob },
2543
+ ...params.context_lines && { context_lines: parseInt(params.context_lines, 10) },
2544
+ ...params.case_sensitive && { case_sensitive: params.case_sensitive === "true" }
2545
+ };
2546
+ tools.push({ name: "grep", arguments: args });
2547
+ } else if (funcName === "list_directory") {
2548
+ const command = params.command;
2549
+ const directPath = params.path;
2550
+ let dirPath = directPath || ".";
2551
+ if (!directPath && command) {
2552
+ const tokens = command.trim().split(/\s+/);
2553
+ const pathTokens = tokens.slice(1).filter((t) => !t.startsWith("-") && !t.startsWith("|") && !t.startsWith("\\("));
2554
+ if (pathTokens.length > 0) {
2555
+ dirPath = pathTokens[0];
2556
+ }
2557
+ }
2558
+ tools.push({ name: "list_directory", arguments: { path: dirPath, pattern: params.pattern || null } });
2559
+ } else if (funcName === "read") {
2560
+ const filePath = params.path;
2561
+ if (!filePath) continue;
2562
+ const args = { path: filePath };
2563
+ const linesStr = params.lines;
2564
+ if (linesStr) {
2565
+ const ranges = [];
2566
+ for (const rangeStr of linesStr.split(",")) {
2567
+ const trimmed = rangeStr.trim();
2568
+ if (!trimmed) continue;
2569
+ const [s, e] = trimmed.split("-").map((v) => parseInt(v.trim(), 10));
2570
+ if (Number.isFinite(s) && Number.isFinite(e)) {
2571
+ ranges.push([s, e]);
2572
+ } else if (Number.isFinite(s)) {
2573
+ ranges.push([s, s]);
2574
+ }
2575
+ }
2576
+ if (ranges.length === 1) {
2577
+ args.start = ranges[0][0];
2578
+ args.end = ranges[0][1];
2579
+ } else if (ranges.length > 1) {
2580
+ args.lines = ranges;
2581
+ }
2582
+ }
2583
+ tools.push({ name: "read", arguments: args });
2584
+ } else if (funcName === "finish") {
2585
+ if (params.result && !params.files) {
2586
+ tools.push({ name: "finish", arguments: { files: [], textResult: params.result } });
2587
+ continue;
2588
+ }
2589
+ const filesStr = params.files;
2590
+ if (!filesStr) {
2591
+ tools.push({ name: "finish", arguments: { files: [], textResult: "No relevant code found." } });
2592
+ continue;
2593
+ }
2594
+ const files = [];
2595
+ for (const line of filesStr.split("\n")) {
2596
+ const trimmed = line.trim();
2597
+ if (!trimmed) continue;
2598
+ const colonIdx = trimmed.indexOf(":");
2599
+ if (colonIdx === -1) {
2600
+ files.push({ path: trimmed, lines: "*" });
2601
+ } else {
2602
+ const filePath = trimmed.slice(0, colonIdx);
2603
+ const rangesPart = trimmed.slice(colonIdx + 1);
2604
+ const ranges = [];
2605
+ for (const rangeStr of rangesPart.split(",")) {
2606
+ const rt = rangeStr.trim();
2607
+ if (!rt || rt === "*") {
2608
+ files.push({ path: filePath, lines: "*" });
2609
+ break;
2610
+ }
2611
+ const [s, e] = rt.split("-").map((v) => parseInt(v.trim(), 10));
2612
+ if (Number.isFinite(s) && Number.isFinite(e)) {
2613
+ ranges.push([s, e]);
2614
+ } else if (Number.isFinite(s)) {
2615
+ ranges.push([s, s]);
2616
+ }
2617
+ }
2618
+ if (ranges.length > 0) {
2619
+ files.push({ path: filePath, lines: ranges });
2620
+ } else if (!files.some((f) => f.path === filePath)) {
2621
+ files.push({ path: filePath, lines: "*" });
2622
+ }
2623
+ }
2624
+ }
2625
+ if (files.length > 0) {
2626
+ tools.push({ name: "finish", arguments: { files } });
2627
+ } else {
2628
+ tools.push({ name: "finish", arguments: { files: [], textResult: filesStr } });
2600
2629
  }
2601
2630
  }
2602
- files.push({ path: filePath, lines: ranges.length > 0 ? ranges : "*" });
2603
2631
  }
2604
- return files;
2605
- }
2606
- function extractPathFromCommand(command) {
2607
- const tokens = command.trim().split(/\s+/);
2608
- const pathTokens = tokens.slice(1).filter((t) => !t.startsWith("-") && !t.startsWith("|") && !t.startsWith("\\("));
2609
- return pathTokens[0] || ".";
2632
+ return tools;
2610
2633
  }
2634
+ var LLMResponseParser = class {
2635
+ parse(text) {
2636
+ if (typeof text !== "string") {
2637
+ throw new TypeError("Command text must be a string.");
2638
+ }
2639
+ const withoutThink = text.replace(/<think>[\s\S]*?<\/think>/gi, "");
2640
+ return parseQwen3ToolCalls(withoutThink);
2641
+ }
2642
+ };
2611
2643
 
2612
2644
  // tools/warp_grep/agent/tools/grep.ts
2613
2645
  async function toolGrep(provider, args) {
@@ -2658,42 +2690,29 @@ async function toolRead(provider, args) {
2658
2690
 
2659
2691
  // tools/warp_grep/agent/tools/list_directory.ts
2660
2692
  init_config();
2661
- var import_path2 = __toESM(require("path"), 1);
2662
- async function toolListDirectory(provider, args, repoRoot) {
2663
- const maxResults = args.maxResults ?? AGENT_CONFIG.MAX_LIST_RESULTS;
2664
- const maxDepth = args.maxDepth ?? AGENT_CONFIG.MAX_LIST_DEPTH;
2665
- const entries = await provider.listDirectory({
2666
- path: args.path,
2667
- pattern: args.pattern ?? null,
2668
- maxResults,
2669
- maxDepth
2670
- });
2671
- if (!entries.length) return "empty";
2672
- if (repoRoot) {
2673
- const absRoot = import_path2.default.resolve(repoRoot);
2674
- const lines = entries.map((e) => import_path2.default.join(absRoot, e.path));
2675
- return lines.join("\n");
2676
- }
2677
- return entries.map((e) => e.path).join("\n");
2678
- }
2679
-
2680
- // tools/warp_grep/agent/tools/glob.ts
2681
- async function toolGlob(provider, args) {
2682
- const res = await provider.glob(args);
2683
- if (res.error) {
2684
- return res.error;
2685
- }
2686
- if (!res.files.length) {
2687
- return "no matches";
2688
- }
2689
- const header = `Found ${res.totalFound} file(s) matching "${args.pattern}" within ${res.searchDir}, sorted by modification time (newest first):`;
2690
- const body = res.files.join("\n");
2691
- const truncated = res.totalFound > res.files.length ? `
2692
- [${res.totalFound - res.files.length} files truncated]` : "";
2693
- return `${header}
2694
- ---
2695
- ${body}
2696
- ---${truncated}`;
2693
+ async function toolListDirectory(provider, args) {
2694
+ const maxResults = args.maxResults ?? AGENT_CONFIG.MAX_OUTPUT_LINES;
2695
+ const initialDepth = args.maxDepth ?? AGENT_CONFIG.MAX_LIST_DEPTH;
2696
+ async function getListRecursive(currentDepth) {
2697
+ const entries = await provider.listDirectory({
2698
+ path: args.path,
2699
+ pattern: args.pattern ?? null,
2700
+ maxResults,
2701
+ maxDepth: currentDepth
2702
+ });
2703
+ if (entries.length >= maxResults && currentDepth > 0) {
2704
+ return getListRecursive(currentDepth - 1);
2705
+ }
2706
+ return { entries };
2707
+ }
2708
+ const { entries: list } = await getListRecursive(initialDepth);
2709
+ if (!list.length) return "empty";
2710
+ const tree = list.map((e) => {
2711
+ const indent = " ".repeat(e.depth);
2712
+ const name = e.type === "dir" ? `${e.name}/` : e.name;
2713
+ return `${indent}${name}`;
2714
+ }).join("\n");
2715
+ return tree;
2697
2716
  }
2698
2717
 
2699
2718
  // tools/warp_grep/agent/tools/finish.ts
@@ -2754,21 +2773,32 @@ function mergeRanges(ranges) {
2754
2773
  return merged;
2755
2774
  }
2756
2775
 
2757
- // tools/warp_grep/agent/helpers.ts
2758
- var import_path3 = __toESM(require("path"), 1);
2759
- init_config();
2760
- var TRUNCATED_MARKER = "[truncated for context limit]";
2761
- function getMessageSize(m) {
2762
- if (m.role === "tool") return m.content.length;
2763
- if (m.role === "assistant") {
2764
- let size = typeof m.content === "string" ? m.content.length : 0;
2765
- if (m.tool_calls) {
2766
- size += m.tool_calls.reduce((s, tc) => s + tc.function.name.length + tc.function.arguments.length, 0);
2776
+ // tools/warp_grep/agent/formatter.ts
2777
+ var ToolOutputFormatter = class {
2778
+ format(toolName, _args, output, options = {}) {
2779
+ const name = (toolName ?? "").trim();
2780
+ if (!name) {
2781
+ return "";
2782
+ }
2783
+ const payload = output?.toString?.()?.trim?.() ?? "";
2784
+ const isError = Boolean(options.isError);
2785
+ if (!payload && !isError) {
2786
+ return "";
2767
2787
  }
2768
- return size;
2788
+ return `<tool_response>
2789
+ ${payload}
2790
+ </tool_response>`;
2769
2791
  }
2770
- return m.content.length;
2792
+ };
2793
+ var sharedFormatter = new ToolOutputFormatter();
2794
+ function formatAgentToolOutput(toolName, args, output, options = {}) {
2795
+ return sharedFormatter.format(toolName, args, output, options);
2771
2796
  }
2797
+
2798
+ // tools/warp_grep/agent/helpers.ts
2799
+ var import_path2 = __toESM(require("path"), 1);
2800
+ init_config();
2801
+ var TRUNCATED_MARKER = "[truncated for context limit]";
2772
2802
  function formatTurnMessage(turnsUsed, maxTurns) {
2773
2803
  const turnsRemaining = maxTurns - turnsUsed;
2774
2804
  if (turnsRemaining === 1) {
@@ -2779,7 +2809,7 @@ You have used ${turnsUsed} turns, you only have 1 turn remaining. You have run o
2779
2809
  You have used ${turnsUsed} turn${turnsUsed === 1 ? "" : "s"} and have ${turnsRemaining} remaining`;
2780
2810
  }
2781
2811
  function calculateContextBudget(messages) {
2782
- const totalChars = messages.reduce((sum, m) => sum + getMessageSize(m), 0);
2812
+ const totalChars = messages.reduce((sum, m) => sum + m.content.length, 0);
2783
2813
  const maxChars = AGENT_CONFIG.MAX_CONTEXT_CHARS;
2784
2814
  const percent = Math.round(totalChars / maxChars * 100);
2785
2815
  const usedK = Math.round(totalChars / 1e3);
@@ -2788,21 +2818,24 @@ function calculateContextBudget(messages) {
2788
2818
  }
2789
2819
  async function buildInitialState(repoRoot, searchTerm, provider, options) {
2790
2820
  const budget = calculateContextBudget([]);
2791
- const turnTag = `You have used 0 turns and have ${AGENT_CONFIG.MAX_TURNS} remaining`;
2821
+ const turnTag = `Turn 0/${AGENT_CONFIG.MAX_TURNS}`;
2792
2822
  const treeDepth = options?.search_type === "node_modules" ? 1 : 2;
2793
- const absRoot = import_path3.default.resolve(repoRoot);
2794
2823
  try {
2795
2824
  const entries = await provider.listDirectory({
2796
2825
  path: ".",
2797
2826
  maxResults: AGENT_CONFIG.MAX_OUTPUT_LINES,
2798
2827
  maxDepth: treeDepth
2799
2828
  });
2800
- const lines = [absRoot];
2801
- for (const e of entries) {
2802
- lines.push(import_path3.default.join(absRoot, e.path));
2803
- }
2829
+ const treeLines = entries.map((e) => {
2830
+ const indent = " ".repeat(e.depth);
2831
+ const name = e.type === "dir" ? `${e.name}/` : e.name;
2832
+ return `${indent}${name}`;
2833
+ });
2834
+ const repoName = import_path2.default.basename(repoRoot);
2835
+ const treeOutput = treeLines.length > 0 ? `${repoName}/
2836
+ ${treeLines.join("\n")}` : `${repoName}/`;
2804
2837
  return `<repo_structure>
2805
- ${lines.join("\n")}
2838
+ ${treeOutput}
2806
2839
  </repo_structure>
2807
2840
 
2808
2841
  <search_string>
@@ -2811,8 +2844,9 @@ ${searchTerm}
2811
2844
  ${budget}
2812
2845
  ${turnTag}`;
2813
2846
  } catch {
2847
+ const repoName = import_path2.default.basename(repoRoot);
2814
2848
  return `<repo_structure>
2815
- ${absRoot}
2849
+ ${repoName}/
2816
2850
  </repo_structure>
2817
2851
 
2818
2852
  <search_string>
@@ -2823,32 +2857,26 @@ ${turnTag}`;
2823
2857
  }
2824
2858
  }
2825
2859
  function enforceContextLimit(messages, maxChars = AGENT_CONFIG.MAX_CONTEXT_CHARS) {
2826
- const getTotalChars = () => messages.reduce((sum, m) => sum + getMessageSize(m), 0);
2860
+ const getTotalChars = () => messages.reduce((sum, m) => sum + m.content.length, 0);
2827
2861
  if (getTotalChars() <= maxChars) {
2828
2862
  return messages;
2829
2863
  }
2830
- const truncatableIndices = [];
2864
+ const userIndices = [];
2831
2865
  let firstUserSkipped = false;
2832
2866
  for (let i = 0; i < messages.length; i++) {
2833
- const m = messages[i];
2834
- if (m.role === "tool") {
2835
- truncatableIndices.push(i);
2836
- } else if (m.role === "user") {
2867
+ if (messages[i].role === "user") {
2837
2868
  if (!firstUserSkipped) {
2838
2869
  firstUserSkipped = true;
2839
2870
  continue;
2840
2871
  }
2841
- truncatableIndices.push(i);
2872
+ userIndices.push(i);
2842
2873
  }
2843
2874
  }
2844
- for (const idx of truncatableIndices) {
2875
+ for (const idx of userIndices) {
2845
2876
  if (getTotalChars() <= maxChars) {
2846
2877
  break;
2847
2878
  }
2848
- const m = messages[idx];
2849
- if (m.role === "tool" && m.content !== TRUNCATED_MARKER) {
2850
- messages[idx] = { role: "tool", tool_call_id: m.tool_call_id, content: TRUNCATED_MARKER };
2851
- } else if (m.role === "user" && m.content !== TRUNCATED_MARKER) {
2879
+ if (messages[idx].content !== TRUNCATED_MARKER) {
2852
2880
  messages[idx] = { role: "user", content: TRUNCATED_MARKER };
2853
2881
  }
2854
2882
  }
@@ -2858,115 +2886,9 @@ function enforceContextLimit(messages, maxChars = AGENT_CONFIG.MAX_CONTEXT_CHARS
2858
2886
  // tools/warp_grep/agent/runner.ts
2859
2887
  var import_openai2 = __toESM(require("openai"), 1);
2860
2888
  init_version();
2861
- var import_path4 = __toESM(require("path"), 1);
2889
+ var import_path3 = __toESM(require("path"), 1);
2890
+ var parser = new LLMResponseParser();
2862
2891
  var DEFAULT_API_URL3 = "https://api.morphllm.com";
2863
- var TOOL_SPECS = [
2864
- {
2865
- type: "function",
2866
- function: {
2867
- name: "list_directory",
2868
- description: "Execute ls or find commands to explore directory structure. Max 500 results. Common junk directories are excluded automatically.",
2869
- parameters: {
2870
- type: "object",
2871
- properties: {
2872
- command: {
2873
- type: "string",
2874
- description: "Full ls or find command (e.g. ls -la src/, find . -maxdepth 2 -type f -name '*.py', find . -type d, ls -d */)."
2875
- }
2876
- },
2877
- required: ["command"]
2878
- }
2879
- }
2880
- },
2881
- {
2882
- type: "function",
2883
- function: {
2884
- name: "grep_search",
2885
- description: "Search for a regex pattern in file contents. Returns matching lines with file paths and line numbers. Case-insensitive. Respects .gitignore.",
2886
- parameters: {
2887
- type: "object",
2888
- properties: {
2889
- pattern: {
2890
- type: "string",
2891
- description: "Regex pattern to search for in file contents (e.g. 'class\\s+\\w+Error', 'import|require|from', 'def (get|set|update)_user')."
2892
- },
2893
- path: {
2894
- type: "string",
2895
- description: "File or directory to search in. Defaults to current working directory."
2896
- },
2897
- glob: {
2898
- type: "string",
2899
- description: "Glob pattern to filter files (e.g. '*.py', '*.{ts,tsx,js,jsx,py,go}', 'src/**/*.go', '!*.test.*')."
2900
- },
2901
- limit: {
2902
- type: "integer",
2903
- description: "Limit output to first N matching lines. Shows all matches if not specified."
2904
- }
2905
- },
2906
- required: ["pattern"]
2907
- }
2908
- }
2909
- },
2910
- {
2911
- type: "function",
2912
- function: {
2913
- name: "glob",
2914
- description: "Find files by name/extension using glob patterns. Returns absolute paths sorted by modification time (newest first). Respects .gitignore. Max 100 results.",
2915
- parameters: {
2916
- type: "object",
2917
- properties: {
2918
- pattern: {
2919
- type: "string",
2920
- description: "Glob pattern to match files (e.g. '*.py', 'src/**/*.js', '*.{ts,tsx}', 'test_*.py')."
2921
- },
2922
- path: {
2923
- type: "string",
2924
- description: "Directory to search in. Defaults to repository root."
2925
- }
2926
- },
2927
- required: ["pattern"]
2928
- }
2929
- }
2930
- },
2931
- {
2932
- type: "function",
2933
- function: {
2934
- name: "read",
2935
- description: "Read entire files or specific line ranges using absolute paths.",
2936
- parameters: {
2937
- type: "object",
2938
- properties: {
2939
- path: {
2940
- type: "string",
2941
- description: "File path to read, using absolute path (e.g. '/home/ubuntu/repo/src/main.py' or windows path)."
2942
- },
2943
- lines: {
2944
- type: "string",
2945
- description: "Optional line range (e.g. '1-50' or '1-20,45-80'). Omit to read entire file."
2946
- }
2947
- },
2948
- required: ["path"]
2949
- }
2950
- }
2951
- },
2952
- {
2953
- type: "function",
2954
- function: {
2955
- name: "finish",
2956
- description: "Submit final answer with all relevant code locations. Include imports and over-include rather than miss context.",
2957
- parameters: {
2958
- type: "object",
2959
- properties: {
2960
- files: {
2961
- type: "string",
2962
- description: "One file per line as path:lines (e.g. 'src/auth.py:1-15,25-50\\nsrc/user.py'). Omit line range to include entire file."
2963
- }
2964
- },
2965
- required: ["files"]
2966
- }
2967
- }
2968
- }
2969
- ];
2970
2892
  async function callModel(messages, model, options = {}) {
2971
2893
  const baseUrl = options.morphApiUrl || DEFAULT_API_URL3;
2972
2894
  const apiKey = options.morphApiKey || process.env.MORPH_API_KEY || "";
@@ -2987,9 +2909,8 @@ async function callModel(messages, model, options = {}) {
2987
2909
  data = await client.chat.completions.create({
2988
2910
  model,
2989
2911
  temperature: 0,
2990
- max_tokens: 2048,
2912
+ max_tokens: 1024,
2991
2913
  messages,
2992
- tools: TOOL_SPECS,
2993
2914
  ...options.search_type ? { search_type: options.search_type } : {}
2994
2915
  });
2995
2916
  } catch (error) {
@@ -3001,87 +2922,187 @@ async function callModel(messages, model, options = {}) {
3001
2922
  throw error;
3002
2923
  }
3003
2924
  const choice = data?.choices?.[0];
3004
- const message = choice?.message;
3005
- if (!message) {
3006
- if (attempt === MAX_EMPTY_RETRIES) {
3007
- throw new Error("Invalid response from model: no message in response");
3008
- }
3009
- await new Promise((resolve2) => setTimeout(resolve2, 200));
3010
- continue;
3011
- }
3012
- const toolCalls = (message.tool_calls || []).map((tc) => ({
3013
- id: tc.id,
3014
- type: "function",
3015
- function: { name: tc.function.name, arguments: tc.function.arguments }
3016
- }));
3017
- if (message.content || toolCalls.length > 0) {
3018
- return { content: message.content ?? null, tool_calls: toolCalls };
2925
+ const content = choice?.message?.content;
2926
+ if (content && typeof content === "string") {
2927
+ return content;
3019
2928
  }
3020
2929
  if (attempt === MAX_EMPTY_RETRIES) {
3021
2930
  const finishReason = choice?.finish_reason ?? "unknown";
2931
+ const hasToolCalls = Array.isArray(choice?.message?.tool_calls) && choice.message.tool_calls.length > 0;
2932
+ const choicesLen = data?.choices?.length ?? 0;
2933
+ const contentType = content === null ? "null" : content === void 0 ? "undefined" : typeof content;
3022
2934
  throw new Error(
3023
- `Invalid response from model: no content and no tool_calls, finish_reason=${finishReason}`
2935
+ `Invalid response from model: content=${contentType}, finish_reason=${finishReason}, has_tool_calls=${hasToolCalls}, choices_length=${choicesLen}`
3024
2936
  );
3025
2937
  }
3026
2938
  await new Promise((resolve2) => setTimeout(resolve2, 200));
3027
2939
  }
3028
2940
  throw new Error("Invalid response from model");
3029
2941
  }
3030
- function safeParseJSON(s) {
3031
- try {
3032
- return JSON.parse(s);
3033
- } catch {
3034
- return {};
3035
- }
3036
- }
3037
- async function executeTool(provider, name, args, repoRoot) {
3038
- switch (name) {
3039
- case "grep_search": {
3040
- const grepArgs = {
3041
- pattern: args.pattern,
3042
- path: args.path || "."
3043
- };
3044
- if (args.glob) grepArgs.glob = args.glob;
3045
- if (args.case_sensitive !== void 0) grepArgs.case_sensitive = args.case_sensitive;
3046
- const result = await toolGrep(provider, grepArgs);
3047
- let output = result.output;
3048
- if (args.limit && typeof args.limit === "number") {
3049
- const lines = output.split("\n");
3050
- if (lines.length > args.limit) {
3051
- output = lines.slice(0, args.limit).join("\n") + `
3052
- ... (truncated at ${args.limit} lines)`;
3053
- }
3054
- }
3055
- return output;
2942
+ async function runWarpGrep(config) {
2943
+ const totalStart = Date.now();
2944
+ const timeoutMs = config.timeout ?? AGENT_CONFIG.TIMEOUT_MS;
2945
+ const timings = { turns: [], timeout_ms: timeoutMs };
2946
+ const repoRoot = import_path3.default.resolve(config.repoRoot || process.cwd());
2947
+ const model = config.model || DEFAULT_MODEL;
2948
+ const messages = [];
2949
+ const maxTurns = AGENT_CONFIG.MAX_TURNS;
2950
+ const initialStateStart = Date.now();
2951
+ const initialState = await buildInitialState(repoRoot, config.searchTerm, config.provider, { search_type: config.search_type });
2952
+ timings.initial_state_ms = Date.now() - initialStateStart;
2953
+ messages.push({ role: "user", content: initialState });
2954
+ const provider = config.provider;
2955
+ const errors = [];
2956
+ let finishMeta;
2957
+ let terminationReason = "terminated";
2958
+ for (let turn = 1; turn <= maxTurns; turn += 1) {
2959
+ const turnMetrics = { turn, morph_api_ms: 0, local_tools_ms: 0 };
2960
+ enforceContextLimit(messages);
2961
+ const modelCallStart = Date.now();
2962
+ const assistantContent = await callModel(messages, model, {
2963
+ morphApiKey: config.morphApiKey,
2964
+ morphApiUrl: config.morphApiUrl,
2965
+ retryConfig: config.retryConfig,
2966
+ timeout: timeoutMs,
2967
+ search_type: config.search_type
2968
+ }).catch((e) => {
2969
+ const errMsg = e instanceof Error ? e.message : String(e);
2970
+ console.error(`[warp_grep] Morph API call failed on turn ${turn}:`, errMsg);
2971
+ errors.push({ message: errMsg });
2972
+ return "";
2973
+ });
2974
+ turnMetrics.morph_api_ms = Date.now() - modelCallStart;
2975
+ if (!assistantContent) {
2976
+ console.error(`[warp_grep] Empty response from Morph API on turn ${turn}. Errors so far:`, errors);
2977
+ timings.turns.push(turnMetrics);
2978
+ break;
3056
2979
  }
3057
- case "glob": {
3058
- return toolGlob(provider, {
3059
- pattern: args.pattern,
3060
- path: args.path
3061
- });
2980
+ messages.push({ role: "assistant", content: assistantContent });
2981
+ const toolCalls = parser.parse(assistantContent);
2982
+ if (toolCalls.length === 0) {
2983
+ console.error(`[warp_grep] No tool calls parsed on turn ${turn}. Assistant content (first 500 chars):`, assistantContent.slice(0, 500));
2984
+ errors.push({ message: "No tool calls produced by the model. Your MCP is likely out of date! Update it by running: rm -rf ~/.npm/_npx && npm cache clean --force && npx -y @morphllm/morphmcp@latest" });
2985
+ terminationReason = "terminated";
2986
+ timings.turns.push(turnMetrics);
2987
+ break;
3062
2988
  }
3063
- case "list_directory": {
3064
- const dirPath = extractPathFromCommand(args.command || ".");
3065
- return toolListDirectory(provider, { path: dirPath }, repoRoot);
2989
+ const finishCalls = toolCalls.filter((c) => c.name === "finish");
2990
+ const grepCalls = toolCalls.filter((c) => c.name === "grep");
2991
+ const listDirCalls = toolCalls.filter((c) => c.name === "list_directory");
2992
+ const readCalls = toolCalls.filter((c) => c.name === "read");
2993
+ const skipCalls = toolCalls.filter((c) => c.name === "_skip");
2994
+ const formatted = [];
2995
+ for (const c of skipCalls) {
2996
+ const msg = c.arguments?.message || "Command skipped due to parsing error";
2997
+ formatted.push(msg);
2998
+ }
2999
+ const allPromises = [];
3000
+ for (const c of grepCalls) {
3001
+ const args = c.arguments ?? {};
3002
+ allPromises.push(
3003
+ toolGrep(provider, args).then(
3004
+ ({ output }) => formatAgentToolOutput("grep", args, output),
3005
+ (err) => formatAgentToolOutput("grep", args, String(err), { isError: true })
3006
+ )
3007
+ );
3066
3008
  }
3067
- case "read": {
3068
- const readArgs = {
3069
- path: args.path
3070
- };
3071
- if (args.lines && typeof args.lines === "string") {
3072
- Object.assign(readArgs, parseReadLines(args.lines));
3009
+ for (const c of listDirCalls) {
3010
+ const args = c.arguments ?? {};
3011
+ allPromises.push(
3012
+ toolListDirectory(provider, args).then(
3013
+ (p) => formatAgentToolOutput("list_directory", args, p),
3014
+ (err) => formatAgentToolOutput("list_directory", args, String(err), { isError: true })
3015
+ )
3016
+ );
3017
+ }
3018
+ for (const c of readCalls) {
3019
+ const args = c.arguments ?? {};
3020
+ allPromises.push(
3021
+ toolRead(provider, args).then(
3022
+ (p) => formatAgentToolOutput("read", args, p),
3023
+ (err) => formatAgentToolOutput("read", args, String(err), { isError: true })
3024
+ )
3025
+ );
3026
+ }
3027
+ const toolExecStart = Date.now();
3028
+ const allResults = await Promise.all(allPromises);
3029
+ turnMetrics.local_tools_ms = Date.now() - toolExecStart;
3030
+ for (const result of allResults) {
3031
+ formatted.push(result);
3032
+ }
3033
+ if (formatted.length > 0) {
3034
+ const turnMessage = formatTurnMessage(turn, maxTurns);
3035
+ const contextBudget = calculateContextBudget(messages);
3036
+ messages.push({ role: "user", content: formatted.join("\n") + turnMessage + "\n" + contextBudget });
3037
+ }
3038
+ timings.turns.push(turnMetrics);
3039
+ if (finishCalls.length) {
3040
+ const fc = finishCalls[0];
3041
+ const files = fc.arguments?.files ?? [];
3042
+ const textResult = fc.arguments?.textResult;
3043
+ finishMeta = { files };
3044
+ terminationReason = "completed";
3045
+ if (files.length === 0) {
3046
+ const payload2 = textResult || "No relevant code found.";
3047
+ timings.turns.push(turnMetrics);
3048
+ timings.total_ms = Date.now() - totalStart;
3049
+ return {
3050
+ terminationReason: "completed",
3051
+ messages,
3052
+ finish: { payload: payload2, metadata: finishMeta },
3053
+ timings
3054
+ };
3073
3055
  }
3074
- return toolRead(provider, readArgs);
3056
+ break;
3075
3057
  }
3076
- default:
3077
- return `Unknown tool: ${name}`;
3078
3058
  }
3059
+ if (terminationReason !== "completed" || !finishMeta) {
3060
+ timings.total_ms = Date.now() - totalStart;
3061
+ return { terminationReason, messages, errors, timings };
3062
+ }
3063
+ const parts = ["Relevant context found:"];
3064
+ for (const f of finishMeta.files) {
3065
+ const ranges = f.lines === "*" ? "*" : Array.isArray(f.lines) ? f.lines.map(([s, e]) => `${s}-${e}`).join(", ") : "*";
3066
+ parts.push(`- ${f.path}: ${ranges}`);
3067
+ }
3068
+ const payload = parts.join("\n");
3069
+ const finishResolutionStart = Date.now();
3070
+ const fileReadErrors = [];
3071
+ const resolved = await readFinishFiles(
3072
+ repoRoot,
3073
+ finishMeta.files,
3074
+ async (p, s, e) => {
3075
+ try {
3076
+ const rr = await provider.read({ path: p, start: s, end: e });
3077
+ return rr.lines.map((l) => {
3078
+ const idx = l.indexOf("|");
3079
+ return idx >= 0 ? l.slice(idx + 1) : l;
3080
+ });
3081
+ } catch (err) {
3082
+ const errorMsg = err instanceof Error ? err.message : String(err);
3083
+ fileReadErrors.push({ path: p, error: errorMsg });
3084
+ console.error(`[warp_grep] Failed to read file: ${p} - ${errorMsg}`);
3085
+ return [`[couldn't find: ${p}]`];
3086
+ }
3087
+ }
3088
+ );
3089
+ timings.finish_resolution_ms = Date.now() - finishResolutionStart;
3090
+ if (fileReadErrors.length > 0) {
3091
+ errors.push(...fileReadErrors.map((e) => ({ message: `File read error: ${e.path} - ${e.error}` })));
3092
+ }
3093
+ timings.total_ms = Date.now() - totalStart;
3094
+ return {
3095
+ terminationReason: "completed",
3096
+ messages,
3097
+ finish: { payload, metadata: finishMeta, resolved },
3098
+ timings
3099
+ };
3079
3100
  }
3080
3101
  async function* runWarpGrepStreaming(config) {
3081
3102
  const totalStart = Date.now();
3082
3103
  const timeoutMs = config.timeout ?? AGENT_CONFIG.TIMEOUT_MS;
3083
3104
  const timings = { turns: [], timeout_ms: timeoutMs };
3084
- const repoRoot = import_path4.default.resolve(config.repoRoot || process.cwd());
3105
+ const repoRoot = import_path3.default.resolve(config.repoRoot || process.cwd());
3085
3106
  const model = config.model || DEFAULT_MODEL;
3086
3107
  const messages = [];
3087
3108
  const maxTurns = AGENT_CONFIG.MAX_TURNS;
@@ -3097,7 +3118,7 @@ async function* runWarpGrepStreaming(config) {
3097
3118
  const turnMetrics = { turn, morph_api_ms: 0, local_tools_ms: 0 };
3098
3119
  enforceContextLimit(messages);
3099
3120
  const modelCallStart = Date.now();
3100
- const response = await callModel(messages, model, {
3121
+ const assistantContent = await callModel(messages, model, {
3101
3122
  morphApiKey: config.morphApiKey,
3102
3123
  morphApiUrl: config.morphApiUrl,
3103
3124
  retryConfig: config.retryConfig,
@@ -3105,45 +3126,90 @@ async function* runWarpGrepStreaming(config) {
3105
3126
  search_type: config.search_type
3106
3127
  }).catch((e) => {
3107
3128
  const errMsg = e instanceof Error ? e.message : String(e);
3108
- console.error(`[warp_grep] Morph API call failed on turn ${turn}:`, errMsg);
3129
+ console.error(`[warp_grep:stream] Morph API call failed on turn ${turn}:`, errMsg);
3109
3130
  errors.push({ message: errMsg });
3110
- return null;
3131
+ return "";
3111
3132
  });
3112
3133
  turnMetrics.morph_api_ms = Date.now() - modelCallStart;
3113
- if (!response) {
3134
+ if (!assistantContent) {
3135
+ console.error(`[warp_grep:stream] Empty response from Morph API on turn ${turn}. Errors so far:`, errors);
3114
3136
  timings.turns.push(turnMetrics);
3115
3137
  break;
3116
3138
  }
3117
- const toolCalls = response.tool_calls;
3118
- messages.push({
3119
- role: "assistant",
3120
- content: response.content,
3121
- ...toolCalls.length > 0 ? { tool_calls: toolCalls } : {}
3122
- });
3139
+ messages.push({ role: "assistant", content: assistantContent });
3140
+ const toolCalls = parser.parse(assistantContent);
3123
3141
  if (toolCalls.length === 0) {
3124
- console.error(`[warp_grep] No tool calls on turn ${turn}. Content: ${(response.content || "").slice(0, 500)}`);
3125
- errors.push({ message: "No tool calls produced by the model." });
3142
+ console.error(`[warp_grep:stream] No tool calls parsed on turn ${turn}. Assistant content (first 500 chars):`, assistantContent.slice(0, 500));
3143
+ errors.push({ message: "No tool calls produced by the model. Your MCP is likely out of date! Update it by running: rm -rf ~/.npm/_npx && npm cache clean --force && npx -y @morphllm/morphmcp@latest" });
3126
3144
  terminationReason = "terminated";
3127
3145
  timings.turns.push(turnMetrics);
3128
3146
  break;
3129
3147
  }
3130
3148
  yield {
3131
3149
  turn,
3132
- toolCalls: toolCalls.map((tc) => ({
3133
- name: tc.function.name,
3134
- arguments: safeParseJSON(tc.function.arguments)
3150
+ toolCalls: toolCalls.map((c) => ({
3151
+ name: c.name,
3152
+ arguments: c.arguments ?? {}
3135
3153
  }))
3136
3154
  };
3137
- const finishCall = toolCalls.find((tc) => tc.function.name === "finish");
3138
- if (finishCall) {
3139
- const args = safeParseJSON(finishCall.function.arguments);
3140
- const filesStr = args.files || "";
3141
- const files = parseFinishFiles(filesStr);
3155
+ const finishCalls = toolCalls.filter((c) => c.name === "finish");
3156
+ const grepCalls = toolCalls.filter((c) => c.name === "grep");
3157
+ const listDirCalls = toolCalls.filter((c) => c.name === "list_directory");
3158
+ const readCalls = toolCalls.filter((c) => c.name === "read");
3159
+ const skipCalls = toolCalls.filter((c) => c.name === "_skip");
3160
+ const formatted = [];
3161
+ for (const c of skipCalls) {
3162
+ const msg = c.arguments?.message || "Command skipped due to parsing error";
3163
+ formatted.push(msg);
3164
+ }
3165
+ const allPromises = [];
3166
+ for (const c of grepCalls) {
3167
+ const args = c.arguments ?? {};
3168
+ allPromises.push(
3169
+ toolGrep(provider, args).then(
3170
+ ({ output }) => formatAgentToolOutput("grep", args, output),
3171
+ (err) => formatAgentToolOutput("grep", args, String(err), { isError: true })
3172
+ )
3173
+ );
3174
+ }
3175
+ for (const c of listDirCalls) {
3176
+ const args = c.arguments ?? {};
3177
+ allPromises.push(
3178
+ toolListDirectory(provider, args).then(
3179
+ (p) => formatAgentToolOutput("list_directory", args, p),
3180
+ (err) => formatAgentToolOutput("list_directory", args, String(err), { isError: true })
3181
+ )
3182
+ );
3183
+ }
3184
+ for (const c of readCalls) {
3185
+ const args = c.arguments ?? {};
3186
+ allPromises.push(
3187
+ toolRead(provider, args).then(
3188
+ (p) => formatAgentToolOutput("read", args, p),
3189
+ (err) => formatAgentToolOutput("read", args, String(err), { isError: true })
3190
+ )
3191
+ );
3192
+ }
3193
+ const toolExecStart = Date.now();
3194
+ const allResults = await Promise.all(allPromises);
3195
+ turnMetrics.local_tools_ms = Date.now() - toolExecStart;
3196
+ for (const result of allResults) {
3197
+ formatted.push(result);
3198
+ }
3199
+ if (formatted.length > 0) {
3200
+ const turnMessage = formatTurnMessage(turn, maxTurns);
3201
+ const contextBudget = calculateContextBudget(messages);
3202
+ messages.push({ role: "user", content: formatted.join("\n") + turnMessage + "\n" + contextBudget });
3203
+ }
3204
+ timings.turns.push(turnMetrics);
3205
+ if (finishCalls.length) {
3206
+ const fc = finishCalls[0];
3207
+ const files = fc.arguments?.files ?? [];
3208
+ const textResult = fc.arguments?.textResult;
3142
3209
  finishMeta = { files };
3143
3210
  terminationReason = "completed";
3144
3211
  if (files.length === 0) {
3145
- const payload2 = filesStr || "No relevant code found.";
3146
- timings.turns.push(turnMetrics);
3212
+ const payload2 = textResult || "No relevant code found.";
3147
3213
  timings.total_ms = Date.now() - totalStart;
3148
3214
  return {
3149
3215
  terminationReason: "completed",
@@ -3152,25 +3218,8 @@ async function* runWarpGrepStreaming(config) {
3152
3218
  timings
3153
3219
  };
3154
3220
  }
3155
- timings.turns.push(turnMetrics);
3156
3221
  break;
3157
3222
  }
3158
- const toolExecStart = Date.now();
3159
- const results = await Promise.all(
3160
- toolCalls.map(async (tc) => {
3161
- const args = safeParseJSON(tc.function.arguments);
3162
- const output = await executeTool(provider, tc.function.name, args, repoRoot).catch((err) => String(err));
3163
- return { tool_call_id: tc.id, content: output };
3164
- })
3165
- );
3166
- turnMetrics.local_tools_ms = Date.now() - toolExecStart;
3167
- for (const result of results) {
3168
- messages.push({ role: "tool", tool_call_id: result.tool_call_id, content: result.content });
3169
- }
3170
- const turnMsg = formatTurnMessage(turn, maxTurns);
3171
- const budget = calculateContextBudget(messages);
3172
- messages.push({ role: "user", content: turnMsg + "\n" + budget });
3173
- timings.turns.push(turnMetrics);
3174
3223
  }
3175
3224
  if (terminationReason !== "completed" || !finishMeta) {
3176
3225
  timings.total_ms = Date.now() - totalStart;
@@ -3214,14 +3263,6 @@ async function* runWarpGrepStreaming(config) {
3214
3263
  timings
3215
3264
  };
3216
3265
  }
3217
- async function runWarpGrep(config) {
3218
- const gen = runWarpGrepStreaming(config);
3219
- let result = await gen.next();
3220
- while (!result.done) {
3221
- result = await gen.next();
3222
- }
3223
- return result.value;
3224
- }
3225
3266
 
3226
3267
  // tools/warp_grep/providers/remote.ts
3227
3268
  init_config();
@@ -3401,35 +3442,6 @@ var RemoteCommandsProvider = class {
3401
3442
  return [];
3402
3443
  }
3403
3444
  }
3404
- /**
3405
- * Glob search - finds files matching a pattern.
3406
- * Falls back to a grep --files approach via the listDir command.
3407
- */
3408
- async glob(params) {
3409
- const searchPath = params.path || this.repoRoot;
3410
- try {
3411
- const stdout = await this.commands.listDir(searchPath, 10);
3412
- const allPaths = (stdout || "").trim().split(/\r?\n/).filter((p) => p.length > 0);
3413
- const globToRegex = (glob) => {
3414
- const escaped = glob.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*").replace(/\?/g, ".");
3415
- return new RegExp(escaped);
3416
- };
3417
- const regex = globToRegex(params.pattern);
3418
- const matched = allPaths.filter((p) => {
3419
- const name = p.split("/").pop() || "";
3420
- return regex.test(name) && !shouldSkip(name);
3421
- });
3422
- const totalFound = matched.length;
3423
- return { files: matched.slice(0, 100), searchDir: searchPath, totalFound };
3424
- } catch (error) {
3425
- return {
3426
- files: [],
3427
- searchDir: searchPath,
3428
- totalFound: 0,
3429
- error: `[GLOB ERROR] ${error instanceof Error ? error.message : String(error)}`
3430
- };
3431
- }
3432
- }
3433
3445
  };
3434
3446
 
3435
3447
  // tools/warp_grep/providers/code_storage_http.ts
@@ -3456,9 +3468,9 @@ function createCodeStorageHttpCommands(config) {
3456
3468
  const { baseUrl, repoId, branch } = config;
3457
3469
  const encodedRepoId = encodeURIComponent(repoId);
3458
3470
  return {
3459
- grep: (pattern, path6, glob) => post(`${baseUrl}/api/code-search/${encodedRepoId}/grep`, { pattern, path: path6, glob, branch }, "grep"),
3460
- read: (path6, start, end) => post(`${baseUrl}/api/code-search/${encodedRepoId}/read`, { path: path6, start, end, branch }, "read"),
3461
- listDir: (path6, maxDepth) => post(`${baseUrl}/api/code-search/${encodedRepoId}/list`, { path: path6, maxDepth, branch }, "list")
3471
+ grep: (pattern, path5, glob) => post(`${baseUrl}/api/code-search/${encodedRepoId}/grep`, { pattern, path: path5, glob, branch }, "grep"),
3472
+ read: (path5, start, end) => post(`${baseUrl}/api/code-search/${encodedRepoId}/read`, { path: path5, start, end, branch }, "read"),
3473
+ listDir: (path5, maxDepth) => post(`${baseUrl}/api/code-search/${encodedRepoId}/list`, { path: path5, maxDepth, branch }, "list")
3462
3474
  };
3463
3475
  }
3464
3476
 
@@ -3841,10 +3853,10 @@ var GitHubClient = class {
3841
3853
  /**
3842
3854
  * Make an authenticated API request
3843
3855
  */
3844
- async request(method, path6, body) {
3845
- const url = `${this.baseUrl}${path6}`;
3856
+ async request(method, path5, body) {
3857
+ const url = `${this.baseUrl}${path5}`;
3846
3858
  if (this.debug) {
3847
- console.log(`[GitHub SDK] ${method} ${path6}`, body || "");
3859
+ console.log(`[GitHub SDK] ${method} ${path5}`, body || "");
3848
3860
  }
3849
3861
  const controller = new AbortController();
3850
3862
  const timeoutId = setTimeout(() => controller.abort(), this.timeout);
@@ -6412,25 +6424,6 @@ init_paths();
6412
6424
  // tools/warp_grep/agent/index.ts
6413
6425
  init_config();
6414
6426
 
6415
- // tools/warp_grep/agent/formatter.ts
6416
- var ToolOutputFormatter = class {
6417
- format(toolName, _args, output, options = {}) {
6418
- const name = (toolName ?? "").trim();
6419
- if (!name) {
6420
- return "";
6421
- }
6422
- const payload = output?.toString?.()?.trim?.() ?? "";
6423
- const isError = Boolean(options.isError);
6424
- if (!payload && !isError) {
6425
- return "";
6426
- }
6427
- return `<tool_response>
6428
- ${payload}
6429
- </tool_response>`;
6430
- }
6431
- };
6432
- var sharedFormatter = new ToolOutputFormatter();
6433
-
6434
6427
  // tools/warp_grep/index.ts
6435
6428
  var warpGrepInputSchema = import_zod5.z.object({
6436
6429
  search_term: import_zod5.z.string().describe("Search problem statement that this subagent is supposed to research for")