@morphllm/morphsdk 0.2.138 → 0.2.139

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 (182) hide show
  1. package/dist/{chunk-QU5JVTYQ.js → chunk-3J74OXN6.js} +2 -2
  2. package/dist/chunk-3T5W2D2W.js +288 -0
  3. package/dist/chunk-3T5W2D2W.js.map +1 -0
  4. package/dist/{chunk-MDVFAW4F.js → chunk-4J5UW34J.js} +4 -4
  5. package/dist/{chunk-IMYH4BD2.js → chunk-5CBMLTG5.js} +5 -5
  6. package/dist/{chunk-CXSAPFUD.js → chunk-6W3X76KE.js} +21 -6
  7. package/dist/chunk-6W3X76KE.js.map +1 -0
  8. package/dist/{chunk-HP64WS73.js → chunk-6WSZDCGP.js} +2 -2
  9. package/dist/{chunk-2PU5V3MK.js → chunk-73ZLTWKF.js} +4 -4
  10. package/dist/{chunk-ZK5GJIAX.js → chunk-7RCHQN7F.js} +2 -2
  11. package/dist/{chunk-ZOC7P5RV.js → chunk-ATAQZLQN.js} +2 -2
  12. package/dist/{chunk-GSOXKIQU.js → chunk-B55ZEX4M.js} +2 -2
  13. package/dist/{chunk-QNXGYWS3.js → chunk-DRAQDTSR.js} +2 -2
  14. package/dist/{chunk-G5GPLD2E.js → chunk-EEBGEMOO.js} +2 -2
  15. package/dist/{chunk-H7RABA4R.js → chunk-EHRKLQ62.js} +2 -2
  16. package/dist/chunk-GQX4PKXZ.js +265 -0
  17. package/dist/chunk-GQX4PKXZ.js.map +1 -0
  18. package/dist/{chunk-YOOALIAK.js → chunk-MHNCFELG.js} +4 -4
  19. package/dist/{chunk-DOW7Y3AB.js → chunk-MTD2JOO7.js} +1 -1
  20. package/dist/{chunk-P4FTR3X4.js → chunk-NEVPVOTT.js} +3 -3
  21. package/dist/{chunk-CUPT64F5.js → chunk-NGHLDI64.js} +2 -2
  22. package/dist/{chunk-KWFRPYUW.js → chunk-OICUUS5Y.js} +4 -4
  23. package/dist/{chunk-QNX4PKPV.js → chunk-TCXBKB7P.js} +2 -2
  24. package/dist/{chunk-XIVAX3WB.js → chunk-ULMSWACH.js} +6 -6
  25. package/dist/{chunk-KHHSG2LO.js → chunk-XIEU3N3R.js} +4 -4
  26. package/dist/{chunk-2GSJGZYK.js → chunk-XUDE6SOY.js} +57 -21
  27. package/dist/{chunk-2GSJGZYK.js.map → chunk-XUDE6SOY.js.map} +1 -1
  28. package/dist/{chunk-XLDP5S2P.js → chunk-ZUG2L4BJ.js} +2 -2
  29. package/dist/{chunk-S3CBEA3Y.js → chunk-ZYN64ZVG.js} +4 -4
  30. package/dist/chunk-ZZ25FZG2.js +73 -0
  31. package/dist/chunk-ZZ25FZG2.js.map +1 -0
  32. package/dist/{client-Ca7e11hJ.d.ts → client-BMmG3SZs.d.ts} +39 -0
  33. package/dist/client.cjs +650 -13
  34. package/dist/client.cjs.map +1 -1
  35. package/dist/client.d.ts +2 -1
  36. package/dist/client.js +30 -27
  37. package/dist/edge.cjs +20 -5
  38. package/dist/edge.cjs.map +1 -1
  39. package/dist/edge.js +9 -9
  40. package/dist/index.cjs +653 -16
  41. package/dist/index.cjs.map +1 -1
  42. package/dist/index.d.ts +2 -1
  43. package/dist/index.js +37 -34
  44. package/dist/modelrouter/core.cjs +20 -5
  45. package/dist/modelrouter/core.cjs.map +1 -1
  46. package/dist/modelrouter/core.js +3 -3
  47. package/dist/modelrouter/index.cjs +20 -5
  48. package/dist/modelrouter/index.cjs.map +1 -1
  49. package/dist/modelrouter/index.js +3 -3
  50. package/dist/subagents/anthropic.cjs +2397 -0
  51. package/dist/subagents/anthropic.cjs.map +1 -0
  52. package/dist/subagents/anthropic.d.ts +41 -0
  53. package/dist/subagents/anthropic.js +19 -0
  54. package/dist/subagents/anthropic.js.map +1 -0
  55. package/dist/subagents/index.cjs +101 -0
  56. package/dist/subagents/index.cjs.map +1 -0
  57. package/dist/subagents/index.d.ts +5 -0
  58. package/dist/subagents/index.js +12 -0
  59. package/dist/subagents/index.js.map +1 -0
  60. package/dist/subagents/prompts.cjs +99 -0
  61. package/dist/subagents/prompts.cjs.map +1 -0
  62. package/dist/subagents/prompts.d.ts +42 -0
  63. package/dist/subagents/prompts.js +12 -0
  64. package/dist/subagents/prompts.js.map +1 -0
  65. package/dist/subagents/types.cjs +19 -0
  66. package/dist/subagents/types.cjs.map +1 -0
  67. package/dist/subagents/types.d.ts +93 -0
  68. package/dist/subagents/types.js +1 -0
  69. package/dist/subagents/types.js.map +1 -0
  70. package/dist/subagents/vercel.cjs +2374 -0
  71. package/dist/subagents/vercel.cjs.map +1 -0
  72. package/dist/subagents/vercel.d.ts +32 -0
  73. package/dist/subagents/vercel.js +19 -0
  74. package/dist/subagents/vercel.js.map +1 -0
  75. package/dist/tools/browser/anthropic.cjs +20 -5
  76. package/dist/tools/browser/anthropic.cjs.map +1 -1
  77. package/dist/tools/browser/anthropic.js +6 -6
  78. package/dist/tools/browser/core.cjs +20 -5
  79. package/dist/tools/browser/core.cjs.map +1 -1
  80. package/dist/tools/browser/core.js +5 -5
  81. package/dist/tools/browser/index.cjs +20 -5
  82. package/dist/tools/browser/index.cjs.map +1 -1
  83. package/dist/tools/browser/index.js +15 -15
  84. package/dist/tools/browser/openai.cjs +20 -5
  85. package/dist/tools/browser/openai.cjs.map +1 -1
  86. package/dist/tools/browser/openai.js +6 -6
  87. package/dist/tools/browser/profiles/core.cjs +20 -5
  88. package/dist/tools/browser/profiles/core.cjs.map +1 -1
  89. package/dist/tools/browser/profiles/core.js +3 -3
  90. package/dist/tools/browser/profiles/index.cjs +20 -5
  91. package/dist/tools/browser/profiles/index.cjs.map +1 -1
  92. package/dist/tools/browser/profiles/index.js +3 -3
  93. package/dist/tools/browser/vercel.cjs +20 -5
  94. package/dist/tools/browser/vercel.cjs.map +1 -1
  95. package/dist/tools/browser/vercel.js +6 -6
  96. package/dist/tools/codebase_search/anthropic.cjs +20 -5
  97. package/dist/tools/codebase_search/anthropic.cjs.map +1 -1
  98. package/dist/tools/codebase_search/anthropic.js +4 -4
  99. package/dist/tools/codebase_search/core.cjs +20 -5
  100. package/dist/tools/codebase_search/core.cjs.map +1 -1
  101. package/dist/tools/codebase_search/core.js +3 -3
  102. package/dist/tools/codebase_search/index.cjs +20 -5
  103. package/dist/tools/codebase_search/index.cjs.map +1 -1
  104. package/dist/tools/codebase_search/index.js +10 -10
  105. package/dist/tools/codebase_search/openai.cjs +20 -5
  106. package/dist/tools/codebase_search/openai.cjs.map +1 -1
  107. package/dist/tools/codebase_search/openai.js +4 -4
  108. package/dist/tools/codebase_search/vercel.cjs +20 -5
  109. package/dist/tools/codebase_search/vercel.cjs.map +1 -1
  110. package/dist/tools/codebase_search/vercel.js +4 -4
  111. package/dist/tools/fastapply/anthropic.cjs +20 -5
  112. package/dist/tools/fastapply/anthropic.cjs.map +1 -1
  113. package/dist/tools/fastapply/anthropic.js +4 -4
  114. package/dist/tools/fastapply/apply.cjs +20 -5
  115. package/dist/tools/fastapply/apply.cjs.map +1 -1
  116. package/dist/tools/fastapply/apply.js +2 -2
  117. package/dist/tools/fastapply/core.cjs +20 -5
  118. package/dist/tools/fastapply/core.cjs.map +1 -1
  119. package/dist/tools/fastapply/core.js +3 -3
  120. package/dist/tools/fastapply/index.cjs +20 -5
  121. package/dist/tools/fastapply/index.cjs.map +1 -1
  122. package/dist/tools/fastapply/index.js +8 -8
  123. package/dist/tools/fastapply/openai.cjs +20 -5
  124. package/dist/tools/fastapply/openai.cjs.map +1 -1
  125. package/dist/tools/fastapply/openai.js +4 -4
  126. package/dist/tools/fastapply/vercel.cjs +20 -5
  127. package/dist/tools/fastapply/vercel.cjs.map +1 -1
  128. package/dist/tools/fastapply/vercel.js +4 -4
  129. package/dist/tools/index.cjs +20 -5
  130. package/dist/tools/index.cjs.map +1 -1
  131. package/dist/tools/index.js +8 -8
  132. package/dist/tools/utils/resilience.cjs +20 -5
  133. package/dist/tools/utils/resilience.cjs.map +1 -1
  134. package/dist/tools/utils/resilience.js +2 -2
  135. package/dist/tools/warp_grep/agent/runner.cjs +20 -5
  136. package/dist/tools/warp_grep/agent/runner.cjs.map +1 -1
  137. package/dist/tools/warp_grep/agent/runner.js +3 -3
  138. package/dist/tools/warp_grep/anthropic.cjs +20 -5
  139. package/dist/tools/warp_grep/anthropic.cjs.map +1 -1
  140. package/dist/tools/warp_grep/anthropic.js +6 -6
  141. package/dist/tools/warp_grep/client.cjs +20 -5
  142. package/dist/tools/warp_grep/client.cjs.map +1 -1
  143. package/dist/tools/warp_grep/client.js +5 -5
  144. package/dist/tools/warp_grep/gemini.cjs +20 -5
  145. package/dist/tools/warp_grep/gemini.cjs.map +1 -1
  146. package/dist/tools/warp_grep/gemini.js +5 -5
  147. package/dist/tools/warp_grep/harness.js +4 -4
  148. package/dist/tools/warp_grep/index.cjs +20 -5
  149. package/dist/tools/warp_grep/index.cjs.map +1 -1
  150. package/dist/tools/warp_grep/index.js +7 -7
  151. package/dist/tools/warp_grep/openai.cjs +20 -5
  152. package/dist/tools/warp_grep/openai.cjs.map +1 -1
  153. package/dist/tools/warp_grep/openai.js +6 -6
  154. package/dist/tools/warp_grep/vercel.cjs +20 -5
  155. package/dist/tools/warp_grep/vercel.cjs.map +1 -1
  156. package/dist/tools/warp_grep/vercel.js +6 -6
  157. package/dist/version.cjs +20 -5
  158. package/dist/version.cjs.map +1 -1
  159. package/dist/version.js +1 -1
  160. package/package.json +20 -5
  161. package/dist/chunk-CXSAPFUD.js.map +0 -1
  162. /package/dist/{chunk-QU5JVTYQ.js.map → chunk-3J74OXN6.js.map} +0 -0
  163. /package/dist/{chunk-MDVFAW4F.js.map → chunk-4J5UW34J.js.map} +0 -0
  164. /package/dist/{chunk-IMYH4BD2.js.map → chunk-5CBMLTG5.js.map} +0 -0
  165. /package/dist/{chunk-HP64WS73.js.map → chunk-6WSZDCGP.js.map} +0 -0
  166. /package/dist/{chunk-2PU5V3MK.js.map → chunk-73ZLTWKF.js.map} +0 -0
  167. /package/dist/{chunk-ZK5GJIAX.js.map → chunk-7RCHQN7F.js.map} +0 -0
  168. /package/dist/{chunk-ZOC7P5RV.js.map → chunk-ATAQZLQN.js.map} +0 -0
  169. /package/dist/{chunk-GSOXKIQU.js.map → chunk-B55ZEX4M.js.map} +0 -0
  170. /package/dist/{chunk-QNXGYWS3.js.map → chunk-DRAQDTSR.js.map} +0 -0
  171. /package/dist/{chunk-G5GPLD2E.js.map → chunk-EEBGEMOO.js.map} +0 -0
  172. /package/dist/{chunk-H7RABA4R.js.map → chunk-EHRKLQ62.js.map} +0 -0
  173. /package/dist/{chunk-YOOALIAK.js.map → chunk-MHNCFELG.js.map} +0 -0
  174. /package/dist/{chunk-DOW7Y3AB.js.map → chunk-MTD2JOO7.js.map} +0 -0
  175. /package/dist/{chunk-P4FTR3X4.js.map → chunk-NEVPVOTT.js.map} +0 -0
  176. /package/dist/{chunk-CUPT64F5.js.map → chunk-NGHLDI64.js.map} +0 -0
  177. /package/dist/{chunk-KWFRPYUW.js.map → chunk-OICUUS5Y.js.map} +0 -0
  178. /package/dist/{chunk-QNX4PKPV.js.map → chunk-TCXBKB7P.js.map} +0 -0
  179. /package/dist/{chunk-XIVAX3WB.js.map → chunk-ULMSWACH.js.map} +0 -0
  180. /package/dist/{chunk-KHHSG2LO.js.map → chunk-XIEU3N3R.js.map} +0 -0
  181. /package/dist/{chunk-XLDP5S2P.js.map → chunk-ZUG2L4BJ.js.map} +0 -0
  182. /package/dist/{chunk-S3CBEA3Y.js.map → chunk-ZYN64ZVG.js.map} +0 -0
@@ -0,0 +1,2397 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __esm = (fn, res) => function __init() {
9
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
10
+ };
11
+ var __export = (target, all) => {
12
+ for (var name in all)
13
+ __defProp(target, name, { get: all[name], enumerable: true });
14
+ };
15
+ var __copyProps = (to, from, except, desc) => {
16
+ if (from && typeof from === "object" || typeof from === "function") {
17
+ for (let key of __getOwnPropNames(from))
18
+ if (!__hasOwnProp.call(to, key) && key !== except)
19
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
20
+ }
21
+ return to;
22
+ };
23
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
24
+ // If the importer is in node compatibility mode or this is not an ESM
25
+ // file that has been converted to a CommonJS file using a Babel-
26
+ // compatible transform (i.e. "__esModule" has not been set), then set
27
+ // "default" to the CommonJS "module.exports" for node compatibility.
28
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
29
+ mod
30
+ ));
31
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
32
+
33
+ // tools/warp_grep/agent/config.ts
34
+ var parseEnvTimeout, AGENT_CONFIG, BUILTIN_EXCLUDES, DEFAULT_EXCLUDES, DEFAULT_MODEL;
35
+ var init_config = __esm({
36
+ "tools/warp_grep/agent/config.ts"() {
37
+ "use strict";
38
+ parseEnvTimeout = (envValue, defaultMs) => {
39
+ if (!envValue) return defaultMs;
40
+ const parsed = parseInt(envValue, 10);
41
+ return isNaN(parsed) || parsed <= 0 ? defaultMs : parsed;
42
+ };
43
+ AGENT_CONFIG = {
44
+ MAX_TURNS: 4,
45
+ /** Default timeout for model calls. Can be overridden via MORPH_WARP_GREP_TIMEOUT env var (in ms) */
46
+ TIMEOUT_MS: parseEnvTimeout(process.env.MORPH_WARP_GREP_TIMEOUT, 3e4),
47
+ MAX_CONTEXT_CHARS: 54e4,
48
+ MAX_OUTPUT_LINES: 200,
49
+ MAX_READ_LINES: 800,
50
+ MAX_LIST_DEPTH: 3,
51
+ LIST_TIMEOUT_MS: 2e3
52
+ };
53
+ BUILTIN_EXCLUDES = [
54
+ // Version control
55
+ ".git",
56
+ ".svn",
57
+ ".hg",
58
+ ".bzr",
59
+ // Dependencies
60
+ "node_modules",
61
+ "bower_components",
62
+ ".pnpm",
63
+ ".yarn",
64
+ "vendor",
65
+ "packages",
66
+ "Pods",
67
+ ".bundle",
68
+ // Python
69
+ "__pycache__",
70
+ ".pytest_cache",
71
+ ".mypy_cache",
72
+ ".ruff_cache",
73
+ ".venv",
74
+ "venv",
75
+ ".tox",
76
+ ".nox",
77
+ ".eggs",
78
+ "*.egg-info",
79
+ // Build outputs
80
+ "dist",
81
+ "build",
82
+ "out",
83
+ "output",
84
+ "target",
85
+ "_build",
86
+ ".next",
87
+ ".nuxt",
88
+ ".output",
89
+ ".vercel",
90
+ ".netlify",
91
+ // Cache directories
92
+ ".cache",
93
+ ".parcel-cache",
94
+ ".turbo",
95
+ ".nx",
96
+ ".gradle",
97
+ // IDE/Editor
98
+ ".idea",
99
+ ".vscode",
100
+ ".vs",
101
+ // Coverage
102
+ "coverage",
103
+ ".coverage",
104
+ "htmlcov",
105
+ ".nyc_output",
106
+ // Temporary
107
+ "tmp",
108
+ "temp",
109
+ ".tmp",
110
+ ".temp",
111
+ // Lock files
112
+ "package-lock.json",
113
+ "yarn.lock",
114
+ "pnpm-lock.yaml",
115
+ "bun.lockb",
116
+ "Cargo.lock",
117
+ "Gemfile.lock",
118
+ "poetry.lock",
119
+ // Binary/minified
120
+ "*.min.js",
121
+ "*.min.css",
122
+ "*.bundle.js",
123
+ "*.wasm",
124
+ "*.so",
125
+ "*.dll",
126
+ "*.pyc",
127
+ "*.map",
128
+ "*.js.map",
129
+ // Hidden directories catch-all
130
+ ".*"
131
+ ];
132
+ DEFAULT_EXCLUDES = (process.env.MORPH_WARP_GREP_EXCLUDE || "").split(",").map((s) => s.trim()).filter(Boolean).concat(BUILTIN_EXCLUDES);
133
+ DEFAULT_MODEL = "morph-warp-grep-v2";
134
+ }
135
+ });
136
+
137
+ // tools/warp_grep/utils/ripgrep.ts
138
+ function spawnRg(rgBinary, args, opts) {
139
+ return new Promise((resolve) => {
140
+ const child = (0, import_child_process.spawn)(rgBinary, args, {
141
+ cwd: opts?.cwd,
142
+ env: { ...process.env, ...opts?.env || {} },
143
+ stdio: ["ignore", "pipe", "pipe"]
144
+ });
145
+ let stdout = "";
146
+ let stderr = "";
147
+ child.stdout.on("data", (d) => stdout += d.toString());
148
+ child.stderr.on("data", (d) => stderr += d.toString());
149
+ child.on("close", (code) => {
150
+ resolve({ stdout, stderr, exitCode: typeof code === "number" ? code : -1 });
151
+ });
152
+ child.on("error", () => {
153
+ resolve({ stdout: "", stderr: "Failed to spawn ripgrep.", exitCode: -1 });
154
+ });
155
+ });
156
+ }
157
+ function isBinaryFailure(result) {
158
+ if (result.exitCode === -1) return true;
159
+ if (result.stderr.includes("jemalloc") || result.stderr.includes("Unsupported system page size")) return true;
160
+ if (result.exitCode === 134) return true;
161
+ return false;
162
+ }
163
+ async function runRipgrep(args, opts) {
164
+ if (rgPathChecked && resolvedRgPath) {
165
+ return spawnRg(resolvedRgPath, args, opts);
166
+ }
167
+ if (!rgPathChecked) {
168
+ const result = await spawnRg(import_ripgrep.rgPath, args, opts);
169
+ if (!isBinaryFailure(result)) {
170
+ resolvedRgPath = import_ripgrep.rgPath;
171
+ rgPathChecked = true;
172
+ return result;
173
+ }
174
+ const fallbackResult = await spawnRg("rg", args, opts);
175
+ if (!isBinaryFailure(fallbackResult)) {
176
+ resolvedRgPath = "rg";
177
+ rgPathChecked = true;
178
+ return fallbackResult;
179
+ }
180
+ rgPathChecked = true;
181
+ return {
182
+ stdout: "",
183
+ stderr: "Failed to spawn ripgrep. Neither bundled nor system rg is available.",
184
+ exitCode: -1
185
+ };
186
+ }
187
+ return {
188
+ stdout: "",
189
+ stderr: "Failed to spawn ripgrep. Neither bundled nor system rg is available.",
190
+ exitCode: -1
191
+ };
192
+ }
193
+ var import_child_process, import_ripgrep, resolvedRgPath, rgPathChecked;
194
+ var init_ripgrep = __esm({
195
+ "tools/warp_grep/utils/ripgrep.ts"() {
196
+ "use strict";
197
+ import_child_process = require("child_process");
198
+ import_ripgrep = require("@vscode/ripgrep");
199
+ resolvedRgPath = null;
200
+ rgPathChecked = false;
201
+ }
202
+ });
203
+
204
+ // tools/warp_grep/utils/paths.ts
205
+ function resolveUnderRepo(repoRoot, targetPath) {
206
+ const absRoot = import_path3.default.resolve(repoRoot);
207
+ const resolved = import_path3.default.resolve(absRoot, targetPath);
208
+ ensureWithinRepo(absRoot, resolved);
209
+ return resolved;
210
+ }
211
+ function ensureWithinRepo(repoRoot, absTarget) {
212
+ const rel = import_path3.default.relative(import_path3.default.resolve(repoRoot), import_path3.default.resolve(absTarget));
213
+ if (rel.startsWith("..") || import_path3.default.isAbsolute(rel)) {
214
+ throw new Error(`Path outside repository root: ${absTarget}`);
215
+ }
216
+ }
217
+ function toRepoRelative(repoRoot, absPath) {
218
+ return import_path3.default.relative(import_path3.default.resolve(repoRoot), import_path3.default.resolve(absPath));
219
+ }
220
+ function isSymlink(p) {
221
+ try {
222
+ const st = import_fs.default.lstatSync(p);
223
+ return st.isSymbolicLink();
224
+ } catch {
225
+ return false;
226
+ }
227
+ }
228
+ function fixPathRepetition(fullPath) {
229
+ const segments = fullPath.split(import_path3.default.sep).filter(Boolean);
230
+ if (segments.length < 2) return null;
231
+ for (let len = Math.floor(segments.length / 2); len >= 1; len--) {
232
+ for (let i = 0; i <= segments.length - 2 * len; i++) {
233
+ const first = segments.slice(i, i + len);
234
+ const second = segments.slice(i + len, i + 2 * len);
235
+ if (first.every((seg, idx) => seg === second[idx])) {
236
+ const fixed = [...segments.slice(0, i), ...segments.slice(i + len)];
237
+ return import_path3.default.sep + fixed.join(import_path3.default.sep);
238
+ }
239
+ }
240
+ }
241
+ return null;
242
+ }
243
+ function isTextualFile(filePath, maxBytes = 2e6) {
244
+ try {
245
+ const st = import_fs.default.statSync(filePath);
246
+ if (!st.isFile()) return false;
247
+ if (st.size > maxBytes) return false;
248
+ const fd = import_fs.default.openSync(filePath, "r");
249
+ const buf = Buffer.alloc(512);
250
+ const read = import_fs.default.readSync(fd, buf, 0, buf.length, 0);
251
+ import_fs.default.closeSync(fd);
252
+ for (let i = 0; i < read; i++) {
253
+ const c = buf[i];
254
+ if (c === 0) return false;
255
+ }
256
+ return true;
257
+ } catch {
258
+ return false;
259
+ }
260
+ }
261
+ var import_fs, import_path3;
262
+ var init_paths = __esm({
263
+ "tools/warp_grep/utils/paths.ts"() {
264
+ "use strict";
265
+ import_fs = __toESM(require("fs"), 1);
266
+ import_path3 = __toESM(require("path"), 1);
267
+ }
268
+ });
269
+
270
+ // tools/warp_grep/utils/files.ts
271
+ async function readAllLines(filePath) {
272
+ const content = await import_promises.default.readFile(filePath, "utf8");
273
+ return content.split(/\r?\n/);
274
+ }
275
+ var import_promises;
276
+ var init_files = __esm({
277
+ "tools/warp_grep/utils/files.ts"() {
278
+ "use strict";
279
+ import_promises = __toESM(require("fs/promises"), 1);
280
+ }
281
+ });
282
+
283
+ // tools/warp_grep/providers/local.ts
284
+ var local_exports = {};
285
+ __export(local_exports, {
286
+ LocalRipgrepProvider: () => LocalRipgrepProvider
287
+ });
288
+ function shouldSkip2(name, allowNames) {
289
+ if (allowNames?.has(name)) return false;
290
+ if (SKIP_NAMES2.has(name)) return true;
291
+ if (name.startsWith(".")) return true;
292
+ for (const ext of SKIP_EXTENSIONS2) {
293
+ if (name.endsWith(ext)) return true;
294
+ }
295
+ return false;
296
+ }
297
+ var import_promises2, import_path4, SKIP_NAMES2, SKIP_EXTENSIONS2, LocalRipgrepProvider;
298
+ var init_local = __esm({
299
+ "tools/warp_grep/providers/local.ts"() {
300
+ "use strict";
301
+ import_promises2 = __toESM(require("fs/promises"), 1);
302
+ import_path4 = __toESM(require("path"), 1);
303
+ init_ripgrep();
304
+ init_paths();
305
+ init_files();
306
+ init_config();
307
+ SKIP_NAMES2 = /* @__PURE__ */ new Set([
308
+ // Version control
309
+ ".git",
310
+ ".svn",
311
+ ".hg",
312
+ ".bzr",
313
+ // Dependencies
314
+ "node_modules",
315
+ "bower_components",
316
+ ".pnpm",
317
+ ".yarn",
318
+ "vendor",
319
+ "Pods",
320
+ ".bundle",
321
+ // Python
322
+ "__pycache__",
323
+ ".pytest_cache",
324
+ ".mypy_cache",
325
+ ".ruff_cache",
326
+ ".venv",
327
+ "venv",
328
+ ".tox",
329
+ ".nox",
330
+ ".eggs",
331
+ // Build outputs
332
+ "dist",
333
+ "build",
334
+ "out",
335
+ "output",
336
+ "target",
337
+ "_build",
338
+ ".next",
339
+ ".nuxt",
340
+ ".output",
341
+ ".vercel",
342
+ ".netlify",
343
+ // Cache
344
+ ".cache",
345
+ ".parcel-cache",
346
+ ".turbo",
347
+ ".nx",
348
+ ".gradle",
349
+ // IDE
350
+ ".idea",
351
+ ".vscode",
352
+ ".vs",
353
+ // Coverage
354
+ "coverage",
355
+ ".coverage",
356
+ "htmlcov",
357
+ ".nyc_output",
358
+ // Temp
359
+ "tmp",
360
+ "temp",
361
+ ".tmp",
362
+ ".temp",
363
+ // Lock files
364
+ "package-lock.json",
365
+ "yarn.lock",
366
+ "pnpm-lock.yaml",
367
+ "bun.lockb",
368
+ "Cargo.lock",
369
+ "Gemfile.lock",
370
+ "poetry.lock"
371
+ ]);
372
+ SKIP_EXTENSIONS2 = /* @__PURE__ */ new Set([
373
+ ".min.js",
374
+ ".min.css",
375
+ ".bundle.js",
376
+ ".wasm",
377
+ ".so",
378
+ ".dll",
379
+ ".pyc",
380
+ ".map",
381
+ ".js.map"
382
+ ]);
383
+ LocalRipgrepProvider = class {
384
+ constructor(repoRoot, excludes = DEFAULT_EXCLUDES, options) {
385
+ this.repoRoot = repoRoot;
386
+ this.excludes = excludes;
387
+ if (options?.allowNames?.length) {
388
+ this.allowNames = new Set(options.allowNames);
389
+ }
390
+ }
391
+ allowNames;
392
+ async grep(params) {
393
+ let abs;
394
+ try {
395
+ abs = resolveUnderRepo(this.repoRoot, params.path);
396
+ } catch (err) {
397
+ return {
398
+ lines: [],
399
+ error: `[PATH ERROR] ${err instanceof Error ? err.message : String(err)}`
400
+ };
401
+ }
402
+ const stat = await import_promises2.default.stat(abs).catch(() => null);
403
+ if (!stat) return { lines: [] };
404
+ const targetArg = abs === import_path4.default.resolve(this.repoRoot) ? "." : toRepoRelative(this.repoRoot, abs);
405
+ const contextLines = params.context_lines !== void 0 ? String(params.context_lines) : "1";
406
+ const args = [
407
+ "--no-config",
408
+ "--no-heading",
409
+ "--with-filename",
410
+ "--line-number",
411
+ "--color=never",
412
+ "--trim",
413
+ "--max-columns=400",
414
+ "-C",
415
+ contextLines,
416
+ ...params.case_sensitive === false ? ["--ignore-case"] : [],
417
+ ...params.glob ? ["--glob", params.glob] : [],
418
+ ...this.excludes.filter((e) => !this.allowNames?.has(e)).flatMap((e) => ["-g", `!${e}`]),
419
+ params.pattern,
420
+ targetArg || "."
421
+ ];
422
+ const res = await runRipgrep(args, { cwd: this.repoRoot });
423
+ if (res.exitCode === -1) {
424
+ return {
425
+ lines: [],
426
+ error: `[RIPGREP NOT AVAILABLE] ripgrep (rg) is required but failed to execute. Please install it:
427
+ \u2022 macOS: brew install ripgrep
428
+ \u2022 Ubuntu/Debian: apt install ripgrep
429
+ \u2022 Windows: choco install ripgrep
430
+ \u2022 Or visit: https://github.com/BurntSushi/ripgrep#installation
431
+ Exit code: ${res.exitCode}${res.stderr ? `
432
+ Details: ${res.stderr}` : ""}`
433
+ };
434
+ }
435
+ if (res.exitCode !== 0 && res.exitCode !== 1) {
436
+ return {
437
+ lines: [],
438
+ error: `[RIPGREP ERROR] grep failed with exit code ${res.exitCode}${res.stderr ? `: ${res.stderr}` : ""}`
439
+ };
440
+ }
441
+ const lines = (res.stdout || "").trim().split(/\r?\n/).filter((l) => l.length > 0);
442
+ if (lines.length > AGENT_CONFIG.MAX_OUTPUT_LINES) {
443
+ const truncated = lines.slice(0, AGENT_CONFIG.MAX_OUTPUT_LINES);
444
+ truncated.push(`... (output truncated at ${AGENT_CONFIG.MAX_OUTPUT_LINES} of ${lines.length} lines)`);
445
+ return { lines: truncated };
446
+ }
447
+ return { lines };
448
+ }
449
+ async read(params) {
450
+ let abs;
451
+ try {
452
+ abs = resolveUnderRepo(this.repoRoot, params.path);
453
+ } catch (err) {
454
+ return {
455
+ lines: [],
456
+ error: `[PATH ERROR] ${err instanceof Error ? err.message : String(err)}`
457
+ };
458
+ }
459
+ let stat = await import_promises2.default.stat(abs).catch(() => null);
460
+ if (!stat || !stat.isFile()) {
461
+ const fixedPath = fixPathRepetition(abs);
462
+ if (fixedPath) {
463
+ const fixedStat = await import_promises2.default.stat(fixedPath).catch(() => null);
464
+ if (fixedStat?.isFile()) {
465
+ abs = fixedPath;
466
+ stat = fixedStat;
467
+ }
468
+ }
469
+ }
470
+ if (!stat || !stat.isFile()) {
471
+ return {
472
+ lines: [],
473
+ error: `[FILE NOT FOUND] You tried to read "${params.path}" but there is no file at this path. Double-check the path exists and is spelled correctly.`
474
+ };
475
+ }
476
+ if (isSymlink(abs)) {
477
+ return {
478
+ lines: [],
479
+ error: `[SYMLINK] You tried to read "${params.path}" but this is a symlink. Try reading the actual file it points to instead.`
480
+ };
481
+ }
482
+ if (!isTextualFile(abs)) {
483
+ return {
484
+ lines: [],
485
+ error: `[UNREADABLE FILE] You tried to read "${params.path}" but this file is either too large or not a text file, so it cannot be read. Try a different file.`
486
+ };
487
+ }
488
+ let lines;
489
+ try {
490
+ lines = await readAllLines(abs);
491
+ } catch (err) {
492
+ return {
493
+ lines: [],
494
+ error: `[READ ERROR] Failed to read "${params.path}": ${err instanceof Error ? err.message : String(err)}`
495
+ };
496
+ }
497
+ const total = lines.length;
498
+ const rawStart = params.start;
499
+ const rawEnd = params.end;
500
+ let s = 1;
501
+ let e = total;
502
+ const startValid = rawStart === void 0 || Number.isFinite(rawStart) && rawStart > 0;
503
+ const endValid = rawEnd === void 0 || Number.isFinite(rawEnd) && rawEnd > 0;
504
+ if (startValid && endValid) {
505
+ s = rawStart ?? 1;
506
+ e = Math.min(rawEnd ?? total, total);
507
+ if (s > total && total > 0 || s > e) {
508
+ s = 1;
509
+ e = total;
510
+ }
511
+ }
512
+ const out = [];
513
+ for (let i = s; i <= e; i += 1) {
514
+ const content = lines[i - 1] ?? "";
515
+ out.push(`${i}|${content}`);
516
+ }
517
+ if (out.length > AGENT_CONFIG.MAX_READ_LINES) {
518
+ const truncated = out.slice(0, AGENT_CONFIG.MAX_READ_LINES);
519
+ truncated.push(`... (output truncated at ${AGENT_CONFIG.MAX_READ_LINES} of ${out.length} lines)`);
520
+ return { lines: truncated };
521
+ }
522
+ return { lines: out };
523
+ }
524
+ async listDirectory(params) {
525
+ let abs;
526
+ try {
527
+ abs = resolveUnderRepo(this.repoRoot, params.path);
528
+ } catch {
529
+ return [];
530
+ }
531
+ const stat = await import_promises2.default.stat(abs).catch(() => null);
532
+ if (!stat || !stat.isDirectory()) {
533
+ return [];
534
+ }
535
+ const maxResults = params.maxResults ?? AGENT_CONFIG.MAX_OUTPUT_LINES;
536
+ const maxDepth = params.maxDepth ?? AGENT_CONFIG.MAX_LIST_DEPTH;
537
+ const regex = params.pattern ? new RegExp(params.pattern) : null;
538
+ const repoRoot = this.repoRoot;
539
+ const allowNames = this.allowNames;
540
+ const results = [];
541
+ let timedOut = false;
542
+ const startTime = Date.now();
543
+ async function walk(dir, depth) {
544
+ if (Date.now() - startTime > AGENT_CONFIG.LIST_TIMEOUT_MS) {
545
+ timedOut = true;
546
+ return;
547
+ }
548
+ if (depth > maxDepth || results.length >= maxResults) return;
549
+ let entries;
550
+ try {
551
+ entries = await import_promises2.default.readdir(dir, { withFileTypes: true });
552
+ } catch {
553
+ return;
554
+ }
555
+ for (const entry of entries) {
556
+ if (timedOut || results.length >= maxResults) break;
557
+ if (shouldSkip2(entry.name, allowNames)) continue;
558
+ if (regex && !regex.test(entry.name)) continue;
559
+ const full = import_path4.default.join(dir, entry.name);
560
+ const isDir = entry.isDirectory();
561
+ results.push({
562
+ name: entry.name,
563
+ path: toRepoRelative(repoRoot, full),
564
+ type: isDir ? "dir" : "file",
565
+ depth
566
+ });
567
+ if (isDir) {
568
+ await walk(full, depth + 1);
569
+ }
570
+ }
571
+ }
572
+ await walk(abs, 0);
573
+ return results;
574
+ }
575
+ };
576
+ }
577
+ });
578
+
579
+ // subagents/anthropic.ts
580
+ var anthropic_exports = {};
581
+ __export(anthropic_exports, {
582
+ createExploreSubagent: () => createExploreSubagent
583
+ });
584
+ module.exports = __toCommonJS(anthropic_exports);
585
+
586
+ // tools/warp_grep/agent/runner.ts
587
+ init_config();
588
+
589
+ // tools/warp_grep/agent/parser.ts
590
+ var VALID_COMMANDS = ["list_directory", "ripgrep", "read", "finish"];
591
+ function isValidCommand(name) {
592
+ return VALID_COMMANDS.includes(name);
593
+ }
594
+ function parseQwen3ToolCalls(text) {
595
+ const tools = [];
596
+ const toolCallRegex = /<tool_call>\s*<function=([a-z_][a-z0-9_]*)>([\s\S]*?)<\/function>\s*<\/tool_call>/gi;
597
+ let match;
598
+ while ((match = toolCallRegex.exec(text)) !== null) {
599
+ const funcName = match[1].toLowerCase();
600
+ const body = match[2];
601
+ if (!isValidCommand(funcName)) continue;
602
+ const params = {};
603
+ const paramRegex = /<parameter=([a-z_][a-z0-9_]*)>([\s\S]*?)<\/parameter>/gi;
604
+ let paramMatch;
605
+ while ((paramMatch = paramRegex.exec(body)) !== null) {
606
+ params[paramMatch[1].toLowerCase()] = paramMatch[2].trim();
607
+ }
608
+ if (funcName === "ripgrep") {
609
+ const pattern = params.pattern;
610
+ if (!pattern) continue;
611
+ const args = {
612
+ pattern,
613
+ path: params.path || ".",
614
+ ...params.glob && { glob: params.glob },
615
+ ...params.context_lines && { context_lines: parseInt(params.context_lines, 10) },
616
+ ...params.case_sensitive && { case_sensitive: params.case_sensitive === "true" }
617
+ };
618
+ tools.push({ name: "grep", arguments: args });
619
+ } else if (funcName === "list_directory") {
620
+ const command = params.command;
621
+ const directPath = params.path;
622
+ let dirPath = directPath || ".";
623
+ if (!directPath && command) {
624
+ const tokens = command.trim().split(/\s+/);
625
+ const pathTokens = tokens.slice(1).filter((t) => !t.startsWith("-") && !t.startsWith("|") && !t.startsWith("\\("));
626
+ if (pathTokens.length > 0) {
627
+ dirPath = pathTokens[0];
628
+ }
629
+ }
630
+ tools.push({ name: "list_directory", arguments: { path: dirPath, pattern: params.pattern || null } });
631
+ } else if (funcName === "read") {
632
+ const filePath = params.path;
633
+ if (!filePath) continue;
634
+ const args = { path: filePath };
635
+ const linesStr = params.lines;
636
+ if (linesStr) {
637
+ const ranges = [];
638
+ for (const rangeStr of linesStr.split(",")) {
639
+ const trimmed = rangeStr.trim();
640
+ if (!trimmed) continue;
641
+ const [s, e] = trimmed.split("-").map((v) => parseInt(v.trim(), 10));
642
+ if (Number.isFinite(s) && Number.isFinite(e)) {
643
+ ranges.push([s, e]);
644
+ } else if (Number.isFinite(s)) {
645
+ ranges.push([s, s]);
646
+ }
647
+ }
648
+ if (ranges.length === 1) {
649
+ args.start = ranges[0][0];
650
+ args.end = ranges[0][1];
651
+ } else if (ranges.length > 1) {
652
+ args.lines = ranges;
653
+ }
654
+ }
655
+ tools.push({ name: "read", arguments: args });
656
+ } else if (funcName === "finish") {
657
+ if (params.result && !params.files) {
658
+ tools.push({ name: "finish", arguments: { files: [], textResult: params.result } });
659
+ continue;
660
+ }
661
+ const filesStr = params.files;
662
+ if (!filesStr) {
663
+ tools.push({ name: "finish", arguments: { files: [], textResult: "No relevant code found." } });
664
+ continue;
665
+ }
666
+ const files = [];
667
+ for (const line of filesStr.split("\n")) {
668
+ const trimmed = line.trim();
669
+ if (!trimmed) continue;
670
+ const colonIdx = trimmed.indexOf(":");
671
+ if (colonIdx === -1) {
672
+ files.push({ path: trimmed, lines: "*" });
673
+ } else {
674
+ const filePath = trimmed.slice(0, colonIdx);
675
+ const rangesPart = trimmed.slice(colonIdx + 1);
676
+ const ranges = [];
677
+ for (const rangeStr of rangesPart.split(",")) {
678
+ const rt = rangeStr.trim();
679
+ if (!rt || rt === "*") {
680
+ files.push({ path: filePath, lines: "*" });
681
+ break;
682
+ }
683
+ const [s, e] = rt.split("-").map((v) => parseInt(v.trim(), 10));
684
+ if (Number.isFinite(s) && Number.isFinite(e)) {
685
+ ranges.push([s, e]);
686
+ } else if (Number.isFinite(s)) {
687
+ ranges.push([s, s]);
688
+ }
689
+ }
690
+ if (ranges.length > 0) {
691
+ files.push({ path: filePath, lines: ranges });
692
+ } else if (!files.some((f) => f.path === filePath)) {
693
+ files.push({ path: filePath, lines: "*" });
694
+ }
695
+ }
696
+ }
697
+ if (files.length > 0) {
698
+ tools.push({ name: "finish", arguments: { files } });
699
+ } else {
700
+ tools.push({ name: "finish", arguments: { files: [], textResult: filesStr } });
701
+ }
702
+ }
703
+ }
704
+ return tools;
705
+ }
706
+ var LLMResponseParser = class {
707
+ parse(text) {
708
+ if (typeof text !== "string") {
709
+ throw new TypeError("Command text must be a string.");
710
+ }
711
+ const withoutThink = text.replace(/<think>[\s\S]*?<\/think>/gi, "");
712
+ return parseQwen3ToolCalls(withoutThink);
713
+ }
714
+ };
715
+
716
+ // tools/warp_grep/agent/tools/grep.ts
717
+ async function toolGrep(provider, args) {
718
+ const res = await provider.grep(args);
719
+ if (res.error) {
720
+ return { output: res.error };
721
+ }
722
+ if (!res.lines.length) {
723
+ return { output: "no matches" };
724
+ }
725
+ return { output: res.lines.join("\n") };
726
+ }
727
+
728
+ // tools/warp_grep/agent/tools/read.ts
729
+ function isValidRange(start, end) {
730
+ return typeof start === "number" && typeof end === "number" && Number.isFinite(start) && Number.isFinite(end) && start > 0 && end >= start;
731
+ }
732
+ async function toolRead(provider, args) {
733
+ if (args.lines && Array.isArray(args.lines) && args.lines.length > 0) {
734
+ const validRanges = [];
735
+ for (const range of args.lines) {
736
+ if (Array.isArray(range) && range.length >= 2 && isValidRange(range[0], range[1])) {
737
+ validRanges.push([range[0], range[1]]);
738
+ }
739
+ }
740
+ if (validRanges.length === 0) {
741
+ const res2 = await provider.read({ path: args.path });
742
+ if (res2.error) return res2.error;
743
+ if (!res2.lines.length) return "(empty file)";
744
+ return res2.lines.join("\n");
745
+ }
746
+ const chunks = [];
747
+ for (const [start, end] of validRanges) {
748
+ const res2 = await provider.read({ path: args.path, start, end });
749
+ if (res2.error) return res2.error;
750
+ chunks.push(res2.lines.join("\n"));
751
+ }
752
+ if (chunks.every((c) => c === "")) return "(empty file)";
753
+ return chunks.join("\n...\n");
754
+ }
755
+ const res = await provider.read({ path: args.path, start: args.start, end: args.end });
756
+ if (res.error) {
757
+ return res.error;
758
+ }
759
+ if (!res.lines.length) return "(empty file)";
760
+ return res.lines.join("\n");
761
+ }
762
+
763
+ // tools/warp_grep/agent/tools/list_directory.ts
764
+ init_config();
765
+ async function toolListDirectory(provider, args) {
766
+ const maxResults = args.maxResults ?? AGENT_CONFIG.MAX_OUTPUT_LINES;
767
+ const initialDepth = args.maxDepth ?? AGENT_CONFIG.MAX_LIST_DEPTH;
768
+ async function getListRecursive(currentDepth) {
769
+ const entries = await provider.listDirectory({
770
+ path: args.path,
771
+ pattern: args.pattern ?? null,
772
+ maxResults,
773
+ maxDepth: currentDepth
774
+ });
775
+ if (entries.length >= maxResults && currentDepth > 0) {
776
+ return getListRecursive(currentDepth - 1);
777
+ }
778
+ return { entries };
779
+ }
780
+ const { entries: list } = await getListRecursive(initialDepth);
781
+ if (!list.length) return "empty";
782
+ const tree = list.map((e) => {
783
+ const indent = " ".repeat(e.depth);
784
+ const name = e.type === "dir" ? `${e.name}/` : e.name;
785
+ return `${indent}${name}`;
786
+ }).join("\n");
787
+ return tree;
788
+ }
789
+
790
+ // tools/warp_grep/agent/tools/finish.ts
791
+ function isValidRange2(range) {
792
+ return Array.isArray(range) && range.length >= 2 && typeof range[0] === "number" && typeof range[1] === "number" && Number.isFinite(range[0]) && Number.isFinite(range[1]) && range[0] > 0 && range[1] >= range[0];
793
+ }
794
+ function extractValidRanges(lines) {
795
+ if (!Array.isArray(lines)) return null;
796
+ const valid = [];
797
+ for (const range of lines) {
798
+ if (isValidRange2(range)) {
799
+ valid.push([range[0], range[1]]);
800
+ }
801
+ }
802
+ return valid.length > 0 ? valid : null;
803
+ }
804
+ async function readFinishFiles(repoRoot, files, reader) {
805
+ const out = [];
806
+ for (const f of files) {
807
+ const validRanges = f.lines === "*" ? null : extractValidRanges(f.lines);
808
+ if (f.lines === "*" || !validRanges) {
809
+ const lines = await reader(f.path);
810
+ out.push({ path: f.path, ranges: "*", content: lines.join("\n") });
811
+ } else {
812
+ const ranges = mergeRanges(validRanges);
813
+ const chunks = [];
814
+ for (let i = 0; i < ranges.length; i++) {
815
+ const [s, e] = ranges[i];
816
+ if (i === 0 && s > 1) {
817
+ chunks.push(`// ... existing code, block starting at line ${s} ...`);
818
+ } else if (i > 0) {
819
+ chunks.push(`// ... existing code, block starting at line ${s} ...`);
820
+ }
821
+ const lines = await reader(f.path, s, e);
822
+ chunks.push(lines.join("\n"));
823
+ }
824
+ out.push({ path: f.path, ranges, content: chunks.join("\n") });
825
+ }
826
+ }
827
+ return out;
828
+ }
829
+ function mergeRanges(ranges) {
830
+ if (!ranges.length) return [];
831
+ const sorted = [...ranges].sort((a, b) => a[0] - b[0]);
832
+ const merged = [];
833
+ let [cs, ce] = sorted[0];
834
+ for (let i = 1; i < sorted.length; i++) {
835
+ const [s, e] = sorted[i];
836
+ if (s <= ce + 1) {
837
+ ce = Math.max(ce, e);
838
+ } else {
839
+ merged.push([cs, ce]);
840
+ cs = s;
841
+ ce = e;
842
+ }
843
+ }
844
+ merged.push([cs, ce]);
845
+ return merged;
846
+ }
847
+
848
+ // tools/warp_grep/agent/formatter.ts
849
+ var ToolOutputFormatter = class {
850
+ format(toolName, _args, output, options = {}) {
851
+ const name = (toolName ?? "").trim();
852
+ if (!name) {
853
+ return "";
854
+ }
855
+ const payload = output?.toString?.()?.trim?.() ?? "";
856
+ const isError = Boolean(options.isError);
857
+ if (!payload && !isError) {
858
+ return "";
859
+ }
860
+ return `<tool_response>
861
+ ${payload}
862
+ </tool_response>`;
863
+ }
864
+ };
865
+ var sharedFormatter = new ToolOutputFormatter();
866
+ function formatAgentToolOutput(toolName, args, output, options = {}) {
867
+ return sharedFormatter.format(toolName, args, output, options);
868
+ }
869
+
870
+ // tools/warp_grep/agent/helpers.ts
871
+ var import_path = __toESM(require("path"), 1);
872
+ init_config();
873
+ var TRUNCATED_MARKER = "[truncated for context limit]";
874
+ function formatTurnMessage(turnsUsed, maxTurns) {
875
+ const turnsRemaining = maxTurns - turnsUsed;
876
+ if (turnsRemaining === 1) {
877
+ return `
878
+ You have used ${turnsUsed} turns, you only have 1 turn remaining. You have run out of turns to explore the code base and MUST call the finish tool now`;
879
+ }
880
+ return `
881
+ You have used ${turnsUsed} turn${turnsUsed === 1 ? "" : "s"} and have ${turnsRemaining} remaining`;
882
+ }
883
+ function calculateContextBudget(messages) {
884
+ const totalChars = messages.reduce((sum, m) => sum + m.content.length, 0);
885
+ const maxChars = AGENT_CONFIG.MAX_CONTEXT_CHARS;
886
+ const percent = Math.round(totalChars / maxChars * 100);
887
+ const usedK = Math.round(totalChars / 1e3);
888
+ const maxK = Math.round(maxChars / 1e3);
889
+ return `<context_budget>${percent}% (${usedK}K/${maxK}K chars)</context_budget>`;
890
+ }
891
+ async function buildInitialState(repoRoot, searchTerm, provider, options) {
892
+ const budget = calculateContextBudget([]);
893
+ const turnTag = `Turn 0/${AGENT_CONFIG.MAX_TURNS}`;
894
+ const treeDepth = options?.search_type === "node_modules" ? 1 : 2;
895
+ try {
896
+ const entries = await provider.listDirectory({
897
+ path: ".",
898
+ maxResults: AGENT_CONFIG.MAX_OUTPUT_LINES,
899
+ maxDepth: treeDepth
900
+ });
901
+ const treeLines = entries.map((e) => {
902
+ const indent = " ".repeat(e.depth);
903
+ const name = e.type === "dir" ? `${e.name}/` : e.name;
904
+ return `${indent}${name}`;
905
+ });
906
+ const repoName = import_path.default.basename(repoRoot);
907
+ const treeOutput = treeLines.length > 0 ? `${repoName}/
908
+ ${treeLines.join("\n")}` : `${repoName}/`;
909
+ return `<repo_structure>
910
+ ${treeOutput}
911
+ </repo_structure>
912
+
913
+ <search_string>
914
+ ${searchTerm}
915
+ </search_string>
916
+ ${budget}
917
+ ${turnTag}`;
918
+ } catch {
919
+ const repoName = import_path.default.basename(repoRoot);
920
+ return `<repo_structure>
921
+ ${repoName}/
922
+ </repo_structure>
923
+
924
+ <search_string>
925
+ ${searchTerm}
926
+ </search_string>
927
+ ${budget}
928
+ ${turnTag}`;
929
+ }
930
+ }
931
+ function enforceContextLimit(messages, maxChars = AGENT_CONFIG.MAX_CONTEXT_CHARS) {
932
+ const getTotalChars = () => messages.reduce((sum, m) => sum + m.content.length, 0);
933
+ if (getTotalChars() <= maxChars) {
934
+ return messages;
935
+ }
936
+ const userIndices = [];
937
+ let firstUserSkipped = false;
938
+ for (let i = 0; i < messages.length; i++) {
939
+ if (messages[i].role === "user") {
940
+ if (!firstUserSkipped) {
941
+ firstUserSkipped = true;
942
+ continue;
943
+ }
944
+ userIndices.push(i);
945
+ }
946
+ }
947
+ for (const idx of userIndices) {
948
+ if (getTotalChars() <= maxChars) {
949
+ break;
950
+ }
951
+ if (messages[idx].content !== TRUNCATED_MARKER) {
952
+ messages[idx] = { role: "user", content: TRUNCATED_MARKER };
953
+ }
954
+ }
955
+ return messages;
956
+ }
957
+
958
+ // tools/warp_grep/agent/runner.ts
959
+ var import_openai = __toESM(require("openai"), 1);
960
+
961
+ // package.json
962
+ var package_default = {
963
+ name: "@morphllm/morphsdk",
964
+ version: "0.2.139",
965
+ description: "TypeScript SDK and CLI for Morph Fast Apply integration",
966
+ type: "module",
967
+ main: "./dist/index.cjs",
968
+ module: "./dist/index.js",
969
+ types: "./dist/index.d.ts",
970
+ exports: {
971
+ ".": {
972
+ types: "./dist/index.d.ts",
973
+ import: "./dist/index.js",
974
+ require: "./dist/index.cjs"
975
+ },
976
+ "./edge": {
977
+ types: "./dist/edge.d.ts",
978
+ import: "./dist/edge.js",
979
+ require: "./dist/edge.cjs"
980
+ },
981
+ "./tools/warp-grep": {
982
+ types: "./dist/tools/warp_grep/index.d.ts",
983
+ import: "./dist/tools/warp_grep/index.js",
984
+ require: "./dist/tools/warp_grep/index.cjs"
985
+ },
986
+ "./tools/warp-grep/openai": {
987
+ types: "./dist/tools/warp_grep/openai.d.ts",
988
+ import: "./dist/tools/warp_grep/openai.js",
989
+ require: "./dist/tools/warp_grep/openai.cjs"
990
+ },
991
+ "./tools/warp-grep/anthropic": {
992
+ types: "./dist/tools/warp_grep/anthropic.d.ts",
993
+ import: "./dist/tools/warp_grep/anthropic.js",
994
+ require: "./dist/tools/warp_grep/anthropic.cjs"
995
+ },
996
+ "./tools/warp-grep/vercel": {
997
+ types: "./dist/tools/warp_grep/vercel.d.ts",
998
+ import: "./dist/tools/warp_grep/vercel.js",
999
+ require: "./dist/tools/warp_grep/vercel.cjs"
1000
+ },
1001
+ "./tools/warp-grep/client": {
1002
+ types: "./dist/tools/warp_grep/client.d.ts",
1003
+ import: "./dist/tools/warp_grep/client.js",
1004
+ require: "./dist/tools/warp_grep/client.cjs"
1005
+ },
1006
+ "./tools/warp-grep/gemini": {
1007
+ types: "./dist/tools/warp_grep/gemini.d.ts",
1008
+ import: "./dist/tools/warp_grep/gemini.js",
1009
+ require: "./dist/tools/warp_grep/gemini.cjs"
1010
+ },
1011
+ "./tools/warp-grep/harness": {
1012
+ types: "./dist/tools/warp_grep/harness.d.ts",
1013
+ import: "./dist/tools/warp_grep/harness.js",
1014
+ require: "./dist/tools/warp_grep/harness.cjs"
1015
+ },
1016
+ "./tools/fastapply": {
1017
+ types: "./dist/tools/fastapply/index.d.ts",
1018
+ import: "./dist/tools/fastapply/index.js",
1019
+ require: "./dist/tools/fastapply/index.cjs"
1020
+ },
1021
+ "./tools/fastapply/anthropic": {
1022
+ types: "./dist/tools/fastapply/anthropic.d.ts",
1023
+ import: "./dist/tools/fastapply/anthropic.js",
1024
+ require: "./dist/tools/fastapply/anthropic.cjs"
1025
+ },
1026
+ "./tools/fastapply/openai": {
1027
+ types: "./dist/tools/fastapply/openai.d.ts",
1028
+ import: "./dist/tools/fastapply/openai.js",
1029
+ require: "./dist/tools/fastapply/openai.cjs"
1030
+ },
1031
+ "./tools/fastapply/vercel": {
1032
+ types: "./dist/tools/fastapply/vercel.d.ts",
1033
+ import: "./dist/tools/fastapply/vercel.js",
1034
+ require: "./dist/tools/fastapply/vercel.cjs"
1035
+ },
1036
+ "./tools/codebase-search": {
1037
+ types: "./dist/tools/codebase_search/index.d.ts",
1038
+ import: "./dist/tools/codebase_search/index.js",
1039
+ require: "./dist/tools/codebase_search/index.cjs"
1040
+ },
1041
+ "./tools/codebase-search/anthropic": {
1042
+ types: "./dist/tools/codebase_search/anthropic.d.ts",
1043
+ import: "./dist/tools/codebase_search/anthropic.js",
1044
+ require: "./dist/tools/codebase_search/anthropic.cjs"
1045
+ },
1046
+ "./tools/codebase-search/openai": {
1047
+ types: "./dist/tools/codebase_search/openai.d.ts",
1048
+ import: "./dist/tools/codebase_search/openai.js",
1049
+ require: "./dist/tools/codebase_search/openai.cjs"
1050
+ },
1051
+ "./tools/codebase-search/vercel": {
1052
+ types: "./dist/tools/codebase_search/vercel.d.ts",
1053
+ import: "./dist/tools/codebase_search/vercel.js",
1054
+ require: "./dist/tools/codebase_search/vercel.cjs"
1055
+ },
1056
+ "./tools/git": {
1057
+ types: "./dist/git/index.d.ts",
1058
+ import: "./dist/git/index.js",
1059
+ require: "./dist/git/index.cjs"
1060
+ },
1061
+ "./tools/browser": {
1062
+ types: "./dist/tools/browser/index.d.ts",
1063
+ import: "./dist/tools/browser/index.js",
1064
+ require: "./dist/tools/browser/index.cjs"
1065
+ },
1066
+ "./tools/browser/anthropic": {
1067
+ types: "./dist/tools/browser/anthropic.d.ts",
1068
+ import: "./dist/tools/browser/anthropic.js",
1069
+ require: "./dist/tools/browser/anthropic.cjs"
1070
+ },
1071
+ "./tools/browser/openai": {
1072
+ types: "./dist/tools/browser/openai.d.ts",
1073
+ import: "./dist/tools/browser/openai.js",
1074
+ require: "./dist/tools/browser/openai.cjs"
1075
+ },
1076
+ "./tools/browser/vercel": {
1077
+ types: "./dist/tools/browser/vercel.d.ts",
1078
+ import: "./dist/tools/browser/vercel.js",
1079
+ require: "./dist/tools/browser/vercel.cjs"
1080
+ },
1081
+ "./tools/browser/profiles": {
1082
+ types: "./dist/tools/browser/profiles/index.d.ts",
1083
+ import: "./dist/tools/browser/profiles/index.js",
1084
+ require: "./dist/tools/browser/profiles/index.cjs"
1085
+ },
1086
+ "./modelrouter": {
1087
+ types: "./dist/modelrouter/index.d.ts",
1088
+ import: "./dist/modelrouter/index.js",
1089
+ require: "./dist/modelrouter/index.cjs"
1090
+ },
1091
+ "./tools/compact": {
1092
+ types: "./dist/tools/compact/index.d.ts",
1093
+ import: "./dist/tools/compact/index.js",
1094
+ require: "./dist/tools/compact/index.cjs"
1095
+ },
1096
+ "./subagents": {
1097
+ types: "./dist/subagents/index.d.ts",
1098
+ import: "./dist/subagents/index.js",
1099
+ require: "./dist/subagents/index.cjs"
1100
+ },
1101
+ "./subagents/vercel": {
1102
+ types: "./dist/subagents/vercel.d.ts",
1103
+ import: "./dist/subagents/vercel.js",
1104
+ require: "./dist/subagents/vercel.cjs"
1105
+ },
1106
+ "./subagents/anthropic": {
1107
+ types: "./dist/subagents/anthropic.d.ts",
1108
+ import: "./dist/subagents/anthropic.js",
1109
+ require: "./dist/subagents/anthropic.cjs"
1110
+ }
1111
+ },
1112
+ files: [
1113
+ "dist/**/*.js",
1114
+ "dist/**/*.cjs",
1115
+ "dist/**/*.d.ts",
1116
+ "dist/**/*.map",
1117
+ "!dist/**/__tests__/**",
1118
+ "!dist/**/*.test.*"
1119
+ ],
1120
+ scripts: {
1121
+ build: "tsup version.ts index.ts edge.ts client.ts tools/index.ts tools/fastapply/index.ts tools/fastapply/core.ts tools/fastapply/apply.ts tools/fastapply/types.ts tools/fastapply/prompts.ts tools/fastapply/anthropic.ts tools/fastapply/openai.ts tools/fastapply/vercel.ts tools/codebase_search/index.ts tools/codebase_search/core.ts tools/codebase_search/types.ts tools/codebase_search/prompts.ts tools/codebase_search/anthropic.ts tools/codebase_search/openai.ts tools/codebase_search/vercel.ts tools/warp_grep/index.ts tools/warp_grep/client.ts tools/warp_grep/openai.ts tools/warp_grep/anthropic.ts tools/warp_grep/vercel.ts tools/warp_grep/gemini.ts tools/warp_grep/harness.ts tools/warp_grep/agent/config.ts tools/warp_grep/agent/parser.ts tools/warp_grep/agent/runner.ts tools/warp_grep/agent/types.ts tools/warp_grep/agent/formatter.ts tools/warp_grep/providers/types.ts tools/warp_grep/providers/local.ts tools/warp_grep/providers/remote.ts tools/warp_grep/providers/code_storage_http.ts tools/warp_grep/tools/grep.ts tools/warp_grep/tools/analyse.ts tools/warp_grep/tools/read.ts tools/warp_grep/tools/finish.ts tools/warp_grep/utils/paths.ts tools/warp_grep/utils/github.ts tools/warp_grep/utils/ripgrep.ts tools/warp_grep/utils/format.ts tools/warp_grep/utils/files.ts git/index.ts git/client.ts git/config.ts git/types.ts tools/browser/index.ts tools/browser/core.ts tools/browser/types.ts tools/browser/prompts.ts tools/browser/anthropic.ts tools/browser/openai.ts tools/browser/vercel.ts tools/browser/live.ts tools/browser/errors.ts tools/browser/profiles/index.ts tools/browser/profiles/core.ts tools/browser/profiles/types.ts modelrouter/index.ts modelrouter/core.ts modelrouter/types.ts tools/compact/index.ts tools/compact/core.ts tools/compact/types.ts tools/utils/resilience.ts subagents/index.ts subagents/types.ts subagents/prompts.ts subagents/vercel.ts subagents/anthropic.ts --format esm,cjs --sourcemap --clean --dts --dts-resolve",
1122
+ prepare: "npm run build",
1123
+ typecheck: "tsc --noEmit",
1124
+ lint: "eslint .",
1125
+ test: "vitest run",
1126
+ "test:watch": "vitest watch",
1127
+ "test:anthropic": "vitest run anthropic",
1128
+ "test:openai": "vitest run openai",
1129
+ "test:vercel": "vitest run vercel",
1130
+ "test:git": "vitest run git",
1131
+ "test:browser": "vitest run browser",
1132
+ "test:agent": "npx tsx tests/fullAgentTest.ts",
1133
+ "test:integration": "npx tsx tests/fullIntegrationTest.ts",
1134
+ "release:patch": "npm version patch && npm publish",
1135
+ "release:minor": "npm version minor && npm publish",
1136
+ "release:major": "npm version major && npm publish"
1137
+ },
1138
+ keywords: [
1139
+ "morph",
1140
+ "fast-apply",
1141
+ "cli",
1142
+ "sdk",
1143
+ "edit-file"
1144
+ ],
1145
+ engines: {
1146
+ node: ">=18"
1147
+ },
1148
+ license: "MIT",
1149
+ dependencies: {
1150
+ "@vscode/ripgrep": "^1.17.0",
1151
+ ai: ">=5.0.0",
1152
+ diff: "^7.0.0",
1153
+ "isomorphic-git": "^1.25.10",
1154
+ openai: "^4.52.7",
1155
+ zod: ">=3.23.0"
1156
+ },
1157
+ devDependencies: {
1158
+ "@ai-sdk/anthropic": "^2.0.70",
1159
+ "@ai-sdk/openai": "^2.0.35",
1160
+ "@anthropic-ai/sdk": "^0.30.1",
1161
+ "@google/generative-ai": "^0.24.1",
1162
+ "@types/diff": "^7.0.2",
1163
+ "@types/node": "^20.14.10",
1164
+ "@typescript-eslint/eslint-plugin": "^7.18.0",
1165
+ "@typescript-eslint/parser": "^7.18.0",
1166
+ dotenv: "^16.4.5",
1167
+ eslint: "^8.57.0",
1168
+ shx: "^0.3.4",
1169
+ tsup: "^8.5.0",
1170
+ tsx: "^4.16.2",
1171
+ typescript: "^5.5.4",
1172
+ vitest: "^2.1.6"
1173
+ },
1174
+ peerDependencies: {
1175
+ "@anthropic-ai/sdk": ">=0.25.0",
1176
+ "@google/generative-ai": ">=0.21.0",
1177
+ ai: ">=5.0.0",
1178
+ zod: ">=3.23.0"
1179
+ },
1180
+ peerDependenciesMeta: {
1181
+ "@anthropic-ai/sdk": {
1182
+ optional: true
1183
+ },
1184
+ "@google/generative-ai": {
1185
+ optional: true
1186
+ },
1187
+ ai: {
1188
+ optional: true
1189
+ },
1190
+ zod: {
1191
+ optional: true
1192
+ }
1193
+ },
1194
+ publishConfig: {
1195
+ access: "public"
1196
+ }
1197
+ };
1198
+
1199
+ // version.ts
1200
+ var SDK_VERSION = package_default.version;
1201
+
1202
+ // tools/warp_grep/agent/runner.ts
1203
+ var import_path2 = __toESM(require("path"), 1);
1204
+ var parser = new LLMResponseParser();
1205
+ var DEFAULT_API_URL = "https://api.morphllm.com";
1206
+ async function callModel(messages, model, options = {}) {
1207
+ const baseUrl = options.morphApiUrl || DEFAULT_API_URL;
1208
+ const apiKey = options.morphApiKey || process.env.MORPH_API_KEY || "";
1209
+ const timeoutMs = options.timeout ?? AGENT_CONFIG.TIMEOUT_MS;
1210
+ const parsedUrl = new URL(baseUrl);
1211
+ const baseURL = parsedUrl.pathname === "/" ? `${baseUrl}/v1` : baseUrl;
1212
+ const client = new import_openai.default({
1213
+ apiKey,
1214
+ baseURL,
1215
+ maxRetries: options.retryConfig?.maxRetries,
1216
+ timeout: timeoutMs,
1217
+ defaultHeaders: { "X-Morph-SDK-Version": SDK_VERSION }
1218
+ });
1219
+ const MAX_EMPTY_RETRIES = 1;
1220
+ for (let attempt = 0; attempt <= MAX_EMPTY_RETRIES; attempt++) {
1221
+ let data;
1222
+ try {
1223
+ data = await client.chat.completions.create({
1224
+ model,
1225
+ temperature: 0,
1226
+ max_tokens: 1024,
1227
+ messages
1228
+ });
1229
+ } catch (error) {
1230
+ if (error instanceof import_openai.default.APIError && error.status === 404) {
1231
+ const defaultMsg = "The endpoint you are trying to call is likely deprecated. Please update with: npm cache clean --force && npx -y @morphllm/morphmcp@latest or visit: https://morphllm.com/mcp";
1232
+ const errorText = error.message?.trim();
1233
+ throw new Error(errorText || defaultMsg);
1234
+ }
1235
+ throw error;
1236
+ }
1237
+ const choice = data?.choices?.[0];
1238
+ const content = choice?.message?.content;
1239
+ if (content && typeof content === "string") {
1240
+ return content;
1241
+ }
1242
+ if (attempt === MAX_EMPTY_RETRIES) {
1243
+ const finishReason = choice?.finish_reason ?? "unknown";
1244
+ const hasToolCalls = Array.isArray(choice?.message?.tool_calls) && choice.message.tool_calls.length > 0;
1245
+ const choicesLen = data?.choices?.length ?? 0;
1246
+ const contentType = content === null ? "null" : content === void 0 ? "undefined" : typeof content;
1247
+ throw new Error(
1248
+ `Invalid response from model: content=${contentType}, finish_reason=${finishReason}, has_tool_calls=${hasToolCalls}, choices_length=${choicesLen}`
1249
+ );
1250
+ }
1251
+ await new Promise((resolve) => setTimeout(resolve, 200));
1252
+ }
1253
+ throw new Error("Invalid response from model");
1254
+ }
1255
+ async function runWarpGrep(config) {
1256
+ const totalStart = Date.now();
1257
+ const timeoutMs = config.timeout ?? AGENT_CONFIG.TIMEOUT_MS;
1258
+ const timings = { turns: [], timeout_ms: timeoutMs };
1259
+ const repoRoot = import_path2.default.resolve(config.repoRoot || process.cwd());
1260
+ const model = config.model || DEFAULT_MODEL;
1261
+ const messages = [];
1262
+ const maxTurns = AGENT_CONFIG.MAX_TURNS;
1263
+ const initialStateStart = Date.now();
1264
+ const initialState = await buildInitialState(repoRoot, config.searchTerm, config.provider, { search_type: config.search_type });
1265
+ timings.initial_state_ms = Date.now() - initialStateStart;
1266
+ messages.push({ role: "user", content: initialState });
1267
+ const provider = config.provider;
1268
+ const errors = [];
1269
+ let finishMeta;
1270
+ let terminationReason = "terminated";
1271
+ for (let turn = 1; turn <= maxTurns; turn += 1) {
1272
+ const turnMetrics = { turn, morph_api_ms: 0, local_tools_ms: 0 };
1273
+ enforceContextLimit(messages);
1274
+ const modelCallStart = Date.now();
1275
+ const assistantContent = await callModel(messages, model, {
1276
+ morphApiKey: config.morphApiKey,
1277
+ morphApiUrl: config.morphApiUrl,
1278
+ retryConfig: config.retryConfig,
1279
+ timeout: timeoutMs
1280
+ }).catch((e) => {
1281
+ const errMsg = e instanceof Error ? e.message : String(e);
1282
+ console.error(`[warp_grep] Morph API call failed on turn ${turn}:`, errMsg);
1283
+ errors.push({ message: errMsg });
1284
+ return "";
1285
+ });
1286
+ turnMetrics.morph_api_ms = Date.now() - modelCallStart;
1287
+ if (!assistantContent) {
1288
+ console.error(`[warp_grep] Empty response from Morph API on turn ${turn}. Errors so far:`, errors);
1289
+ timings.turns.push(turnMetrics);
1290
+ break;
1291
+ }
1292
+ messages.push({ role: "assistant", content: assistantContent });
1293
+ const toolCalls = parser.parse(assistantContent);
1294
+ if (toolCalls.length === 0) {
1295
+ console.error(`[warp_grep] No tool calls parsed on turn ${turn}. Assistant content (first 500 chars):`, assistantContent.slice(0, 500));
1296
+ 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" });
1297
+ terminationReason = "terminated";
1298
+ timings.turns.push(turnMetrics);
1299
+ break;
1300
+ }
1301
+ const finishCalls = toolCalls.filter((c) => c.name === "finish");
1302
+ const grepCalls = toolCalls.filter((c) => c.name === "grep");
1303
+ const listDirCalls = toolCalls.filter((c) => c.name === "list_directory");
1304
+ const readCalls = toolCalls.filter((c) => c.name === "read");
1305
+ const skipCalls = toolCalls.filter((c) => c.name === "_skip");
1306
+ const formatted = [];
1307
+ for (const c of skipCalls) {
1308
+ const msg = c.arguments?.message || "Command skipped due to parsing error";
1309
+ formatted.push(msg);
1310
+ }
1311
+ const allPromises = [];
1312
+ for (const c of grepCalls) {
1313
+ const args = c.arguments ?? {};
1314
+ allPromises.push(
1315
+ toolGrep(provider, args).then(
1316
+ ({ output }) => formatAgentToolOutput("grep", args, output),
1317
+ (err) => formatAgentToolOutput("grep", args, String(err), { isError: true })
1318
+ )
1319
+ );
1320
+ }
1321
+ for (const c of listDirCalls) {
1322
+ const args = c.arguments ?? {};
1323
+ allPromises.push(
1324
+ toolListDirectory(provider, args).then(
1325
+ (p) => formatAgentToolOutput("list_directory", args, p),
1326
+ (err) => formatAgentToolOutput("list_directory", args, String(err), { isError: true })
1327
+ )
1328
+ );
1329
+ }
1330
+ for (const c of readCalls) {
1331
+ const args = c.arguments ?? {};
1332
+ allPromises.push(
1333
+ toolRead(provider, args).then(
1334
+ (p) => formatAgentToolOutput("read", args, p),
1335
+ (err) => formatAgentToolOutput("read", args, String(err), { isError: true })
1336
+ )
1337
+ );
1338
+ }
1339
+ const toolExecStart = Date.now();
1340
+ const allResults = await Promise.all(allPromises);
1341
+ turnMetrics.local_tools_ms = Date.now() - toolExecStart;
1342
+ for (const result of allResults) {
1343
+ formatted.push(result);
1344
+ }
1345
+ if (formatted.length > 0) {
1346
+ const turnMessage = formatTurnMessage(turn, maxTurns);
1347
+ const contextBudget = calculateContextBudget(messages);
1348
+ messages.push({ role: "user", content: formatted.join("\n") + turnMessage + "\n" + contextBudget });
1349
+ }
1350
+ timings.turns.push(turnMetrics);
1351
+ if (finishCalls.length) {
1352
+ const fc = finishCalls[0];
1353
+ const files = fc.arguments?.files ?? [];
1354
+ const textResult = fc.arguments?.textResult;
1355
+ finishMeta = { files };
1356
+ terminationReason = "completed";
1357
+ if (files.length === 0) {
1358
+ const payload2 = textResult || "No relevant code found.";
1359
+ timings.turns.push(turnMetrics);
1360
+ timings.total_ms = Date.now() - totalStart;
1361
+ return {
1362
+ terminationReason: "completed",
1363
+ messages,
1364
+ finish: { payload: payload2, metadata: finishMeta },
1365
+ timings
1366
+ };
1367
+ }
1368
+ break;
1369
+ }
1370
+ }
1371
+ if (terminationReason !== "completed" || !finishMeta) {
1372
+ timings.total_ms = Date.now() - totalStart;
1373
+ return { terminationReason, messages, errors, timings };
1374
+ }
1375
+ const parts = ["Relevant context found:"];
1376
+ for (const f of finishMeta.files) {
1377
+ const ranges = f.lines === "*" ? "*" : Array.isArray(f.lines) ? f.lines.map(([s, e]) => `${s}-${e}`).join(", ") : "*";
1378
+ parts.push(`- ${f.path}: ${ranges}`);
1379
+ }
1380
+ const payload = parts.join("\n");
1381
+ const finishResolutionStart = Date.now();
1382
+ const fileReadErrors = [];
1383
+ const resolved = await readFinishFiles(
1384
+ repoRoot,
1385
+ finishMeta.files,
1386
+ async (p, s, e) => {
1387
+ try {
1388
+ const rr = await provider.read({ path: p, start: s, end: e });
1389
+ return rr.lines.map((l) => {
1390
+ const idx = l.indexOf("|");
1391
+ return idx >= 0 ? l.slice(idx + 1) : l;
1392
+ });
1393
+ } catch (err) {
1394
+ const errorMsg = err instanceof Error ? err.message : String(err);
1395
+ fileReadErrors.push({ path: p, error: errorMsg });
1396
+ console.error(`[warp_grep] Failed to read file: ${p} - ${errorMsg}`);
1397
+ return [`[couldn't find: ${p}]`];
1398
+ }
1399
+ }
1400
+ );
1401
+ timings.finish_resolution_ms = Date.now() - finishResolutionStart;
1402
+ if (fileReadErrors.length > 0) {
1403
+ errors.push(...fileReadErrors.map((e) => ({ message: `File read error: ${e.path} - ${e.error}` })));
1404
+ }
1405
+ timings.total_ms = Date.now() - totalStart;
1406
+ return {
1407
+ terminationReason: "completed",
1408
+ messages,
1409
+ finish: { payload, metadata: finishMeta, resolved },
1410
+ timings
1411
+ };
1412
+ }
1413
+ async function* runWarpGrepStreaming(config) {
1414
+ const totalStart = Date.now();
1415
+ const timeoutMs = config.timeout ?? AGENT_CONFIG.TIMEOUT_MS;
1416
+ const timings = { turns: [], timeout_ms: timeoutMs };
1417
+ const repoRoot = import_path2.default.resolve(config.repoRoot || process.cwd());
1418
+ const model = config.model || DEFAULT_MODEL;
1419
+ const messages = [];
1420
+ const maxTurns = AGENT_CONFIG.MAX_TURNS;
1421
+ const initialStateStart = Date.now();
1422
+ const initialState = await buildInitialState(repoRoot, config.searchTerm, config.provider, { search_type: config.search_type });
1423
+ timings.initial_state_ms = Date.now() - initialStateStart;
1424
+ messages.push({ role: "user", content: initialState });
1425
+ const provider = config.provider;
1426
+ const errors = [];
1427
+ let finishMeta;
1428
+ let terminationReason = "terminated";
1429
+ for (let turn = 1; turn <= maxTurns; turn += 1) {
1430
+ const turnMetrics = { turn, morph_api_ms: 0, local_tools_ms: 0 };
1431
+ enforceContextLimit(messages);
1432
+ const modelCallStart = Date.now();
1433
+ const assistantContent = await callModel(messages, model, {
1434
+ morphApiKey: config.morphApiKey,
1435
+ morphApiUrl: config.morphApiUrl,
1436
+ retryConfig: config.retryConfig,
1437
+ timeout: timeoutMs
1438
+ }).catch((e) => {
1439
+ const errMsg = e instanceof Error ? e.message : String(e);
1440
+ console.error(`[warp_grep:stream] Morph API call failed on turn ${turn}:`, errMsg);
1441
+ errors.push({ message: errMsg });
1442
+ return "";
1443
+ });
1444
+ turnMetrics.morph_api_ms = Date.now() - modelCallStart;
1445
+ if (!assistantContent) {
1446
+ console.error(`[warp_grep:stream] Empty response from Morph API on turn ${turn}. Errors so far:`, errors);
1447
+ timings.turns.push(turnMetrics);
1448
+ break;
1449
+ }
1450
+ messages.push({ role: "assistant", content: assistantContent });
1451
+ const toolCalls = parser.parse(assistantContent);
1452
+ if (toolCalls.length === 0) {
1453
+ console.error(`[warp_grep:stream] No tool calls parsed on turn ${turn}. Assistant content (first 500 chars):`, assistantContent.slice(0, 500));
1454
+ 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" });
1455
+ terminationReason = "terminated";
1456
+ timings.turns.push(turnMetrics);
1457
+ break;
1458
+ }
1459
+ yield {
1460
+ turn,
1461
+ toolCalls: toolCalls.map((c) => ({
1462
+ name: c.name,
1463
+ arguments: c.arguments ?? {}
1464
+ }))
1465
+ };
1466
+ const finishCalls = toolCalls.filter((c) => c.name === "finish");
1467
+ const grepCalls = toolCalls.filter((c) => c.name === "grep");
1468
+ const listDirCalls = toolCalls.filter((c) => c.name === "list_directory");
1469
+ const readCalls = toolCalls.filter((c) => c.name === "read");
1470
+ const skipCalls = toolCalls.filter((c) => c.name === "_skip");
1471
+ const formatted = [];
1472
+ for (const c of skipCalls) {
1473
+ const msg = c.arguments?.message || "Command skipped due to parsing error";
1474
+ formatted.push(msg);
1475
+ }
1476
+ const allPromises = [];
1477
+ for (const c of grepCalls) {
1478
+ const args = c.arguments ?? {};
1479
+ allPromises.push(
1480
+ toolGrep(provider, args).then(
1481
+ ({ output }) => formatAgentToolOutput("grep", args, output),
1482
+ (err) => formatAgentToolOutput("grep", args, String(err), { isError: true })
1483
+ )
1484
+ );
1485
+ }
1486
+ for (const c of listDirCalls) {
1487
+ const args = c.arguments ?? {};
1488
+ allPromises.push(
1489
+ toolListDirectory(provider, args).then(
1490
+ (p) => formatAgentToolOutput("list_directory", args, p),
1491
+ (err) => formatAgentToolOutput("list_directory", args, String(err), { isError: true })
1492
+ )
1493
+ );
1494
+ }
1495
+ for (const c of readCalls) {
1496
+ const args = c.arguments ?? {};
1497
+ allPromises.push(
1498
+ toolRead(provider, args).then(
1499
+ (p) => formatAgentToolOutput("read", args, p),
1500
+ (err) => formatAgentToolOutput("read", args, String(err), { isError: true })
1501
+ )
1502
+ );
1503
+ }
1504
+ const toolExecStart = Date.now();
1505
+ const allResults = await Promise.all(allPromises);
1506
+ turnMetrics.local_tools_ms = Date.now() - toolExecStart;
1507
+ for (const result of allResults) {
1508
+ formatted.push(result);
1509
+ }
1510
+ if (formatted.length > 0) {
1511
+ const turnMessage = formatTurnMessage(turn, maxTurns);
1512
+ const contextBudget = calculateContextBudget(messages);
1513
+ messages.push({ role: "user", content: formatted.join("\n") + turnMessage + "\n" + contextBudget });
1514
+ }
1515
+ timings.turns.push(turnMetrics);
1516
+ if (finishCalls.length) {
1517
+ const fc = finishCalls[0];
1518
+ const files = fc.arguments?.files ?? [];
1519
+ const textResult = fc.arguments?.textResult;
1520
+ finishMeta = { files };
1521
+ terminationReason = "completed";
1522
+ if (files.length === 0) {
1523
+ const payload2 = textResult || "No relevant code found.";
1524
+ timings.total_ms = Date.now() - totalStart;
1525
+ return {
1526
+ terminationReason: "completed",
1527
+ messages,
1528
+ finish: { payload: payload2, metadata: finishMeta },
1529
+ timings
1530
+ };
1531
+ }
1532
+ break;
1533
+ }
1534
+ }
1535
+ if (terminationReason !== "completed" || !finishMeta) {
1536
+ timings.total_ms = Date.now() - totalStart;
1537
+ return { terminationReason, messages, errors, timings };
1538
+ }
1539
+ const parts = ["Relevant context found:"];
1540
+ for (const f of finishMeta.files) {
1541
+ const ranges = f.lines === "*" ? "*" : Array.isArray(f.lines) ? f.lines.map(([s, e]) => `${s}-${e}`).join(", ") : "*";
1542
+ parts.push(`- ${f.path}: ${ranges}`);
1543
+ }
1544
+ const payload = parts.join("\n");
1545
+ const finishResolutionStart = Date.now();
1546
+ const fileReadErrors = [];
1547
+ const resolved = await readFinishFiles(
1548
+ repoRoot,
1549
+ finishMeta.files,
1550
+ async (p, s, e) => {
1551
+ try {
1552
+ const rr = await provider.read({ path: p, start: s, end: e });
1553
+ return rr.lines.map((l) => {
1554
+ const idx = l.indexOf("|");
1555
+ return idx >= 0 ? l.slice(idx + 1) : l;
1556
+ });
1557
+ } catch (err) {
1558
+ const errorMsg = err instanceof Error ? err.message : String(err);
1559
+ fileReadErrors.push({ path: p, error: errorMsg });
1560
+ console.error(`[warp_grep] Failed to read file: ${p} - ${errorMsg}`);
1561
+ return [`[couldn't find: ${p}]`];
1562
+ }
1563
+ }
1564
+ );
1565
+ timings.finish_resolution_ms = Date.now() - finishResolutionStart;
1566
+ if (fileReadErrors.length > 0) {
1567
+ errors.push(...fileReadErrors.map((e) => ({ message: `File read error: ${e.path} - ${e.error}` })));
1568
+ }
1569
+ timings.total_ms = Date.now() - totalStart;
1570
+ return {
1571
+ terminationReason: "completed",
1572
+ messages,
1573
+ finish: { payload, metadata: finishMeta, resolved },
1574
+ timings
1575
+ };
1576
+ }
1577
+
1578
+ // tools/warp_grep/providers/remote.ts
1579
+ init_config();
1580
+ var SKIP_NAMES = /* @__PURE__ */ new Set([
1581
+ // Version control
1582
+ ".git",
1583
+ ".svn",
1584
+ ".hg",
1585
+ ".bzr",
1586
+ // Dependencies
1587
+ "node_modules",
1588
+ "bower_components",
1589
+ ".pnpm",
1590
+ ".yarn",
1591
+ "vendor",
1592
+ "Pods",
1593
+ ".bundle",
1594
+ // Python
1595
+ "__pycache__",
1596
+ ".pytest_cache",
1597
+ ".mypy_cache",
1598
+ ".ruff_cache",
1599
+ ".venv",
1600
+ "venv",
1601
+ ".tox",
1602
+ ".nox",
1603
+ ".eggs",
1604
+ // Build outputs
1605
+ "dist",
1606
+ "build",
1607
+ "out",
1608
+ "output",
1609
+ "target",
1610
+ "_build",
1611
+ ".next",
1612
+ ".nuxt",
1613
+ ".output",
1614
+ ".vercel",
1615
+ ".netlify",
1616
+ // Cache
1617
+ ".cache",
1618
+ ".parcel-cache",
1619
+ ".turbo",
1620
+ ".nx",
1621
+ ".gradle",
1622
+ // IDE
1623
+ ".idea",
1624
+ ".vscode",
1625
+ ".vs",
1626
+ // Coverage
1627
+ "coverage",
1628
+ ".coverage",
1629
+ "htmlcov",
1630
+ ".nyc_output",
1631
+ // Temp
1632
+ "tmp",
1633
+ "temp",
1634
+ ".tmp",
1635
+ ".temp",
1636
+ // Lock files
1637
+ "package-lock.json",
1638
+ "yarn.lock",
1639
+ "pnpm-lock.yaml",
1640
+ "bun.lockb",
1641
+ "Cargo.lock",
1642
+ "Gemfile.lock",
1643
+ "poetry.lock"
1644
+ ]);
1645
+ var SKIP_EXTENSIONS = /* @__PURE__ */ new Set([
1646
+ ".min.js",
1647
+ ".min.css",
1648
+ ".bundle.js",
1649
+ ".wasm",
1650
+ ".so",
1651
+ ".dll",
1652
+ ".pyc",
1653
+ ".map",
1654
+ ".js.map"
1655
+ ]);
1656
+ function shouldSkip(name) {
1657
+ if (SKIP_NAMES.has(name)) return true;
1658
+ if (name.startsWith(".")) return true;
1659
+ for (const ext of SKIP_EXTENSIONS) {
1660
+ if (name.endsWith(ext)) return true;
1661
+ }
1662
+ return false;
1663
+ }
1664
+ var RemoteCommandsProvider = class {
1665
+ constructor(repoRoot, commands) {
1666
+ this.repoRoot = repoRoot;
1667
+ this.commands = commands;
1668
+ }
1669
+ /**
1670
+ * Run grep command and parse ripgrep output
1671
+ */
1672
+ async grep(params) {
1673
+ try {
1674
+ const stdout = await this.commands.grep(params.pattern, params.path, params.glob);
1675
+ const lines = (stdout || "").trim().split(/\r?\n/).filter((l) => l.length > 0);
1676
+ if (lines.length > AGENT_CONFIG.MAX_OUTPUT_LINES) {
1677
+ const truncated = lines.slice(0, AGENT_CONFIG.MAX_OUTPUT_LINES);
1678
+ truncated.push(`... (output truncated at ${AGENT_CONFIG.MAX_OUTPUT_LINES} of ${lines.length} lines)`);
1679
+ return { lines: truncated };
1680
+ }
1681
+ return { lines };
1682
+ } catch (error) {
1683
+ return {
1684
+ lines: [],
1685
+ error: `[GREP ERROR] ${error instanceof Error ? error.message : String(error)}`
1686
+ };
1687
+ }
1688
+ }
1689
+ /**
1690
+ * Read file and add line numbers
1691
+ */
1692
+ async read(params) {
1693
+ const rawStart = params.start;
1694
+ const rawEnd = params.end;
1695
+ const startValid = rawStart === void 0 || Number.isFinite(rawStart) && rawStart > 0;
1696
+ const endValid = rawEnd === void 0 || Number.isFinite(rawEnd) && rawEnd > 0;
1697
+ const rangeValid = startValid && endValid && (rawStart === void 0 || rawEnd === void 0 || rawStart <= rawEnd);
1698
+ const start = rangeValid && rawStart !== void 0 ? rawStart : 1;
1699
+ const end = rangeValid && rawEnd !== void 0 ? rawEnd : 1e6;
1700
+ try {
1701
+ const stdout = await this.commands.read(params.path, start, end);
1702
+ const contentLines = (stdout || "").split("\n");
1703
+ if (contentLines.length > 0 && contentLines[contentLines.length - 1] === "") {
1704
+ contentLines.pop();
1705
+ }
1706
+ const lines = contentLines.map((content, idx) => `${start + idx}|${content}`);
1707
+ if (lines.length > AGENT_CONFIG.MAX_READ_LINES) {
1708
+ const truncated = lines.slice(0, AGENT_CONFIG.MAX_READ_LINES);
1709
+ truncated.push(`... (output truncated at ${AGENT_CONFIG.MAX_READ_LINES} of ${lines.length} lines)`);
1710
+ return { lines: truncated };
1711
+ }
1712
+ return { lines };
1713
+ } catch (error) {
1714
+ return {
1715
+ lines: [],
1716
+ error: `[READ ERROR] ${error instanceof Error ? error.message : String(error)}`
1717
+ };
1718
+ }
1719
+ }
1720
+ /**
1721
+ * List directory and parse find output
1722
+ */
1723
+ async listDirectory(params) {
1724
+ const maxDepth = params.maxDepth ?? AGENT_CONFIG.MAX_LIST_DEPTH;
1725
+ const maxResults = params.maxResults ?? AGENT_CONFIG.MAX_OUTPUT_LINES;
1726
+ try {
1727
+ const stdout = await this.commands.listDir(params.path, maxDepth);
1728
+ const paths = (stdout || "").trim().split(/\r?\n/).filter((p) => p.length > 0);
1729
+ const regex = params.pattern ? new RegExp(params.pattern) : null;
1730
+ const entries = [];
1731
+ for (const fullPath of paths) {
1732
+ if (fullPath === params.path || fullPath === this.repoRoot) continue;
1733
+ const name = fullPath.split("/").pop() || "";
1734
+ if (shouldSkip(name)) continue;
1735
+ if (regex && !regex.test(name)) continue;
1736
+ let relativePath = fullPath;
1737
+ if (fullPath.startsWith(this.repoRoot)) {
1738
+ relativePath = fullPath.slice(this.repoRoot.length).replace(/^\//, "");
1739
+ }
1740
+ const depth = relativePath.split("/").filter(Boolean).length - 1;
1741
+ const hasExtension = name.includes(".") && !name.startsWith(".");
1742
+ const type = hasExtension ? "file" : "dir";
1743
+ entries.push({
1744
+ name,
1745
+ path: relativePath,
1746
+ type,
1747
+ depth: Math.max(0, depth)
1748
+ });
1749
+ if (entries.length >= maxResults) break;
1750
+ }
1751
+ return entries;
1752
+ } catch (error) {
1753
+ return [];
1754
+ }
1755
+ }
1756
+ };
1757
+
1758
+ // tools/warp_grep/providers/code_storage_http.ts
1759
+ async function post(url, body, op) {
1760
+ const res = await fetch(url, {
1761
+ method: "POST",
1762
+ headers: { "Content-Type": "application/json" },
1763
+ body: JSON.stringify(body)
1764
+ });
1765
+ if (!res.ok) {
1766
+ const text = await res.text().catch(() => res.statusText);
1767
+ try {
1768
+ const parsed = JSON.parse(text);
1769
+ if (parsed.error) return `Error: ${parsed.error}`;
1770
+ } catch {
1771
+ }
1772
+ return `Error: ${op} failed (${res.status}): ${text}`;
1773
+ }
1774
+ const data = await res.json();
1775
+ if (data.error) throw new Error(data.error);
1776
+ return data.stdout;
1777
+ }
1778
+ function createCodeStorageHttpCommands(config) {
1779
+ const { baseUrl, repoId, branch } = config;
1780
+ const encodedRepoId = encodeURIComponent(repoId);
1781
+ return {
1782
+ grep: (pattern, path5, glob) => post(`${baseUrl}/api/code-search/${encodedRepoId}/grep`, { pattern, path: path5, glob, branch }, "grep"),
1783
+ read: (path5, start, end) => post(`${baseUrl}/api/code-search/${encodedRepoId}/read`, { path: path5, start, end, branch }, "read"),
1784
+ listDir: (path5, maxDepth) => post(`${baseUrl}/api/code-search/${encodedRepoId}/list`, { path: path5, maxDepth, branch }, "list")
1785
+ };
1786
+ }
1787
+
1788
+ // tools/warp_grep/utils/github.ts
1789
+ function parseGitHubUrl(input) {
1790
+ input = input.trim();
1791
+ const urlPattern = /^(?:https?:\/\/)?github\.com\/([^\/]+)\/([^\/\?\#]+)/;
1792
+ const match = input.match(urlPattern);
1793
+ if (match) {
1794
+ return { owner: match[1], repo: match[2].replace(/\.git$/, "") };
1795
+ }
1796
+ const shortPattern = /^([^\/]+)\/([^\/]+)$/;
1797
+ const shortMatch = input.match(shortPattern);
1798
+ if (shortMatch && !shortMatch[1].includes(".")) {
1799
+ return { owner: shortMatch[1], repo: shortMatch[2].replace(/\.git$/, "") };
1800
+ }
1801
+ throw new Error(
1802
+ `Invalid GitHub URL or shorthand: "${input}". Expected "owner/repo" or "https://github.com/owner/repo"`
1803
+ );
1804
+ }
1805
+
1806
+ // tools/warp_grep/client.ts
1807
+ var DEFAULT_CODE_SEARCH_URL = "https://morphllm.com";
1808
+ async function getLocalProvider(repoRoot, excludes) {
1809
+ const { LocalRipgrepProvider: LocalRipgrepProvider2 } = await Promise.resolve().then(() => (init_local(), local_exports));
1810
+ return new LocalRipgrepProvider2(repoRoot, excludes);
1811
+ }
1812
+ var WarpGrepClient = class {
1813
+ config;
1814
+ constructor(config = {}) {
1815
+ this.config = { ...config };
1816
+ }
1817
+ execute(input) {
1818
+ const toolConfig = {
1819
+ repoRoot: input.repoRoot,
1820
+ remoteCommands: input.remoteCommands,
1821
+ provider: input.provider,
1822
+ excludes: input.excludes,
1823
+ includes: input.includes,
1824
+ debug: input.debug ?? this.config.debug,
1825
+ morphApiKey: this.config.morphApiKey,
1826
+ morphApiUrl: this.config.morphApiUrl,
1827
+ retryConfig: this.config.retryConfig,
1828
+ timeout: this.config.timeout
1829
+ };
1830
+ if (input.streamSteps) {
1831
+ return executeToolCallStreaming({ search_term: input.searchTerm }, toolConfig);
1832
+ }
1833
+ return executeToolCall({ search_term: input.searchTerm }, toolConfig);
1834
+ }
1835
+ searchGitHub(input) {
1836
+ if (input.streamSteps) {
1837
+ return this._searchGitHubStreaming(input);
1838
+ }
1839
+ return this._searchGitHubAsync(input);
1840
+ }
1841
+ /**
1842
+ * Read a single file from a public GitHub repository
1843
+ *
1844
+ * @example
1845
+ * ```typescript
1846
+ * const result = await client.readGitHubFile({
1847
+ * github: 'vercel/next.js',
1848
+ * path: 'src/server/app-render/index.tsx',
1849
+ * startLine: 1,
1850
+ * endLine: 50,
1851
+ * });
1852
+ * if (result.success) console.log(result.content);
1853
+ * ```
1854
+ */
1855
+ async readGitHubFile(input) {
1856
+ return executeGitHubReadFile(input, { timeout: this.config.timeout });
1857
+ }
1858
+ async _resolveGitHubRepo(input) {
1859
+ const { owner, repo } = parseGitHubUrl(input.github);
1860
+ const baseUrl = this.config.codeSearchUrl || DEFAULT_CODE_SEARCH_URL;
1861
+ const importRes = await fetch(`${baseUrl}/api/code-search/get-or-create?url=${encodeURIComponent(`${owner}/${repo}`)}`);
1862
+ if (!importRes.ok) {
1863
+ const text = await importRes.text().catch(() => importRes.statusText);
1864
+ throw new Error(`Failed to import repo ${owner}/${repo}: ${text}`);
1865
+ }
1866
+ const { repoId, defaultBranch } = await importRes.json();
1867
+ return {
1868
+ repo,
1869
+ remoteCommands: createCodeStorageHttpCommands({ baseUrl, repoId, branch: input.branch || defaultBranch })
1870
+ };
1871
+ }
1872
+ async _searchGitHubAsync(input) {
1873
+ try {
1874
+ const { repo, remoteCommands } = await this._resolveGitHubRepo(input);
1875
+ return this.execute({
1876
+ searchTerm: input.searchTerm,
1877
+ repoRoot: repo,
1878
+ remoteCommands
1879
+ });
1880
+ } catch (error) {
1881
+ return { success: false, error: error instanceof Error ? error.message : String(error) };
1882
+ }
1883
+ }
1884
+ async *_searchGitHubStreaming(input) {
1885
+ let repo;
1886
+ let remoteCommands;
1887
+ try {
1888
+ ({ repo, remoteCommands } = await this._resolveGitHubRepo(input));
1889
+ } catch (error) {
1890
+ return { success: false, error: error instanceof Error ? error.message : String(error) };
1891
+ }
1892
+ const generator = this.execute({
1893
+ searchTerm: input.searchTerm,
1894
+ repoRoot: repo,
1895
+ remoteCommands,
1896
+ streamSteps: true
1897
+ });
1898
+ let result;
1899
+ for (; ; ) {
1900
+ const { value, done } = await generator.next();
1901
+ if (done) {
1902
+ result = value;
1903
+ break;
1904
+ }
1905
+ yield value;
1906
+ }
1907
+ return result;
1908
+ }
1909
+ };
1910
+ async function executeToolCall(input, config) {
1911
+ const parsed = typeof input === "string" ? JSON.parse(input) : input;
1912
+ const provider = config.remoteCommands ? new RemoteCommandsProvider(config.repoRoot, config.remoteCommands) : config.provider ?? await getLocalProvider(config.repoRoot, config.excludes);
1913
+ const result = await runWarpGrep({
1914
+ searchTerm: parsed.search_term,
1915
+ repoRoot: config.repoRoot,
1916
+ provider,
1917
+ excludes: config.excludes,
1918
+ includes: config.includes,
1919
+ debug: config.debug ?? false,
1920
+ morphApiKey: config.morphApiKey,
1921
+ morphApiUrl: config.morphApiUrl,
1922
+ retryConfig: config.retryConfig,
1923
+ timeout: config.timeout
1924
+ });
1925
+ const finish = result.finish;
1926
+ if (result.terminationReason !== "completed" || !finish?.metadata) {
1927
+ const errorDetails = result.errors?.map((e) => e.message).join("; ") || "unknown reason";
1928
+ console.error(`[warp_grep] executeToolCall failed. Reason: ${result.terminationReason}. Errors: ${errorDetails}. Turns: ${result.timings?.turns?.length ?? 0}`);
1929
+ return { success: false, error: `Search did not complete: ${errorDetails}` };
1930
+ }
1931
+ const contexts = (finish.resolved ?? []).map((r) => ({
1932
+ file: r.path,
1933
+ content: r.content,
1934
+ lines: r.ranges
1935
+ }));
1936
+ return { success: true, contexts, summary: finish.payload };
1937
+ }
1938
+ function processAgentResult(result) {
1939
+ const finish = result.finish;
1940
+ if (result.terminationReason !== "completed" || !finish?.metadata) {
1941
+ const errorDetails = result.errors?.map((e) => e.message).join("; ") || "unknown reason";
1942
+ console.error(`[warp_grep] processAgentResult failed. Reason: ${result.terminationReason}. Errors: ${errorDetails}. Turns: ${result.timings?.turns?.length ?? 0}`);
1943
+ return { success: false, error: `Search did not complete: ${errorDetails}` };
1944
+ }
1945
+ const contexts = (finish.resolved ?? []).map((r) => ({
1946
+ file: r.path,
1947
+ content: r.content,
1948
+ lines: r.ranges
1949
+ }));
1950
+ return { success: true, contexts, summary: finish.payload };
1951
+ }
1952
+ async function* executeToolCallStreaming(input, config) {
1953
+ const parsed = typeof input === "string" ? JSON.parse(input) : input;
1954
+ const provider = config.remoteCommands ? new RemoteCommandsProvider(config.repoRoot, config.remoteCommands) : config.provider ?? await getLocalProvider(config.repoRoot, config.excludes);
1955
+ const generator = runWarpGrepStreaming({
1956
+ searchTerm: parsed.search_term,
1957
+ repoRoot: config.repoRoot,
1958
+ provider,
1959
+ excludes: config.excludes,
1960
+ includes: config.includes,
1961
+ debug: config.debug ?? false,
1962
+ morphApiKey: config.morphApiKey,
1963
+ morphApiUrl: config.morphApiUrl,
1964
+ retryConfig: config.retryConfig,
1965
+ timeout: config.timeout
1966
+ });
1967
+ let agentResult;
1968
+ for (; ; ) {
1969
+ const { value, done } = await generator.next();
1970
+ if (done) {
1971
+ agentResult = value;
1972
+ break;
1973
+ }
1974
+ yield value;
1975
+ }
1976
+ return processAgentResult(agentResult);
1977
+ }
1978
+ async function fetchRawGitHubFile(owner, repo, filePath, branch, timeout) {
1979
+ const branches = branch ? [branch] : ["HEAD"];
1980
+ const fallbacks = ["main", "master", "develop"];
1981
+ const fetchWithTimeout = (url) => timeout ? fetch(url, { signal: AbortSignal.timeout(timeout) }) : fetch(url);
1982
+ for (const b of branches) {
1983
+ const url = `https://raw.githubusercontent.com/${owner}/${repo}/${b}/${filePath}`;
1984
+ const res = await fetchWithTimeout(url);
1985
+ if (res.ok) return { content: await res.text(), branch: b };
1986
+ }
1987
+ for (const fb of fallbacks) {
1988
+ if (branch && fb === branch) continue;
1989
+ const url = `https://raw.githubusercontent.com/${owner}/${repo}/${fb}/${filePath}`;
1990
+ const res = await fetchWithTimeout(url);
1991
+ if (res.ok) return { content: await res.text(), branch: fb };
1992
+ }
1993
+ throw new Error(`File not found: ${owner}/${repo}/${filePath}`);
1994
+ }
1995
+ async function executeGitHubReadFile(input, config) {
1996
+ try {
1997
+ const { owner, repo } = parseGitHubUrl(input.github);
1998
+ const { content: raw, branch } = await fetchRawGitHubFile(
1999
+ owner,
2000
+ repo,
2001
+ input.path,
2002
+ input.branch,
2003
+ config?.timeout
2004
+ );
2005
+ const allLines = raw.split("\n");
2006
+ const totalLines = allLines.length;
2007
+ const start = Math.max(1, input.startLine ?? 1);
2008
+ const end = Math.min(totalLines, input.endLine ?? totalLines);
2009
+ const selected = allLines.slice(start - 1, end);
2010
+ const padWidth = String(end).length;
2011
+ const numbered = selected.map((line, i) => `${String(start + i).padStart(padWidth)}|${line}`).join("\n");
2012
+ return {
2013
+ success: true,
2014
+ content: numbered,
2015
+ path: input.path,
2016
+ github: `${owner}/${repo}`,
2017
+ branch,
2018
+ lineRange: [start, end],
2019
+ totalLines
2020
+ };
2021
+ } catch (error) {
2022
+ return {
2023
+ success: false,
2024
+ error: error instanceof Error ? error.message : String(error)
2025
+ };
2026
+ }
2027
+ }
2028
+ function formatResult(result) {
2029
+ if (!result.success) {
2030
+ return `Search failed: ${result.error}`;
2031
+ }
2032
+ if (!result.contexts || result.contexts.length === 0) {
2033
+ return "No relevant code found. Try rephrasing your search term.";
2034
+ }
2035
+ const parts = [];
2036
+ parts.push(`Morph Fast Context subagent performed search on repository:
2037
+ `);
2038
+ parts.push("Relevant context found:");
2039
+ for (const ctx of result.contexts) {
2040
+ const rangeStr = !ctx.lines || ctx.lines === "*" ? "*" : ctx.lines.map(([s, e]) => `${s}-${e}`).join(",");
2041
+ parts.push(`- ${ctx.file}:${rangeStr}`);
2042
+ }
2043
+ parts.push("\nHere is the content of files:\n");
2044
+ for (const ctx of result.contexts) {
2045
+ const rangeStr = !ctx.lines || ctx.lines === "*" ? "" : ` lines="${ctx.lines.map(([s, e]) => `${s}-${e}`).join(",")}"`;
2046
+ parts.push(`<file path="${ctx.file}"${rangeStr}>`);
2047
+ parts.push(ctx.content);
2048
+ parts.push("</file>\n");
2049
+ }
2050
+ return parts.join("\n");
2051
+ }
2052
+
2053
+ // subagents/prompts.ts
2054
+ var THOROUGHNESS_INSTRUCTIONS = {
2055
+ quick: `Do 1-2 targeted searches. Find the most relevant file/function quickly and summarize. Don't go deep.`,
2056
+ medium: `Do 2-4 searches. Start broad, then follow up on the most promising leads. Cover the main aspects.`,
2057
+ thorough: `Do 4-8 searches. Explore systematically: start broad, then drill into each relevant area. Cover edge cases, related files, and the full call chain. Leave no stone unturned.`
2058
+ };
2059
+ function getSystemPrompt(thoroughness = "medium") {
2060
+ return `You are a codebase exploration specialist. Your job is to search a codebase and return a concise, accurate summary of what you find.
2061
+
2062
+ ## Mode
2063
+ READ-ONLY. You cannot modify files. You can only search and read code.
2064
+
2065
+ ## Strategy
2066
+ ${THOROUGHNESS_INSTRUCTIONS[thoroughness]}
2067
+
2068
+ - Use multiple focused searches rather than one vague search
2069
+ - Follow imports, function calls, and type references to build complete understanding
2070
+ - If a search returns no results, try alternative terms (e.g., "auth" vs "authentication" vs "login")
2071
+ - Look at both implementation and tests when relevant
2072
+
2073
+ ## Communication
2074
+ You have a \`send_message\` tool. Use it when:
2075
+ - You hit a fork in the road and need guidance ("Found auth in both src/middleware/ and legacy/auth/. Which should I focus on?")
2076
+ - You need clarification on ambiguous requests ("There are 3 auth strategies: JWT, session, OAuth. Which one?")
2077
+ - You want to share a key finding before continuing ("The main auth handler is in src/auth/index.ts. It delegates to strategy-specific modules. Continuing to trace JWT flow.")
2078
+
2079
+ Do NOT use send_message for routine status updates. Only use it when you genuinely need input or have a significant finding worth sharing before you're done.
2080
+
2081
+ ## Output
2082
+ When you have enough information, output your final summary. Structure it as:
2083
+ 1. Direct answer to the question
2084
+ 2. Key files and their roles
2085
+ 3. How the pieces connect
2086
+
2087
+ Be concise. The summary should be useful to another AI model that will use your findings to complete a task.`;
2088
+ }
2089
+ var CODEBASE_SEARCH_TOOL = {
2090
+ name: "codebase_search",
2091
+ description: "Search the codebase for relevant code. Takes a natural language search request describing what you want to find. Returns matching file contents with line numbers.",
2092
+ input_schema: {
2093
+ type: "object",
2094
+ properties: {
2095
+ searchRequest: {
2096
+ type: "string",
2097
+ description: "Natural language description of what to search for in the codebase"
2098
+ }
2099
+ },
2100
+ required: ["searchRequest"],
2101
+ additionalProperties: false
2102
+ }
2103
+ };
2104
+ var SEND_MESSAGE_TOOL = {
2105
+ name: "send_message",
2106
+ description: "Send a message to the orchestrating agent. Use this to ask questions, request clarification, or share important findings. The orchestrator may reply with additional context. Use sparingly \u2014 only when you genuinely need input or have a significant finding.",
2107
+ input_schema: {
2108
+ type: "object",
2109
+ properties: {
2110
+ message: {
2111
+ type: "string",
2112
+ description: "The message to send to the orchestrator"
2113
+ }
2114
+ },
2115
+ required: ["message"],
2116
+ additionalProperties: false
2117
+ }
2118
+ };
2119
+
2120
+ // subagents/anthropic.ts
2121
+ var DEFAULT_MAX_TURNS = {
2122
+ quick: 3,
2123
+ medium: 6,
2124
+ thorough: 12
2125
+ };
2126
+ function getMaxTurns(config) {
2127
+ return config.maxTurns ?? DEFAULT_MAX_TURNS[config.thoroughness ?? "medium"] ?? 6;
2128
+ }
2129
+ var TOOLS = [
2130
+ {
2131
+ name: CODEBASE_SEARCH_TOOL.name,
2132
+ description: CODEBASE_SEARCH_TOOL.description,
2133
+ input_schema: CODEBASE_SEARCH_TOOL.input_schema
2134
+ },
2135
+ {
2136
+ name: SEND_MESSAGE_TOOL.name,
2137
+ description: SEND_MESSAGE_TOOL.description,
2138
+ input_schema: SEND_MESSAGE_TOOL.input_schema
2139
+ }
2140
+ ];
2141
+ function createExploreSubagent(config) {
2142
+ if (!config.repoRoot) {
2143
+ throw new Error("repoRoot is required for Explore subagent");
2144
+ }
2145
+ const warpGrep = new WarpGrepClient({
2146
+ morphApiKey: config.morphApiKey
2147
+ });
2148
+ const thoroughness = config.thoroughness ?? "medium";
2149
+ const maxTurns = getMaxTurns(config);
2150
+ const replyTimeout = config.replyTimeout ?? 3e4;
2151
+ async function runExplore(prompt, callbacks = {}) {
2152
+ const startTime = Date.now();
2153
+ const allContexts = [];
2154
+ let searchCount = 0;
2155
+ const timeoutMs = config.timeout;
2156
+ try {
2157
+ const messages = [{ role: "user", content: prompt }];
2158
+ let turns = 0;
2159
+ while (turns < maxTurns) {
2160
+ if (timeoutMs && Date.now() - startTime > timeoutMs) {
2161
+ return {
2162
+ success: false,
2163
+ summary: "",
2164
+ contexts: deduplicateContexts(allContexts),
2165
+ searchCount,
2166
+ durationMs: Date.now() - startTime,
2167
+ error: `Exploration timed out after ${timeoutMs}ms`
2168
+ };
2169
+ }
2170
+ const response = await config.client.messages.create({
2171
+ model: config.model,
2172
+ max_tokens: 4096,
2173
+ system: getSystemPrompt(thoroughness),
2174
+ tools: TOOLS,
2175
+ messages
2176
+ });
2177
+ turns++;
2178
+ if (response.stop_reason === "end_turn" || !response.content.some((b) => b.type === "tool_use")) {
2179
+ const textBlock = response.content.find((b) => b.type === "text");
2180
+ const summary = textBlock?.text || "Exploration completed but no summary was generated.";
2181
+ callbacks.onStep?.({
2182
+ step: searchCount,
2183
+ searchRequest: "",
2184
+ contextsFound: allContexts.length,
2185
+ isFinal: true
2186
+ });
2187
+ return {
2188
+ success: true,
2189
+ summary,
2190
+ contexts: deduplicateContexts(allContexts),
2191
+ searchCount,
2192
+ durationMs: Date.now() - startTime
2193
+ };
2194
+ }
2195
+ messages.push({ role: "assistant", content: response.content });
2196
+ const toolResults = [];
2197
+ for (const block of response.content) {
2198
+ if (block.type !== "tool_use") continue;
2199
+ if (block.name === "codebase_search") {
2200
+ searchCount++;
2201
+ const input = block.input;
2202
+ const warpResult = await warpGrep.execute({
2203
+ searchTerm: input.searchRequest,
2204
+ repoRoot: config.repoRoot,
2205
+ excludes: config.excludes,
2206
+ includes: config.includes
2207
+ });
2208
+ if (warpResult.contexts) {
2209
+ allContexts.push(...warpResult.contexts);
2210
+ }
2211
+ callbacks.onStep?.({
2212
+ step: searchCount,
2213
+ searchRequest: input.searchRequest,
2214
+ contextsFound: warpResult.contexts?.length ?? 0,
2215
+ isFinal: false
2216
+ });
2217
+ toolResults.push({
2218
+ type: "tool_result",
2219
+ tool_use_id: block.id,
2220
+ content: formatResult(warpResult)
2221
+ });
2222
+ } else if (block.name === "send_message") {
2223
+ const input = block.input;
2224
+ const subagentMsg = {
2225
+ from: "explore",
2226
+ content: input.message,
2227
+ timestamp: Date.now()
2228
+ };
2229
+ let replyText = "";
2230
+ if (callbacks.onMessage) {
2231
+ replyText = await Promise.race([
2232
+ new Promise((resolve) => {
2233
+ callbacks.onMessage(subagentMsg, (text) => {
2234
+ resolve(text);
2235
+ });
2236
+ }),
2237
+ new Promise(
2238
+ (resolve) => setTimeout(() => resolve(""), replyTimeout)
2239
+ )
2240
+ ]);
2241
+ }
2242
+ const toolResponse = replyText ? `Response from orchestrator: ${replyText}` : "No response. Continue with your best judgment.";
2243
+ toolResults.push({
2244
+ type: "tool_result",
2245
+ tool_use_id: block.id,
2246
+ content: toolResponse
2247
+ });
2248
+ }
2249
+ }
2250
+ messages.push({ role: "user", content: toolResults });
2251
+ }
2252
+ return {
2253
+ success: true,
2254
+ summary: "Exploration completed (max turns reached).",
2255
+ contexts: deduplicateContexts(allContexts),
2256
+ searchCount,
2257
+ durationMs: Date.now() - startTime
2258
+ };
2259
+ } catch (error) {
2260
+ return {
2261
+ success: false,
2262
+ summary: "",
2263
+ contexts: deduplicateContexts(allContexts),
2264
+ searchCount,
2265
+ durationMs: Date.now() - startTime,
2266
+ error: error instanceof Error ? error.message : String(error)
2267
+ };
2268
+ }
2269
+ }
2270
+ const exploreTool = Object.assign(
2271
+ {
2272
+ name: "explore",
2273
+ description: "Explore a codebase to answer questions about code structure, find implementations, trace call chains, and understand architecture. Returns a summary of findings.",
2274
+ input_schema: {
2275
+ type: "object",
2276
+ properties: {
2277
+ searchRequest: {
2278
+ type: "string",
2279
+ description: "What to explore in the codebase. Be specific about what you want to understand."
2280
+ }
2281
+ },
2282
+ required: ["searchRequest"]
2283
+ }
2284
+ },
2285
+ {
2286
+ execute: async (input) => {
2287
+ return runExplore(input.searchRequest);
2288
+ },
2289
+ formatResult: (result) => {
2290
+ if (!result.success) {
2291
+ return `Exploration failed: ${result.error}`;
2292
+ }
2293
+ return result.summary;
2294
+ }
2295
+ }
2296
+ );
2297
+ return {
2298
+ /** Anthropic Tool definition for use in parent agents */
2299
+ tool: exploreTool,
2300
+ /** Run exploration with messaging support */
2301
+ run(prompt) {
2302
+ const messageHandlers = [];
2303
+ const stepHandlers = [];
2304
+ let resultPromise = null;
2305
+ const session = {
2306
+ on(event, handler) {
2307
+ if (event === "message") messageHandlers.push(handler);
2308
+ if (event === "step") stepHandlers.push(handler);
2309
+ return session;
2310
+ },
2311
+ send(_text) {
2312
+ },
2313
+ get result() {
2314
+ if (!resultPromise) {
2315
+ resultPromise = runExplore(prompt, {
2316
+ onStep: (step) => {
2317
+ for (const handler of stepHandlers) handler(step);
2318
+ },
2319
+ onMessage: (msg, reply) => {
2320
+ if (messageHandlers.length > 0) {
2321
+ for (const handler of messageHandlers) handler(msg, reply);
2322
+ } else {
2323
+ reply("");
2324
+ }
2325
+ }
2326
+ });
2327
+ }
2328
+ return resultPromise;
2329
+ }
2330
+ };
2331
+ return session;
2332
+ },
2333
+ /** Stream exploration events as an async generator */
2334
+ async *stream(prompt) {
2335
+ const events = [];
2336
+ let resolveNext = null;
2337
+ let done = false;
2338
+ const resultPromise = runExplore(prompt, {
2339
+ onStep: (step) => {
2340
+ events.push({
2341
+ type: "step",
2342
+ step: step.step,
2343
+ searchRequest: step.searchRequest,
2344
+ contextsFound: step.contextsFound,
2345
+ isFinal: step.isFinal
2346
+ });
2347
+ resolveNext?.();
2348
+ },
2349
+ onMessage: (msg, reply) => {
2350
+ events.push({
2351
+ type: "message",
2352
+ from: msg.from,
2353
+ content: msg.content,
2354
+ timestamp: msg.timestamp
2355
+ });
2356
+ resolveNext?.();
2357
+ reply("Continue with your best judgment.");
2358
+ }
2359
+ });
2360
+ while (!done) {
2361
+ if (events.length > 0) {
2362
+ yield events.shift();
2363
+ } else {
2364
+ const raceResult = await Promise.race([
2365
+ resultPromise.then((r) => ({ type: "done", result: r })),
2366
+ new Promise((resolve) => {
2367
+ resolveNext = () => resolve({ type: "event" });
2368
+ })
2369
+ ]);
2370
+ if (raceResult.type === "done") {
2371
+ while (events.length > 0) {
2372
+ yield events.shift();
2373
+ }
2374
+ done = true;
2375
+ return raceResult.result;
2376
+ }
2377
+ }
2378
+ }
2379
+ return await resultPromise;
2380
+ }
2381
+ };
2382
+ }
2383
+ function deduplicateContexts(contexts) {
2384
+ const map = /* @__PURE__ */ new Map();
2385
+ for (const ctx of contexts) {
2386
+ const existing = map.get(ctx.file);
2387
+ if (!existing || ctx.content.length > existing.content.length) {
2388
+ map.set(ctx.file, ctx);
2389
+ }
2390
+ }
2391
+ return Array.from(map.values());
2392
+ }
2393
+ // Annotate the CommonJS export names for ESM import in node:
2394
+ 0 && (module.exports = {
2395
+ createExploreSubagent
2396
+ });
2397
+ //# sourceMappingURL=anthropic.cjs.map