@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,2374 @@
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/vercel.ts
580
+ var vercel_exports = {};
581
+ __export(vercel_exports, {
582
+ createExploreSubagent: () => createExploreSubagent
583
+ });
584
+ module.exports = __toCommonJS(vercel_exports);
585
+ var import_ai = require("ai");
586
+ var import_zod = require("zod");
587
+
588
+ // tools/warp_grep/agent/runner.ts
589
+ init_config();
590
+
591
+ // tools/warp_grep/agent/parser.ts
592
+ var VALID_COMMANDS = ["list_directory", "ripgrep", "read", "finish"];
593
+ function isValidCommand(name) {
594
+ return VALID_COMMANDS.includes(name);
595
+ }
596
+ function parseQwen3ToolCalls(text) {
597
+ const tools = [];
598
+ const toolCallRegex = /<tool_call>\s*<function=([a-z_][a-z0-9_]*)>([\s\S]*?)<\/function>\s*<\/tool_call>/gi;
599
+ let match;
600
+ while ((match = toolCallRegex.exec(text)) !== null) {
601
+ const funcName = match[1].toLowerCase();
602
+ const body = match[2];
603
+ if (!isValidCommand(funcName)) continue;
604
+ const params = {};
605
+ const paramRegex = /<parameter=([a-z_][a-z0-9_]*)>([\s\S]*?)<\/parameter>/gi;
606
+ let paramMatch;
607
+ while ((paramMatch = paramRegex.exec(body)) !== null) {
608
+ params[paramMatch[1].toLowerCase()] = paramMatch[2].trim();
609
+ }
610
+ if (funcName === "ripgrep") {
611
+ const pattern = params.pattern;
612
+ if (!pattern) continue;
613
+ const args = {
614
+ pattern,
615
+ path: params.path || ".",
616
+ ...params.glob && { glob: params.glob },
617
+ ...params.context_lines && { context_lines: parseInt(params.context_lines, 10) },
618
+ ...params.case_sensitive && { case_sensitive: params.case_sensitive === "true" }
619
+ };
620
+ tools.push({ name: "grep", arguments: args });
621
+ } else if (funcName === "list_directory") {
622
+ const command = params.command;
623
+ const directPath = params.path;
624
+ let dirPath = directPath || ".";
625
+ if (!directPath && command) {
626
+ const tokens = command.trim().split(/\s+/);
627
+ const pathTokens = tokens.slice(1).filter((t) => !t.startsWith("-") && !t.startsWith("|") && !t.startsWith("\\("));
628
+ if (pathTokens.length > 0) {
629
+ dirPath = pathTokens[0];
630
+ }
631
+ }
632
+ tools.push({ name: "list_directory", arguments: { path: dirPath, pattern: params.pattern || null } });
633
+ } else if (funcName === "read") {
634
+ const filePath = params.path;
635
+ if (!filePath) continue;
636
+ const args = { path: filePath };
637
+ const linesStr = params.lines;
638
+ if (linesStr) {
639
+ const ranges = [];
640
+ for (const rangeStr of linesStr.split(",")) {
641
+ const trimmed = rangeStr.trim();
642
+ if (!trimmed) continue;
643
+ const [s, e] = trimmed.split("-").map((v) => parseInt(v.trim(), 10));
644
+ if (Number.isFinite(s) && Number.isFinite(e)) {
645
+ ranges.push([s, e]);
646
+ } else if (Number.isFinite(s)) {
647
+ ranges.push([s, s]);
648
+ }
649
+ }
650
+ if (ranges.length === 1) {
651
+ args.start = ranges[0][0];
652
+ args.end = ranges[0][1];
653
+ } else if (ranges.length > 1) {
654
+ args.lines = ranges;
655
+ }
656
+ }
657
+ tools.push({ name: "read", arguments: args });
658
+ } else if (funcName === "finish") {
659
+ if (params.result && !params.files) {
660
+ tools.push({ name: "finish", arguments: { files: [], textResult: params.result } });
661
+ continue;
662
+ }
663
+ const filesStr = params.files;
664
+ if (!filesStr) {
665
+ tools.push({ name: "finish", arguments: { files: [], textResult: "No relevant code found." } });
666
+ continue;
667
+ }
668
+ const files = [];
669
+ for (const line of filesStr.split("\n")) {
670
+ const trimmed = line.trim();
671
+ if (!trimmed) continue;
672
+ const colonIdx = trimmed.indexOf(":");
673
+ if (colonIdx === -1) {
674
+ files.push({ path: trimmed, lines: "*" });
675
+ } else {
676
+ const filePath = trimmed.slice(0, colonIdx);
677
+ const rangesPart = trimmed.slice(colonIdx + 1);
678
+ const ranges = [];
679
+ for (const rangeStr of rangesPart.split(",")) {
680
+ const rt = rangeStr.trim();
681
+ if (!rt || rt === "*") {
682
+ files.push({ path: filePath, lines: "*" });
683
+ break;
684
+ }
685
+ const [s, e] = rt.split("-").map((v) => parseInt(v.trim(), 10));
686
+ if (Number.isFinite(s) && Number.isFinite(e)) {
687
+ ranges.push([s, e]);
688
+ } else if (Number.isFinite(s)) {
689
+ ranges.push([s, s]);
690
+ }
691
+ }
692
+ if (ranges.length > 0) {
693
+ files.push({ path: filePath, lines: ranges });
694
+ } else if (!files.some((f) => f.path === filePath)) {
695
+ files.push({ path: filePath, lines: "*" });
696
+ }
697
+ }
698
+ }
699
+ if (files.length > 0) {
700
+ tools.push({ name: "finish", arguments: { files } });
701
+ } else {
702
+ tools.push({ name: "finish", arguments: { files: [], textResult: filesStr } });
703
+ }
704
+ }
705
+ }
706
+ return tools;
707
+ }
708
+ var LLMResponseParser = class {
709
+ parse(text) {
710
+ if (typeof text !== "string") {
711
+ throw new TypeError("Command text must be a string.");
712
+ }
713
+ const withoutThink = text.replace(/<think>[\s\S]*?<\/think>/gi, "");
714
+ return parseQwen3ToolCalls(withoutThink);
715
+ }
716
+ };
717
+
718
+ // tools/warp_grep/agent/tools/grep.ts
719
+ async function toolGrep(provider, args) {
720
+ const res = await provider.grep(args);
721
+ if (res.error) {
722
+ return { output: res.error };
723
+ }
724
+ if (!res.lines.length) {
725
+ return { output: "no matches" };
726
+ }
727
+ return { output: res.lines.join("\n") };
728
+ }
729
+
730
+ // tools/warp_grep/agent/tools/read.ts
731
+ function isValidRange(start, end) {
732
+ return typeof start === "number" && typeof end === "number" && Number.isFinite(start) && Number.isFinite(end) && start > 0 && end >= start;
733
+ }
734
+ async function toolRead(provider, args) {
735
+ if (args.lines && Array.isArray(args.lines) && args.lines.length > 0) {
736
+ const validRanges = [];
737
+ for (const range of args.lines) {
738
+ if (Array.isArray(range) && range.length >= 2 && isValidRange(range[0], range[1])) {
739
+ validRanges.push([range[0], range[1]]);
740
+ }
741
+ }
742
+ if (validRanges.length === 0) {
743
+ const res2 = await provider.read({ path: args.path });
744
+ if (res2.error) return res2.error;
745
+ if (!res2.lines.length) return "(empty file)";
746
+ return res2.lines.join("\n");
747
+ }
748
+ const chunks = [];
749
+ for (const [start, end] of validRanges) {
750
+ const res2 = await provider.read({ path: args.path, start, end });
751
+ if (res2.error) return res2.error;
752
+ chunks.push(res2.lines.join("\n"));
753
+ }
754
+ if (chunks.every((c) => c === "")) return "(empty file)";
755
+ return chunks.join("\n...\n");
756
+ }
757
+ const res = await provider.read({ path: args.path, start: args.start, end: args.end });
758
+ if (res.error) {
759
+ return res.error;
760
+ }
761
+ if (!res.lines.length) return "(empty file)";
762
+ return res.lines.join("\n");
763
+ }
764
+
765
+ // tools/warp_grep/agent/tools/list_directory.ts
766
+ init_config();
767
+ async function toolListDirectory(provider, args) {
768
+ const maxResults = args.maxResults ?? AGENT_CONFIG.MAX_OUTPUT_LINES;
769
+ const initialDepth = args.maxDepth ?? AGENT_CONFIG.MAX_LIST_DEPTH;
770
+ async function getListRecursive(currentDepth) {
771
+ const entries = await provider.listDirectory({
772
+ path: args.path,
773
+ pattern: args.pattern ?? null,
774
+ maxResults,
775
+ maxDepth: currentDepth
776
+ });
777
+ if (entries.length >= maxResults && currentDepth > 0) {
778
+ return getListRecursive(currentDepth - 1);
779
+ }
780
+ return { entries };
781
+ }
782
+ const { entries: list } = await getListRecursive(initialDepth);
783
+ if (!list.length) return "empty";
784
+ const tree = list.map((e) => {
785
+ const indent = " ".repeat(e.depth);
786
+ const name = e.type === "dir" ? `${e.name}/` : e.name;
787
+ return `${indent}${name}`;
788
+ }).join("\n");
789
+ return tree;
790
+ }
791
+
792
+ // tools/warp_grep/agent/tools/finish.ts
793
+ function isValidRange2(range) {
794
+ 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];
795
+ }
796
+ function extractValidRanges(lines) {
797
+ if (!Array.isArray(lines)) return null;
798
+ const valid = [];
799
+ for (const range of lines) {
800
+ if (isValidRange2(range)) {
801
+ valid.push([range[0], range[1]]);
802
+ }
803
+ }
804
+ return valid.length > 0 ? valid : null;
805
+ }
806
+ async function readFinishFiles(repoRoot, files, reader) {
807
+ const out = [];
808
+ for (const f of files) {
809
+ const validRanges = f.lines === "*" ? null : extractValidRanges(f.lines);
810
+ if (f.lines === "*" || !validRanges) {
811
+ const lines = await reader(f.path);
812
+ out.push({ path: f.path, ranges: "*", content: lines.join("\n") });
813
+ } else {
814
+ const ranges = mergeRanges(validRanges);
815
+ const chunks = [];
816
+ for (let i = 0; i < ranges.length; i++) {
817
+ const [s, e] = ranges[i];
818
+ if (i === 0 && s > 1) {
819
+ chunks.push(`// ... existing code, block starting at line ${s} ...`);
820
+ } else if (i > 0) {
821
+ chunks.push(`// ... existing code, block starting at line ${s} ...`);
822
+ }
823
+ const lines = await reader(f.path, s, e);
824
+ chunks.push(lines.join("\n"));
825
+ }
826
+ out.push({ path: f.path, ranges, content: chunks.join("\n") });
827
+ }
828
+ }
829
+ return out;
830
+ }
831
+ function mergeRanges(ranges) {
832
+ if (!ranges.length) return [];
833
+ const sorted = [...ranges].sort((a, b) => a[0] - b[0]);
834
+ const merged = [];
835
+ let [cs, ce] = sorted[0];
836
+ for (let i = 1; i < sorted.length; i++) {
837
+ const [s, e] = sorted[i];
838
+ if (s <= ce + 1) {
839
+ ce = Math.max(ce, e);
840
+ } else {
841
+ merged.push([cs, ce]);
842
+ cs = s;
843
+ ce = e;
844
+ }
845
+ }
846
+ merged.push([cs, ce]);
847
+ return merged;
848
+ }
849
+
850
+ // tools/warp_grep/agent/formatter.ts
851
+ var ToolOutputFormatter = class {
852
+ format(toolName, _args, output, options = {}) {
853
+ const name = (toolName ?? "").trim();
854
+ if (!name) {
855
+ return "";
856
+ }
857
+ const payload = output?.toString?.()?.trim?.() ?? "";
858
+ const isError = Boolean(options.isError);
859
+ if (!payload && !isError) {
860
+ return "";
861
+ }
862
+ return `<tool_response>
863
+ ${payload}
864
+ </tool_response>`;
865
+ }
866
+ };
867
+ var sharedFormatter = new ToolOutputFormatter();
868
+ function formatAgentToolOutput(toolName, args, output, options = {}) {
869
+ return sharedFormatter.format(toolName, args, output, options);
870
+ }
871
+
872
+ // tools/warp_grep/agent/helpers.ts
873
+ var import_path = __toESM(require("path"), 1);
874
+ init_config();
875
+ var TRUNCATED_MARKER = "[truncated for context limit]";
876
+ function formatTurnMessage(turnsUsed, maxTurns) {
877
+ const turnsRemaining = maxTurns - turnsUsed;
878
+ if (turnsRemaining === 1) {
879
+ return `
880
+ 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`;
881
+ }
882
+ return `
883
+ You have used ${turnsUsed} turn${turnsUsed === 1 ? "" : "s"} and have ${turnsRemaining} remaining`;
884
+ }
885
+ function calculateContextBudget(messages) {
886
+ const totalChars = messages.reduce((sum, m) => sum + m.content.length, 0);
887
+ const maxChars = AGENT_CONFIG.MAX_CONTEXT_CHARS;
888
+ const percent = Math.round(totalChars / maxChars * 100);
889
+ const usedK = Math.round(totalChars / 1e3);
890
+ const maxK = Math.round(maxChars / 1e3);
891
+ return `<context_budget>${percent}% (${usedK}K/${maxK}K chars)</context_budget>`;
892
+ }
893
+ async function buildInitialState(repoRoot, searchTerm, provider, options) {
894
+ const budget = calculateContextBudget([]);
895
+ const turnTag = `Turn 0/${AGENT_CONFIG.MAX_TURNS}`;
896
+ const treeDepth = options?.search_type === "node_modules" ? 1 : 2;
897
+ try {
898
+ const entries = await provider.listDirectory({
899
+ path: ".",
900
+ maxResults: AGENT_CONFIG.MAX_OUTPUT_LINES,
901
+ maxDepth: treeDepth
902
+ });
903
+ const treeLines = entries.map((e) => {
904
+ const indent = " ".repeat(e.depth);
905
+ const name = e.type === "dir" ? `${e.name}/` : e.name;
906
+ return `${indent}${name}`;
907
+ });
908
+ const repoName = import_path.default.basename(repoRoot);
909
+ const treeOutput = treeLines.length > 0 ? `${repoName}/
910
+ ${treeLines.join("\n")}` : `${repoName}/`;
911
+ return `<repo_structure>
912
+ ${treeOutput}
913
+ </repo_structure>
914
+
915
+ <search_string>
916
+ ${searchTerm}
917
+ </search_string>
918
+ ${budget}
919
+ ${turnTag}`;
920
+ } catch {
921
+ const repoName = import_path.default.basename(repoRoot);
922
+ return `<repo_structure>
923
+ ${repoName}/
924
+ </repo_structure>
925
+
926
+ <search_string>
927
+ ${searchTerm}
928
+ </search_string>
929
+ ${budget}
930
+ ${turnTag}`;
931
+ }
932
+ }
933
+ function enforceContextLimit(messages, maxChars = AGENT_CONFIG.MAX_CONTEXT_CHARS) {
934
+ const getTotalChars = () => messages.reduce((sum, m) => sum + m.content.length, 0);
935
+ if (getTotalChars() <= maxChars) {
936
+ return messages;
937
+ }
938
+ const userIndices = [];
939
+ let firstUserSkipped = false;
940
+ for (let i = 0; i < messages.length; i++) {
941
+ if (messages[i].role === "user") {
942
+ if (!firstUserSkipped) {
943
+ firstUserSkipped = true;
944
+ continue;
945
+ }
946
+ userIndices.push(i);
947
+ }
948
+ }
949
+ for (const idx of userIndices) {
950
+ if (getTotalChars() <= maxChars) {
951
+ break;
952
+ }
953
+ if (messages[idx].content !== TRUNCATED_MARKER) {
954
+ messages[idx] = { role: "user", content: TRUNCATED_MARKER };
955
+ }
956
+ }
957
+ return messages;
958
+ }
959
+
960
+ // tools/warp_grep/agent/runner.ts
961
+ var import_openai = __toESM(require("openai"), 1);
962
+
963
+ // package.json
964
+ var package_default = {
965
+ name: "@morphllm/morphsdk",
966
+ version: "0.2.139",
967
+ description: "TypeScript SDK and CLI for Morph Fast Apply integration",
968
+ type: "module",
969
+ main: "./dist/index.cjs",
970
+ module: "./dist/index.js",
971
+ types: "./dist/index.d.ts",
972
+ exports: {
973
+ ".": {
974
+ types: "./dist/index.d.ts",
975
+ import: "./dist/index.js",
976
+ require: "./dist/index.cjs"
977
+ },
978
+ "./edge": {
979
+ types: "./dist/edge.d.ts",
980
+ import: "./dist/edge.js",
981
+ require: "./dist/edge.cjs"
982
+ },
983
+ "./tools/warp-grep": {
984
+ types: "./dist/tools/warp_grep/index.d.ts",
985
+ import: "./dist/tools/warp_grep/index.js",
986
+ require: "./dist/tools/warp_grep/index.cjs"
987
+ },
988
+ "./tools/warp-grep/openai": {
989
+ types: "./dist/tools/warp_grep/openai.d.ts",
990
+ import: "./dist/tools/warp_grep/openai.js",
991
+ require: "./dist/tools/warp_grep/openai.cjs"
992
+ },
993
+ "./tools/warp-grep/anthropic": {
994
+ types: "./dist/tools/warp_grep/anthropic.d.ts",
995
+ import: "./dist/tools/warp_grep/anthropic.js",
996
+ require: "./dist/tools/warp_grep/anthropic.cjs"
997
+ },
998
+ "./tools/warp-grep/vercel": {
999
+ types: "./dist/tools/warp_grep/vercel.d.ts",
1000
+ import: "./dist/tools/warp_grep/vercel.js",
1001
+ require: "./dist/tools/warp_grep/vercel.cjs"
1002
+ },
1003
+ "./tools/warp-grep/client": {
1004
+ types: "./dist/tools/warp_grep/client.d.ts",
1005
+ import: "./dist/tools/warp_grep/client.js",
1006
+ require: "./dist/tools/warp_grep/client.cjs"
1007
+ },
1008
+ "./tools/warp-grep/gemini": {
1009
+ types: "./dist/tools/warp_grep/gemini.d.ts",
1010
+ import: "./dist/tools/warp_grep/gemini.js",
1011
+ require: "./dist/tools/warp_grep/gemini.cjs"
1012
+ },
1013
+ "./tools/warp-grep/harness": {
1014
+ types: "./dist/tools/warp_grep/harness.d.ts",
1015
+ import: "./dist/tools/warp_grep/harness.js",
1016
+ require: "./dist/tools/warp_grep/harness.cjs"
1017
+ },
1018
+ "./tools/fastapply": {
1019
+ types: "./dist/tools/fastapply/index.d.ts",
1020
+ import: "./dist/tools/fastapply/index.js",
1021
+ require: "./dist/tools/fastapply/index.cjs"
1022
+ },
1023
+ "./tools/fastapply/anthropic": {
1024
+ types: "./dist/tools/fastapply/anthropic.d.ts",
1025
+ import: "./dist/tools/fastapply/anthropic.js",
1026
+ require: "./dist/tools/fastapply/anthropic.cjs"
1027
+ },
1028
+ "./tools/fastapply/openai": {
1029
+ types: "./dist/tools/fastapply/openai.d.ts",
1030
+ import: "./dist/tools/fastapply/openai.js",
1031
+ require: "./dist/tools/fastapply/openai.cjs"
1032
+ },
1033
+ "./tools/fastapply/vercel": {
1034
+ types: "./dist/tools/fastapply/vercel.d.ts",
1035
+ import: "./dist/tools/fastapply/vercel.js",
1036
+ require: "./dist/tools/fastapply/vercel.cjs"
1037
+ },
1038
+ "./tools/codebase-search": {
1039
+ types: "./dist/tools/codebase_search/index.d.ts",
1040
+ import: "./dist/tools/codebase_search/index.js",
1041
+ require: "./dist/tools/codebase_search/index.cjs"
1042
+ },
1043
+ "./tools/codebase-search/anthropic": {
1044
+ types: "./dist/tools/codebase_search/anthropic.d.ts",
1045
+ import: "./dist/tools/codebase_search/anthropic.js",
1046
+ require: "./dist/tools/codebase_search/anthropic.cjs"
1047
+ },
1048
+ "./tools/codebase-search/openai": {
1049
+ types: "./dist/tools/codebase_search/openai.d.ts",
1050
+ import: "./dist/tools/codebase_search/openai.js",
1051
+ require: "./dist/tools/codebase_search/openai.cjs"
1052
+ },
1053
+ "./tools/codebase-search/vercel": {
1054
+ types: "./dist/tools/codebase_search/vercel.d.ts",
1055
+ import: "./dist/tools/codebase_search/vercel.js",
1056
+ require: "./dist/tools/codebase_search/vercel.cjs"
1057
+ },
1058
+ "./tools/git": {
1059
+ types: "./dist/git/index.d.ts",
1060
+ import: "./dist/git/index.js",
1061
+ require: "./dist/git/index.cjs"
1062
+ },
1063
+ "./tools/browser": {
1064
+ types: "./dist/tools/browser/index.d.ts",
1065
+ import: "./dist/tools/browser/index.js",
1066
+ require: "./dist/tools/browser/index.cjs"
1067
+ },
1068
+ "./tools/browser/anthropic": {
1069
+ types: "./dist/tools/browser/anthropic.d.ts",
1070
+ import: "./dist/tools/browser/anthropic.js",
1071
+ require: "./dist/tools/browser/anthropic.cjs"
1072
+ },
1073
+ "./tools/browser/openai": {
1074
+ types: "./dist/tools/browser/openai.d.ts",
1075
+ import: "./dist/tools/browser/openai.js",
1076
+ require: "./dist/tools/browser/openai.cjs"
1077
+ },
1078
+ "./tools/browser/vercel": {
1079
+ types: "./dist/tools/browser/vercel.d.ts",
1080
+ import: "./dist/tools/browser/vercel.js",
1081
+ require: "./dist/tools/browser/vercel.cjs"
1082
+ },
1083
+ "./tools/browser/profiles": {
1084
+ types: "./dist/tools/browser/profiles/index.d.ts",
1085
+ import: "./dist/tools/browser/profiles/index.js",
1086
+ require: "./dist/tools/browser/profiles/index.cjs"
1087
+ },
1088
+ "./modelrouter": {
1089
+ types: "./dist/modelrouter/index.d.ts",
1090
+ import: "./dist/modelrouter/index.js",
1091
+ require: "./dist/modelrouter/index.cjs"
1092
+ },
1093
+ "./tools/compact": {
1094
+ types: "./dist/tools/compact/index.d.ts",
1095
+ import: "./dist/tools/compact/index.js",
1096
+ require: "./dist/tools/compact/index.cjs"
1097
+ },
1098
+ "./subagents": {
1099
+ types: "./dist/subagents/index.d.ts",
1100
+ import: "./dist/subagents/index.js",
1101
+ require: "./dist/subagents/index.cjs"
1102
+ },
1103
+ "./subagents/vercel": {
1104
+ types: "./dist/subagents/vercel.d.ts",
1105
+ import: "./dist/subagents/vercel.js",
1106
+ require: "./dist/subagents/vercel.cjs"
1107
+ },
1108
+ "./subagents/anthropic": {
1109
+ types: "./dist/subagents/anthropic.d.ts",
1110
+ import: "./dist/subagents/anthropic.js",
1111
+ require: "./dist/subagents/anthropic.cjs"
1112
+ }
1113
+ },
1114
+ files: [
1115
+ "dist/**/*.js",
1116
+ "dist/**/*.cjs",
1117
+ "dist/**/*.d.ts",
1118
+ "dist/**/*.map",
1119
+ "!dist/**/__tests__/**",
1120
+ "!dist/**/*.test.*"
1121
+ ],
1122
+ scripts: {
1123
+ 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",
1124
+ prepare: "npm run build",
1125
+ typecheck: "tsc --noEmit",
1126
+ lint: "eslint .",
1127
+ test: "vitest run",
1128
+ "test:watch": "vitest watch",
1129
+ "test:anthropic": "vitest run anthropic",
1130
+ "test:openai": "vitest run openai",
1131
+ "test:vercel": "vitest run vercel",
1132
+ "test:git": "vitest run git",
1133
+ "test:browser": "vitest run browser",
1134
+ "test:agent": "npx tsx tests/fullAgentTest.ts",
1135
+ "test:integration": "npx tsx tests/fullIntegrationTest.ts",
1136
+ "release:patch": "npm version patch && npm publish",
1137
+ "release:minor": "npm version minor && npm publish",
1138
+ "release:major": "npm version major && npm publish"
1139
+ },
1140
+ keywords: [
1141
+ "morph",
1142
+ "fast-apply",
1143
+ "cli",
1144
+ "sdk",
1145
+ "edit-file"
1146
+ ],
1147
+ engines: {
1148
+ node: ">=18"
1149
+ },
1150
+ license: "MIT",
1151
+ dependencies: {
1152
+ "@vscode/ripgrep": "^1.17.0",
1153
+ ai: ">=5.0.0",
1154
+ diff: "^7.0.0",
1155
+ "isomorphic-git": "^1.25.10",
1156
+ openai: "^4.52.7",
1157
+ zod: ">=3.23.0"
1158
+ },
1159
+ devDependencies: {
1160
+ "@ai-sdk/anthropic": "^2.0.70",
1161
+ "@ai-sdk/openai": "^2.0.35",
1162
+ "@anthropic-ai/sdk": "^0.30.1",
1163
+ "@google/generative-ai": "^0.24.1",
1164
+ "@types/diff": "^7.0.2",
1165
+ "@types/node": "^20.14.10",
1166
+ "@typescript-eslint/eslint-plugin": "^7.18.0",
1167
+ "@typescript-eslint/parser": "^7.18.0",
1168
+ dotenv: "^16.4.5",
1169
+ eslint: "^8.57.0",
1170
+ shx: "^0.3.4",
1171
+ tsup: "^8.5.0",
1172
+ tsx: "^4.16.2",
1173
+ typescript: "^5.5.4",
1174
+ vitest: "^2.1.6"
1175
+ },
1176
+ peerDependencies: {
1177
+ "@anthropic-ai/sdk": ">=0.25.0",
1178
+ "@google/generative-ai": ">=0.21.0",
1179
+ ai: ">=5.0.0",
1180
+ zod: ">=3.23.0"
1181
+ },
1182
+ peerDependenciesMeta: {
1183
+ "@anthropic-ai/sdk": {
1184
+ optional: true
1185
+ },
1186
+ "@google/generative-ai": {
1187
+ optional: true
1188
+ },
1189
+ ai: {
1190
+ optional: true
1191
+ },
1192
+ zod: {
1193
+ optional: true
1194
+ }
1195
+ },
1196
+ publishConfig: {
1197
+ access: "public"
1198
+ }
1199
+ };
1200
+
1201
+ // version.ts
1202
+ var SDK_VERSION = package_default.version;
1203
+
1204
+ // tools/warp_grep/agent/runner.ts
1205
+ var import_path2 = __toESM(require("path"), 1);
1206
+ var parser = new LLMResponseParser();
1207
+ var DEFAULT_API_URL = "https://api.morphllm.com";
1208
+ async function callModel(messages, model, options = {}) {
1209
+ const baseUrl = options.morphApiUrl || DEFAULT_API_URL;
1210
+ const apiKey = options.morphApiKey || process.env.MORPH_API_KEY || "";
1211
+ const timeoutMs = options.timeout ?? AGENT_CONFIG.TIMEOUT_MS;
1212
+ const parsedUrl = new URL(baseUrl);
1213
+ const baseURL = parsedUrl.pathname === "/" ? `${baseUrl}/v1` : baseUrl;
1214
+ const client = new import_openai.default({
1215
+ apiKey,
1216
+ baseURL,
1217
+ maxRetries: options.retryConfig?.maxRetries,
1218
+ timeout: timeoutMs,
1219
+ defaultHeaders: { "X-Morph-SDK-Version": SDK_VERSION }
1220
+ });
1221
+ const MAX_EMPTY_RETRIES = 1;
1222
+ for (let attempt = 0; attempt <= MAX_EMPTY_RETRIES; attempt++) {
1223
+ let data;
1224
+ try {
1225
+ data = await client.chat.completions.create({
1226
+ model,
1227
+ temperature: 0,
1228
+ max_tokens: 1024,
1229
+ messages
1230
+ });
1231
+ } catch (error) {
1232
+ if (error instanceof import_openai.default.APIError && error.status === 404) {
1233
+ 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";
1234
+ const errorText = error.message?.trim();
1235
+ throw new Error(errorText || defaultMsg);
1236
+ }
1237
+ throw error;
1238
+ }
1239
+ const choice = data?.choices?.[0];
1240
+ const content = choice?.message?.content;
1241
+ if (content && typeof content === "string") {
1242
+ return content;
1243
+ }
1244
+ if (attempt === MAX_EMPTY_RETRIES) {
1245
+ const finishReason = choice?.finish_reason ?? "unknown";
1246
+ const hasToolCalls = Array.isArray(choice?.message?.tool_calls) && choice.message.tool_calls.length > 0;
1247
+ const choicesLen = data?.choices?.length ?? 0;
1248
+ const contentType = content === null ? "null" : content === void 0 ? "undefined" : typeof content;
1249
+ throw new Error(
1250
+ `Invalid response from model: content=${contentType}, finish_reason=${finishReason}, has_tool_calls=${hasToolCalls}, choices_length=${choicesLen}`
1251
+ );
1252
+ }
1253
+ await new Promise((resolve) => setTimeout(resolve, 200));
1254
+ }
1255
+ throw new Error("Invalid response from model");
1256
+ }
1257
+ async function runWarpGrep(config) {
1258
+ const totalStart = Date.now();
1259
+ const timeoutMs = config.timeout ?? AGENT_CONFIG.TIMEOUT_MS;
1260
+ const timings = { turns: [], timeout_ms: timeoutMs };
1261
+ const repoRoot = import_path2.default.resolve(config.repoRoot || process.cwd());
1262
+ const model = config.model || DEFAULT_MODEL;
1263
+ const messages = [];
1264
+ const maxTurns = AGENT_CONFIG.MAX_TURNS;
1265
+ const initialStateStart = Date.now();
1266
+ const initialState = await buildInitialState(repoRoot, config.searchTerm, config.provider, { search_type: config.search_type });
1267
+ timings.initial_state_ms = Date.now() - initialStateStart;
1268
+ messages.push({ role: "user", content: initialState });
1269
+ const provider = config.provider;
1270
+ const errors = [];
1271
+ let finishMeta;
1272
+ let terminationReason = "terminated";
1273
+ for (let turn = 1; turn <= maxTurns; turn += 1) {
1274
+ const turnMetrics = { turn, morph_api_ms: 0, local_tools_ms: 0 };
1275
+ enforceContextLimit(messages);
1276
+ const modelCallStart = Date.now();
1277
+ const assistantContent = await callModel(messages, model, {
1278
+ morphApiKey: config.morphApiKey,
1279
+ morphApiUrl: config.morphApiUrl,
1280
+ retryConfig: config.retryConfig,
1281
+ timeout: timeoutMs
1282
+ }).catch((e) => {
1283
+ const errMsg = e instanceof Error ? e.message : String(e);
1284
+ console.error(`[warp_grep] Morph API call failed on turn ${turn}:`, errMsg);
1285
+ errors.push({ message: errMsg });
1286
+ return "";
1287
+ });
1288
+ turnMetrics.morph_api_ms = Date.now() - modelCallStart;
1289
+ if (!assistantContent) {
1290
+ console.error(`[warp_grep] Empty response from Morph API on turn ${turn}. Errors so far:`, errors);
1291
+ timings.turns.push(turnMetrics);
1292
+ break;
1293
+ }
1294
+ messages.push({ role: "assistant", content: assistantContent });
1295
+ const toolCalls = parser.parse(assistantContent);
1296
+ if (toolCalls.length === 0) {
1297
+ console.error(`[warp_grep] No tool calls parsed on turn ${turn}. Assistant content (first 500 chars):`, assistantContent.slice(0, 500));
1298
+ 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" });
1299
+ terminationReason = "terminated";
1300
+ timings.turns.push(turnMetrics);
1301
+ break;
1302
+ }
1303
+ const finishCalls = toolCalls.filter((c) => c.name === "finish");
1304
+ const grepCalls = toolCalls.filter((c) => c.name === "grep");
1305
+ const listDirCalls = toolCalls.filter((c) => c.name === "list_directory");
1306
+ const readCalls = toolCalls.filter((c) => c.name === "read");
1307
+ const skipCalls = toolCalls.filter((c) => c.name === "_skip");
1308
+ const formatted = [];
1309
+ for (const c of skipCalls) {
1310
+ const msg = c.arguments?.message || "Command skipped due to parsing error";
1311
+ formatted.push(msg);
1312
+ }
1313
+ const allPromises = [];
1314
+ for (const c of grepCalls) {
1315
+ const args = c.arguments ?? {};
1316
+ allPromises.push(
1317
+ toolGrep(provider, args).then(
1318
+ ({ output }) => formatAgentToolOutput("grep", args, output),
1319
+ (err) => formatAgentToolOutput("grep", args, String(err), { isError: true })
1320
+ )
1321
+ );
1322
+ }
1323
+ for (const c of listDirCalls) {
1324
+ const args = c.arguments ?? {};
1325
+ allPromises.push(
1326
+ toolListDirectory(provider, args).then(
1327
+ (p) => formatAgentToolOutput("list_directory", args, p),
1328
+ (err) => formatAgentToolOutput("list_directory", args, String(err), { isError: true })
1329
+ )
1330
+ );
1331
+ }
1332
+ for (const c of readCalls) {
1333
+ const args = c.arguments ?? {};
1334
+ allPromises.push(
1335
+ toolRead(provider, args).then(
1336
+ (p) => formatAgentToolOutput("read", args, p),
1337
+ (err) => formatAgentToolOutput("read", args, String(err), { isError: true })
1338
+ )
1339
+ );
1340
+ }
1341
+ const toolExecStart = Date.now();
1342
+ const allResults = await Promise.all(allPromises);
1343
+ turnMetrics.local_tools_ms = Date.now() - toolExecStart;
1344
+ for (const result of allResults) {
1345
+ formatted.push(result);
1346
+ }
1347
+ if (formatted.length > 0) {
1348
+ const turnMessage = formatTurnMessage(turn, maxTurns);
1349
+ const contextBudget = calculateContextBudget(messages);
1350
+ messages.push({ role: "user", content: formatted.join("\n") + turnMessage + "\n" + contextBudget });
1351
+ }
1352
+ timings.turns.push(turnMetrics);
1353
+ if (finishCalls.length) {
1354
+ const fc = finishCalls[0];
1355
+ const files = fc.arguments?.files ?? [];
1356
+ const textResult = fc.arguments?.textResult;
1357
+ finishMeta = { files };
1358
+ terminationReason = "completed";
1359
+ if (files.length === 0) {
1360
+ const payload2 = textResult || "No relevant code found.";
1361
+ timings.turns.push(turnMetrics);
1362
+ timings.total_ms = Date.now() - totalStart;
1363
+ return {
1364
+ terminationReason: "completed",
1365
+ messages,
1366
+ finish: { payload: payload2, metadata: finishMeta },
1367
+ timings
1368
+ };
1369
+ }
1370
+ break;
1371
+ }
1372
+ }
1373
+ if (terminationReason !== "completed" || !finishMeta) {
1374
+ timings.total_ms = Date.now() - totalStart;
1375
+ return { terminationReason, messages, errors, timings };
1376
+ }
1377
+ const parts = ["Relevant context found:"];
1378
+ for (const f of finishMeta.files) {
1379
+ const ranges = f.lines === "*" ? "*" : Array.isArray(f.lines) ? f.lines.map(([s, e]) => `${s}-${e}`).join(", ") : "*";
1380
+ parts.push(`- ${f.path}: ${ranges}`);
1381
+ }
1382
+ const payload = parts.join("\n");
1383
+ const finishResolutionStart = Date.now();
1384
+ const fileReadErrors = [];
1385
+ const resolved = await readFinishFiles(
1386
+ repoRoot,
1387
+ finishMeta.files,
1388
+ async (p, s, e) => {
1389
+ try {
1390
+ const rr = await provider.read({ path: p, start: s, end: e });
1391
+ return rr.lines.map((l) => {
1392
+ const idx = l.indexOf("|");
1393
+ return idx >= 0 ? l.slice(idx + 1) : l;
1394
+ });
1395
+ } catch (err) {
1396
+ const errorMsg = err instanceof Error ? err.message : String(err);
1397
+ fileReadErrors.push({ path: p, error: errorMsg });
1398
+ console.error(`[warp_grep] Failed to read file: ${p} - ${errorMsg}`);
1399
+ return [`[couldn't find: ${p}]`];
1400
+ }
1401
+ }
1402
+ );
1403
+ timings.finish_resolution_ms = Date.now() - finishResolutionStart;
1404
+ if (fileReadErrors.length > 0) {
1405
+ errors.push(...fileReadErrors.map((e) => ({ message: `File read error: ${e.path} - ${e.error}` })));
1406
+ }
1407
+ timings.total_ms = Date.now() - totalStart;
1408
+ return {
1409
+ terminationReason: "completed",
1410
+ messages,
1411
+ finish: { payload, metadata: finishMeta, resolved },
1412
+ timings
1413
+ };
1414
+ }
1415
+ async function* runWarpGrepStreaming(config) {
1416
+ const totalStart = Date.now();
1417
+ const timeoutMs = config.timeout ?? AGENT_CONFIG.TIMEOUT_MS;
1418
+ const timings = { turns: [], timeout_ms: timeoutMs };
1419
+ const repoRoot = import_path2.default.resolve(config.repoRoot || process.cwd());
1420
+ const model = config.model || DEFAULT_MODEL;
1421
+ const messages = [];
1422
+ const maxTurns = AGENT_CONFIG.MAX_TURNS;
1423
+ const initialStateStart = Date.now();
1424
+ const initialState = await buildInitialState(repoRoot, config.searchTerm, config.provider, { search_type: config.search_type });
1425
+ timings.initial_state_ms = Date.now() - initialStateStart;
1426
+ messages.push({ role: "user", content: initialState });
1427
+ const provider = config.provider;
1428
+ const errors = [];
1429
+ let finishMeta;
1430
+ let terminationReason = "terminated";
1431
+ for (let turn = 1; turn <= maxTurns; turn += 1) {
1432
+ const turnMetrics = { turn, morph_api_ms: 0, local_tools_ms: 0 };
1433
+ enforceContextLimit(messages);
1434
+ const modelCallStart = Date.now();
1435
+ const assistantContent = await callModel(messages, model, {
1436
+ morphApiKey: config.morphApiKey,
1437
+ morphApiUrl: config.morphApiUrl,
1438
+ retryConfig: config.retryConfig,
1439
+ timeout: timeoutMs
1440
+ }).catch((e) => {
1441
+ const errMsg = e instanceof Error ? e.message : String(e);
1442
+ console.error(`[warp_grep:stream] Morph API call failed on turn ${turn}:`, errMsg);
1443
+ errors.push({ message: errMsg });
1444
+ return "";
1445
+ });
1446
+ turnMetrics.morph_api_ms = Date.now() - modelCallStart;
1447
+ if (!assistantContent) {
1448
+ console.error(`[warp_grep:stream] Empty response from Morph API on turn ${turn}. Errors so far:`, errors);
1449
+ timings.turns.push(turnMetrics);
1450
+ break;
1451
+ }
1452
+ messages.push({ role: "assistant", content: assistantContent });
1453
+ const toolCalls = parser.parse(assistantContent);
1454
+ if (toolCalls.length === 0) {
1455
+ console.error(`[warp_grep:stream] No tool calls parsed on turn ${turn}. Assistant content (first 500 chars):`, assistantContent.slice(0, 500));
1456
+ 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" });
1457
+ terminationReason = "terminated";
1458
+ timings.turns.push(turnMetrics);
1459
+ break;
1460
+ }
1461
+ yield {
1462
+ turn,
1463
+ toolCalls: toolCalls.map((c) => ({
1464
+ name: c.name,
1465
+ arguments: c.arguments ?? {}
1466
+ }))
1467
+ };
1468
+ const finishCalls = toolCalls.filter((c) => c.name === "finish");
1469
+ const grepCalls = toolCalls.filter((c) => c.name === "grep");
1470
+ const listDirCalls = toolCalls.filter((c) => c.name === "list_directory");
1471
+ const readCalls = toolCalls.filter((c) => c.name === "read");
1472
+ const skipCalls = toolCalls.filter((c) => c.name === "_skip");
1473
+ const formatted = [];
1474
+ for (const c of skipCalls) {
1475
+ const msg = c.arguments?.message || "Command skipped due to parsing error";
1476
+ formatted.push(msg);
1477
+ }
1478
+ const allPromises = [];
1479
+ for (const c of grepCalls) {
1480
+ const args = c.arguments ?? {};
1481
+ allPromises.push(
1482
+ toolGrep(provider, args).then(
1483
+ ({ output }) => formatAgentToolOutput("grep", args, output),
1484
+ (err) => formatAgentToolOutput("grep", args, String(err), { isError: true })
1485
+ )
1486
+ );
1487
+ }
1488
+ for (const c of listDirCalls) {
1489
+ const args = c.arguments ?? {};
1490
+ allPromises.push(
1491
+ toolListDirectory(provider, args).then(
1492
+ (p) => formatAgentToolOutput("list_directory", args, p),
1493
+ (err) => formatAgentToolOutput("list_directory", args, String(err), { isError: true })
1494
+ )
1495
+ );
1496
+ }
1497
+ for (const c of readCalls) {
1498
+ const args = c.arguments ?? {};
1499
+ allPromises.push(
1500
+ toolRead(provider, args).then(
1501
+ (p) => formatAgentToolOutput("read", args, p),
1502
+ (err) => formatAgentToolOutput("read", args, String(err), { isError: true })
1503
+ )
1504
+ );
1505
+ }
1506
+ const toolExecStart = Date.now();
1507
+ const allResults = await Promise.all(allPromises);
1508
+ turnMetrics.local_tools_ms = Date.now() - toolExecStart;
1509
+ for (const result of allResults) {
1510
+ formatted.push(result);
1511
+ }
1512
+ if (formatted.length > 0) {
1513
+ const turnMessage = formatTurnMessage(turn, maxTurns);
1514
+ const contextBudget = calculateContextBudget(messages);
1515
+ messages.push({ role: "user", content: formatted.join("\n") + turnMessage + "\n" + contextBudget });
1516
+ }
1517
+ timings.turns.push(turnMetrics);
1518
+ if (finishCalls.length) {
1519
+ const fc = finishCalls[0];
1520
+ const files = fc.arguments?.files ?? [];
1521
+ const textResult = fc.arguments?.textResult;
1522
+ finishMeta = { files };
1523
+ terminationReason = "completed";
1524
+ if (files.length === 0) {
1525
+ const payload2 = textResult || "No relevant code found.";
1526
+ timings.total_ms = Date.now() - totalStart;
1527
+ return {
1528
+ terminationReason: "completed",
1529
+ messages,
1530
+ finish: { payload: payload2, metadata: finishMeta },
1531
+ timings
1532
+ };
1533
+ }
1534
+ break;
1535
+ }
1536
+ }
1537
+ if (terminationReason !== "completed" || !finishMeta) {
1538
+ timings.total_ms = Date.now() - totalStart;
1539
+ return { terminationReason, messages, errors, timings };
1540
+ }
1541
+ const parts = ["Relevant context found:"];
1542
+ for (const f of finishMeta.files) {
1543
+ const ranges = f.lines === "*" ? "*" : Array.isArray(f.lines) ? f.lines.map(([s, e]) => `${s}-${e}`).join(", ") : "*";
1544
+ parts.push(`- ${f.path}: ${ranges}`);
1545
+ }
1546
+ const payload = parts.join("\n");
1547
+ const finishResolutionStart = Date.now();
1548
+ const fileReadErrors = [];
1549
+ const resolved = await readFinishFiles(
1550
+ repoRoot,
1551
+ finishMeta.files,
1552
+ async (p, s, e) => {
1553
+ try {
1554
+ const rr = await provider.read({ path: p, start: s, end: e });
1555
+ return rr.lines.map((l) => {
1556
+ const idx = l.indexOf("|");
1557
+ return idx >= 0 ? l.slice(idx + 1) : l;
1558
+ });
1559
+ } catch (err) {
1560
+ const errorMsg = err instanceof Error ? err.message : String(err);
1561
+ fileReadErrors.push({ path: p, error: errorMsg });
1562
+ console.error(`[warp_grep] Failed to read file: ${p} - ${errorMsg}`);
1563
+ return [`[couldn't find: ${p}]`];
1564
+ }
1565
+ }
1566
+ );
1567
+ timings.finish_resolution_ms = Date.now() - finishResolutionStart;
1568
+ if (fileReadErrors.length > 0) {
1569
+ errors.push(...fileReadErrors.map((e) => ({ message: `File read error: ${e.path} - ${e.error}` })));
1570
+ }
1571
+ timings.total_ms = Date.now() - totalStart;
1572
+ return {
1573
+ terminationReason: "completed",
1574
+ messages,
1575
+ finish: { payload, metadata: finishMeta, resolved },
1576
+ timings
1577
+ };
1578
+ }
1579
+
1580
+ // tools/warp_grep/providers/remote.ts
1581
+ init_config();
1582
+ var SKIP_NAMES = /* @__PURE__ */ new Set([
1583
+ // Version control
1584
+ ".git",
1585
+ ".svn",
1586
+ ".hg",
1587
+ ".bzr",
1588
+ // Dependencies
1589
+ "node_modules",
1590
+ "bower_components",
1591
+ ".pnpm",
1592
+ ".yarn",
1593
+ "vendor",
1594
+ "Pods",
1595
+ ".bundle",
1596
+ // Python
1597
+ "__pycache__",
1598
+ ".pytest_cache",
1599
+ ".mypy_cache",
1600
+ ".ruff_cache",
1601
+ ".venv",
1602
+ "venv",
1603
+ ".tox",
1604
+ ".nox",
1605
+ ".eggs",
1606
+ // Build outputs
1607
+ "dist",
1608
+ "build",
1609
+ "out",
1610
+ "output",
1611
+ "target",
1612
+ "_build",
1613
+ ".next",
1614
+ ".nuxt",
1615
+ ".output",
1616
+ ".vercel",
1617
+ ".netlify",
1618
+ // Cache
1619
+ ".cache",
1620
+ ".parcel-cache",
1621
+ ".turbo",
1622
+ ".nx",
1623
+ ".gradle",
1624
+ // IDE
1625
+ ".idea",
1626
+ ".vscode",
1627
+ ".vs",
1628
+ // Coverage
1629
+ "coverage",
1630
+ ".coverage",
1631
+ "htmlcov",
1632
+ ".nyc_output",
1633
+ // Temp
1634
+ "tmp",
1635
+ "temp",
1636
+ ".tmp",
1637
+ ".temp",
1638
+ // Lock files
1639
+ "package-lock.json",
1640
+ "yarn.lock",
1641
+ "pnpm-lock.yaml",
1642
+ "bun.lockb",
1643
+ "Cargo.lock",
1644
+ "Gemfile.lock",
1645
+ "poetry.lock"
1646
+ ]);
1647
+ var SKIP_EXTENSIONS = /* @__PURE__ */ new Set([
1648
+ ".min.js",
1649
+ ".min.css",
1650
+ ".bundle.js",
1651
+ ".wasm",
1652
+ ".so",
1653
+ ".dll",
1654
+ ".pyc",
1655
+ ".map",
1656
+ ".js.map"
1657
+ ]);
1658
+ function shouldSkip(name) {
1659
+ if (SKIP_NAMES.has(name)) return true;
1660
+ if (name.startsWith(".")) return true;
1661
+ for (const ext of SKIP_EXTENSIONS) {
1662
+ if (name.endsWith(ext)) return true;
1663
+ }
1664
+ return false;
1665
+ }
1666
+ var RemoteCommandsProvider = class {
1667
+ constructor(repoRoot, commands) {
1668
+ this.repoRoot = repoRoot;
1669
+ this.commands = commands;
1670
+ }
1671
+ /**
1672
+ * Run grep command and parse ripgrep output
1673
+ */
1674
+ async grep(params) {
1675
+ try {
1676
+ const stdout = await this.commands.grep(params.pattern, params.path, params.glob);
1677
+ const lines = (stdout || "").trim().split(/\r?\n/).filter((l) => l.length > 0);
1678
+ if (lines.length > AGENT_CONFIG.MAX_OUTPUT_LINES) {
1679
+ const truncated = lines.slice(0, AGENT_CONFIG.MAX_OUTPUT_LINES);
1680
+ truncated.push(`... (output truncated at ${AGENT_CONFIG.MAX_OUTPUT_LINES} of ${lines.length} lines)`);
1681
+ return { lines: truncated };
1682
+ }
1683
+ return { lines };
1684
+ } catch (error) {
1685
+ return {
1686
+ lines: [],
1687
+ error: `[GREP ERROR] ${error instanceof Error ? error.message : String(error)}`
1688
+ };
1689
+ }
1690
+ }
1691
+ /**
1692
+ * Read file and add line numbers
1693
+ */
1694
+ async read(params) {
1695
+ const rawStart = params.start;
1696
+ const rawEnd = params.end;
1697
+ const startValid = rawStart === void 0 || Number.isFinite(rawStart) && rawStart > 0;
1698
+ const endValid = rawEnd === void 0 || Number.isFinite(rawEnd) && rawEnd > 0;
1699
+ const rangeValid = startValid && endValid && (rawStart === void 0 || rawEnd === void 0 || rawStart <= rawEnd);
1700
+ const start = rangeValid && rawStart !== void 0 ? rawStart : 1;
1701
+ const end = rangeValid && rawEnd !== void 0 ? rawEnd : 1e6;
1702
+ try {
1703
+ const stdout = await this.commands.read(params.path, start, end);
1704
+ const contentLines = (stdout || "").split("\n");
1705
+ if (contentLines.length > 0 && contentLines[contentLines.length - 1] === "") {
1706
+ contentLines.pop();
1707
+ }
1708
+ const lines = contentLines.map((content, idx) => `${start + idx}|${content}`);
1709
+ if (lines.length > AGENT_CONFIG.MAX_READ_LINES) {
1710
+ const truncated = lines.slice(0, AGENT_CONFIG.MAX_READ_LINES);
1711
+ truncated.push(`... (output truncated at ${AGENT_CONFIG.MAX_READ_LINES} of ${lines.length} lines)`);
1712
+ return { lines: truncated };
1713
+ }
1714
+ return { lines };
1715
+ } catch (error) {
1716
+ return {
1717
+ lines: [],
1718
+ error: `[READ ERROR] ${error instanceof Error ? error.message : String(error)}`
1719
+ };
1720
+ }
1721
+ }
1722
+ /**
1723
+ * List directory and parse find output
1724
+ */
1725
+ async listDirectory(params) {
1726
+ const maxDepth = params.maxDepth ?? AGENT_CONFIG.MAX_LIST_DEPTH;
1727
+ const maxResults = params.maxResults ?? AGENT_CONFIG.MAX_OUTPUT_LINES;
1728
+ try {
1729
+ const stdout = await this.commands.listDir(params.path, maxDepth);
1730
+ const paths = (stdout || "").trim().split(/\r?\n/).filter((p) => p.length > 0);
1731
+ const regex = params.pattern ? new RegExp(params.pattern) : null;
1732
+ const entries = [];
1733
+ for (const fullPath of paths) {
1734
+ if (fullPath === params.path || fullPath === this.repoRoot) continue;
1735
+ const name = fullPath.split("/").pop() || "";
1736
+ if (shouldSkip(name)) continue;
1737
+ if (regex && !regex.test(name)) continue;
1738
+ let relativePath = fullPath;
1739
+ if (fullPath.startsWith(this.repoRoot)) {
1740
+ relativePath = fullPath.slice(this.repoRoot.length).replace(/^\//, "");
1741
+ }
1742
+ const depth = relativePath.split("/").filter(Boolean).length - 1;
1743
+ const hasExtension = name.includes(".") && !name.startsWith(".");
1744
+ const type = hasExtension ? "file" : "dir";
1745
+ entries.push({
1746
+ name,
1747
+ path: relativePath,
1748
+ type,
1749
+ depth: Math.max(0, depth)
1750
+ });
1751
+ if (entries.length >= maxResults) break;
1752
+ }
1753
+ return entries;
1754
+ } catch (error) {
1755
+ return [];
1756
+ }
1757
+ }
1758
+ };
1759
+
1760
+ // tools/warp_grep/providers/code_storage_http.ts
1761
+ async function post(url, body, op) {
1762
+ const res = await fetch(url, {
1763
+ method: "POST",
1764
+ headers: { "Content-Type": "application/json" },
1765
+ body: JSON.stringify(body)
1766
+ });
1767
+ if (!res.ok) {
1768
+ const text = await res.text().catch(() => res.statusText);
1769
+ try {
1770
+ const parsed = JSON.parse(text);
1771
+ if (parsed.error) return `Error: ${parsed.error}`;
1772
+ } catch {
1773
+ }
1774
+ return `Error: ${op} failed (${res.status}): ${text}`;
1775
+ }
1776
+ const data = await res.json();
1777
+ if (data.error) throw new Error(data.error);
1778
+ return data.stdout;
1779
+ }
1780
+ function createCodeStorageHttpCommands(config) {
1781
+ const { baseUrl, repoId, branch } = config;
1782
+ const encodedRepoId = encodeURIComponent(repoId);
1783
+ return {
1784
+ grep: (pattern, path5, glob) => post(`${baseUrl}/api/code-search/${encodedRepoId}/grep`, { pattern, path: path5, glob, branch }, "grep"),
1785
+ read: (path5, start, end) => post(`${baseUrl}/api/code-search/${encodedRepoId}/read`, { path: path5, start, end, branch }, "read"),
1786
+ listDir: (path5, maxDepth) => post(`${baseUrl}/api/code-search/${encodedRepoId}/list`, { path: path5, maxDepth, branch }, "list")
1787
+ };
1788
+ }
1789
+
1790
+ // tools/warp_grep/utils/github.ts
1791
+ function parseGitHubUrl(input) {
1792
+ input = input.trim();
1793
+ const urlPattern = /^(?:https?:\/\/)?github\.com\/([^\/]+)\/([^\/\?\#]+)/;
1794
+ const match = input.match(urlPattern);
1795
+ if (match) {
1796
+ return { owner: match[1], repo: match[2].replace(/\.git$/, "") };
1797
+ }
1798
+ const shortPattern = /^([^\/]+)\/([^\/]+)$/;
1799
+ const shortMatch = input.match(shortPattern);
1800
+ if (shortMatch && !shortMatch[1].includes(".")) {
1801
+ return { owner: shortMatch[1], repo: shortMatch[2].replace(/\.git$/, "") };
1802
+ }
1803
+ throw new Error(
1804
+ `Invalid GitHub URL or shorthand: "${input}". Expected "owner/repo" or "https://github.com/owner/repo"`
1805
+ );
1806
+ }
1807
+
1808
+ // tools/warp_grep/client.ts
1809
+ var DEFAULT_CODE_SEARCH_URL = "https://morphllm.com";
1810
+ async function getLocalProvider(repoRoot, excludes) {
1811
+ const { LocalRipgrepProvider: LocalRipgrepProvider2 } = await Promise.resolve().then(() => (init_local(), local_exports));
1812
+ return new LocalRipgrepProvider2(repoRoot, excludes);
1813
+ }
1814
+ var WarpGrepClient = class {
1815
+ config;
1816
+ constructor(config = {}) {
1817
+ this.config = { ...config };
1818
+ }
1819
+ execute(input) {
1820
+ const toolConfig = {
1821
+ repoRoot: input.repoRoot,
1822
+ remoteCommands: input.remoteCommands,
1823
+ provider: input.provider,
1824
+ excludes: input.excludes,
1825
+ includes: input.includes,
1826
+ debug: input.debug ?? this.config.debug,
1827
+ morphApiKey: this.config.morphApiKey,
1828
+ morphApiUrl: this.config.morphApiUrl,
1829
+ retryConfig: this.config.retryConfig,
1830
+ timeout: this.config.timeout
1831
+ };
1832
+ if (input.streamSteps) {
1833
+ return executeToolCallStreaming({ search_term: input.searchTerm }, toolConfig);
1834
+ }
1835
+ return executeToolCall({ search_term: input.searchTerm }, toolConfig);
1836
+ }
1837
+ searchGitHub(input) {
1838
+ if (input.streamSteps) {
1839
+ return this._searchGitHubStreaming(input);
1840
+ }
1841
+ return this._searchGitHubAsync(input);
1842
+ }
1843
+ /**
1844
+ * Read a single file from a public GitHub repository
1845
+ *
1846
+ * @example
1847
+ * ```typescript
1848
+ * const result = await client.readGitHubFile({
1849
+ * github: 'vercel/next.js',
1850
+ * path: 'src/server/app-render/index.tsx',
1851
+ * startLine: 1,
1852
+ * endLine: 50,
1853
+ * });
1854
+ * if (result.success) console.log(result.content);
1855
+ * ```
1856
+ */
1857
+ async readGitHubFile(input) {
1858
+ return executeGitHubReadFile(input, { timeout: this.config.timeout });
1859
+ }
1860
+ async _resolveGitHubRepo(input) {
1861
+ const { owner, repo } = parseGitHubUrl(input.github);
1862
+ const baseUrl = this.config.codeSearchUrl || DEFAULT_CODE_SEARCH_URL;
1863
+ const importRes = await fetch(`${baseUrl}/api/code-search/get-or-create?url=${encodeURIComponent(`${owner}/${repo}`)}`);
1864
+ if (!importRes.ok) {
1865
+ const text = await importRes.text().catch(() => importRes.statusText);
1866
+ throw new Error(`Failed to import repo ${owner}/${repo}: ${text}`);
1867
+ }
1868
+ const { repoId, defaultBranch } = await importRes.json();
1869
+ return {
1870
+ repo,
1871
+ remoteCommands: createCodeStorageHttpCommands({ baseUrl, repoId, branch: input.branch || defaultBranch })
1872
+ };
1873
+ }
1874
+ async _searchGitHubAsync(input) {
1875
+ try {
1876
+ const { repo, remoteCommands } = await this._resolveGitHubRepo(input);
1877
+ return this.execute({
1878
+ searchTerm: input.searchTerm,
1879
+ repoRoot: repo,
1880
+ remoteCommands
1881
+ });
1882
+ } catch (error) {
1883
+ return { success: false, error: error instanceof Error ? error.message : String(error) };
1884
+ }
1885
+ }
1886
+ async *_searchGitHubStreaming(input) {
1887
+ let repo;
1888
+ let remoteCommands;
1889
+ try {
1890
+ ({ repo, remoteCommands } = await this._resolveGitHubRepo(input));
1891
+ } catch (error) {
1892
+ return { success: false, error: error instanceof Error ? error.message : String(error) };
1893
+ }
1894
+ const generator = this.execute({
1895
+ searchTerm: input.searchTerm,
1896
+ repoRoot: repo,
1897
+ remoteCommands,
1898
+ streamSteps: true
1899
+ });
1900
+ let result;
1901
+ for (; ; ) {
1902
+ const { value, done } = await generator.next();
1903
+ if (done) {
1904
+ result = value;
1905
+ break;
1906
+ }
1907
+ yield value;
1908
+ }
1909
+ return result;
1910
+ }
1911
+ };
1912
+ async function executeToolCall(input, config) {
1913
+ const parsed = typeof input === "string" ? JSON.parse(input) : input;
1914
+ const provider = config.remoteCommands ? new RemoteCommandsProvider(config.repoRoot, config.remoteCommands) : config.provider ?? await getLocalProvider(config.repoRoot, config.excludes);
1915
+ const result = await runWarpGrep({
1916
+ searchTerm: parsed.search_term,
1917
+ repoRoot: config.repoRoot,
1918
+ provider,
1919
+ excludes: config.excludes,
1920
+ includes: config.includes,
1921
+ debug: config.debug ?? false,
1922
+ morphApiKey: config.morphApiKey,
1923
+ morphApiUrl: config.morphApiUrl,
1924
+ retryConfig: config.retryConfig,
1925
+ timeout: config.timeout
1926
+ });
1927
+ const finish = result.finish;
1928
+ if (result.terminationReason !== "completed" || !finish?.metadata) {
1929
+ const errorDetails = result.errors?.map((e) => e.message).join("; ") || "unknown reason";
1930
+ console.error(`[warp_grep] executeToolCall failed. Reason: ${result.terminationReason}. Errors: ${errorDetails}. Turns: ${result.timings?.turns?.length ?? 0}`);
1931
+ return { success: false, error: `Search did not complete: ${errorDetails}` };
1932
+ }
1933
+ const contexts = (finish.resolved ?? []).map((r) => ({
1934
+ file: r.path,
1935
+ content: r.content,
1936
+ lines: r.ranges
1937
+ }));
1938
+ return { success: true, contexts, summary: finish.payload };
1939
+ }
1940
+ function processAgentResult(result) {
1941
+ const finish = result.finish;
1942
+ if (result.terminationReason !== "completed" || !finish?.metadata) {
1943
+ const errorDetails = result.errors?.map((e) => e.message).join("; ") || "unknown reason";
1944
+ console.error(`[warp_grep] processAgentResult failed. Reason: ${result.terminationReason}. Errors: ${errorDetails}. Turns: ${result.timings?.turns?.length ?? 0}`);
1945
+ return { success: false, error: `Search did not complete: ${errorDetails}` };
1946
+ }
1947
+ const contexts = (finish.resolved ?? []).map((r) => ({
1948
+ file: r.path,
1949
+ content: r.content,
1950
+ lines: r.ranges
1951
+ }));
1952
+ return { success: true, contexts, summary: finish.payload };
1953
+ }
1954
+ async function* executeToolCallStreaming(input, config) {
1955
+ const parsed = typeof input === "string" ? JSON.parse(input) : input;
1956
+ const provider = config.remoteCommands ? new RemoteCommandsProvider(config.repoRoot, config.remoteCommands) : config.provider ?? await getLocalProvider(config.repoRoot, config.excludes);
1957
+ const generator = runWarpGrepStreaming({
1958
+ searchTerm: parsed.search_term,
1959
+ repoRoot: config.repoRoot,
1960
+ provider,
1961
+ excludes: config.excludes,
1962
+ includes: config.includes,
1963
+ debug: config.debug ?? false,
1964
+ morphApiKey: config.morphApiKey,
1965
+ morphApiUrl: config.morphApiUrl,
1966
+ retryConfig: config.retryConfig,
1967
+ timeout: config.timeout
1968
+ });
1969
+ let agentResult;
1970
+ for (; ; ) {
1971
+ const { value, done } = await generator.next();
1972
+ if (done) {
1973
+ agentResult = value;
1974
+ break;
1975
+ }
1976
+ yield value;
1977
+ }
1978
+ return processAgentResult(agentResult);
1979
+ }
1980
+ async function fetchRawGitHubFile(owner, repo, filePath, branch, timeout) {
1981
+ const branches = branch ? [branch] : ["HEAD"];
1982
+ const fallbacks = ["main", "master", "develop"];
1983
+ const fetchWithTimeout = (url) => timeout ? fetch(url, { signal: AbortSignal.timeout(timeout) }) : fetch(url);
1984
+ for (const b of branches) {
1985
+ const url = `https://raw.githubusercontent.com/${owner}/${repo}/${b}/${filePath}`;
1986
+ const res = await fetchWithTimeout(url);
1987
+ if (res.ok) return { content: await res.text(), branch: b };
1988
+ }
1989
+ for (const fb of fallbacks) {
1990
+ if (branch && fb === branch) continue;
1991
+ const url = `https://raw.githubusercontent.com/${owner}/${repo}/${fb}/${filePath}`;
1992
+ const res = await fetchWithTimeout(url);
1993
+ if (res.ok) return { content: await res.text(), branch: fb };
1994
+ }
1995
+ throw new Error(`File not found: ${owner}/${repo}/${filePath}`);
1996
+ }
1997
+ async function executeGitHubReadFile(input, config) {
1998
+ try {
1999
+ const { owner, repo } = parseGitHubUrl(input.github);
2000
+ const { content: raw, branch } = await fetchRawGitHubFile(
2001
+ owner,
2002
+ repo,
2003
+ input.path,
2004
+ input.branch,
2005
+ config?.timeout
2006
+ );
2007
+ const allLines = raw.split("\n");
2008
+ const totalLines = allLines.length;
2009
+ const start = Math.max(1, input.startLine ?? 1);
2010
+ const end = Math.min(totalLines, input.endLine ?? totalLines);
2011
+ const selected = allLines.slice(start - 1, end);
2012
+ const padWidth = String(end).length;
2013
+ const numbered = selected.map((line, i) => `${String(start + i).padStart(padWidth)}|${line}`).join("\n");
2014
+ return {
2015
+ success: true,
2016
+ content: numbered,
2017
+ path: input.path,
2018
+ github: `${owner}/${repo}`,
2019
+ branch,
2020
+ lineRange: [start, end],
2021
+ totalLines
2022
+ };
2023
+ } catch (error) {
2024
+ return {
2025
+ success: false,
2026
+ error: error instanceof Error ? error.message : String(error)
2027
+ };
2028
+ }
2029
+ }
2030
+ function formatResult(result) {
2031
+ if (!result.success) {
2032
+ return `Search failed: ${result.error}`;
2033
+ }
2034
+ if (!result.contexts || result.contexts.length === 0) {
2035
+ return "No relevant code found. Try rephrasing your search term.";
2036
+ }
2037
+ const parts = [];
2038
+ parts.push(`Morph Fast Context subagent performed search on repository:
2039
+ `);
2040
+ parts.push("Relevant context found:");
2041
+ for (const ctx of result.contexts) {
2042
+ const rangeStr = !ctx.lines || ctx.lines === "*" ? "*" : ctx.lines.map(([s, e]) => `${s}-${e}`).join(",");
2043
+ parts.push(`- ${ctx.file}:${rangeStr}`);
2044
+ }
2045
+ parts.push("\nHere is the content of files:\n");
2046
+ for (const ctx of result.contexts) {
2047
+ const rangeStr = !ctx.lines || ctx.lines === "*" ? "" : ` lines="${ctx.lines.map(([s, e]) => `${s}-${e}`).join(",")}"`;
2048
+ parts.push(`<file path="${ctx.file}"${rangeStr}>`);
2049
+ parts.push(ctx.content);
2050
+ parts.push("</file>\n");
2051
+ }
2052
+ return parts.join("\n");
2053
+ }
2054
+
2055
+ // subagents/prompts.ts
2056
+ var THOROUGHNESS_INSTRUCTIONS = {
2057
+ quick: `Do 1-2 targeted searches. Find the most relevant file/function quickly and summarize. Don't go deep.`,
2058
+ medium: `Do 2-4 searches. Start broad, then follow up on the most promising leads. Cover the main aspects.`,
2059
+ 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.`
2060
+ };
2061
+ function getSystemPrompt(thoroughness = "medium") {
2062
+ return `You are a codebase exploration specialist. Your job is to search a codebase and return a concise, accurate summary of what you find.
2063
+
2064
+ ## Mode
2065
+ READ-ONLY. You cannot modify files. You can only search and read code.
2066
+
2067
+ ## Strategy
2068
+ ${THOROUGHNESS_INSTRUCTIONS[thoroughness]}
2069
+
2070
+ - Use multiple focused searches rather than one vague search
2071
+ - Follow imports, function calls, and type references to build complete understanding
2072
+ - If a search returns no results, try alternative terms (e.g., "auth" vs "authentication" vs "login")
2073
+ - Look at both implementation and tests when relevant
2074
+
2075
+ ## Communication
2076
+ You have a \`send_message\` tool. Use it when:
2077
+ - You hit a fork in the road and need guidance ("Found auth in both src/middleware/ and legacy/auth/. Which should I focus on?")
2078
+ - You need clarification on ambiguous requests ("There are 3 auth strategies: JWT, session, OAuth. Which one?")
2079
+ - 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.")
2080
+
2081
+ 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.
2082
+
2083
+ ## Output
2084
+ When you have enough information, output your final summary. Structure it as:
2085
+ 1. Direct answer to the question
2086
+ 2. Key files and their roles
2087
+ 3. How the pieces connect
2088
+
2089
+ Be concise. The summary should be useful to another AI model that will use your findings to complete a task.`;
2090
+ }
2091
+ var CODEBASE_SEARCH_TOOL = {
2092
+ name: "codebase_search",
2093
+ 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.",
2094
+ input_schema: {
2095
+ type: "object",
2096
+ properties: {
2097
+ searchRequest: {
2098
+ type: "string",
2099
+ description: "Natural language description of what to search for in the codebase"
2100
+ }
2101
+ },
2102
+ required: ["searchRequest"],
2103
+ additionalProperties: false
2104
+ }
2105
+ };
2106
+ var SEND_MESSAGE_TOOL = {
2107
+ name: "send_message",
2108
+ 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.",
2109
+ input_schema: {
2110
+ type: "object",
2111
+ properties: {
2112
+ message: {
2113
+ type: "string",
2114
+ description: "The message to send to the orchestrator"
2115
+ }
2116
+ },
2117
+ required: ["message"],
2118
+ additionalProperties: false
2119
+ }
2120
+ };
2121
+
2122
+ // subagents/vercel.ts
2123
+ var DEFAULT_MAX_TURNS = {
2124
+ quick: 3,
2125
+ medium: 6,
2126
+ thorough: 12
2127
+ };
2128
+ function getMaxTurns(config) {
2129
+ return config.maxTurns ?? DEFAULT_MAX_TURNS[config.thoroughness ?? "medium"] ?? 6;
2130
+ }
2131
+ function createExploreSubagent(config) {
2132
+ if (!config.repoRoot) {
2133
+ throw new Error("repoRoot is required for Explore subagent");
2134
+ }
2135
+ const warpGrep = new WarpGrepClient({
2136
+ morphApiKey: config.morphApiKey
2137
+ });
2138
+ const thoroughness = config.thoroughness ?? "medium";
2139
+ const replyTimeout = config.replyTimeout ?? 3e4;
2140
+ async function runExplore(prompt, callbacks = {}) {
2141
+ const startTime = Date.now();
2142
+ const allContexts = [];
2143
+ let searchCount = 0;
2144
+ const timeoutMs = config.timeout;
2145
+ const timeoutPromise = timeoutMs ? new Promise(
2146
+ (_, reject) => setTimeout(() => reject(new Error(`Exploration timed out after ${timeoutMs}ms`)), timeoutMs)
2147
+ ) : null;
2148
+ const runPromise = (async () => {
2149
+ try {
2150
+ const codebaseSearchSchema = import_zod.z.object({
2151
+ searchRequest: import_zod.z.string().describe("Natural language description of what to search for")
2152
+ });
2153
+ const sendMessageSchema = import_zod.z.object({
2154
+ message: import_zod.z.string().describe("The message to send to the orchestrator")
2155
+ });
2156
+ const result = await (0, import_ai.generateText)({
2157
+ model: config.model,
2158
+ system: getSystemPrompt(thoroughness),
2159
+ prompt,
2160
+ tools: {
2161
+ codebase_search: (0, import_ai.tool)({
2162
+ description: CODEBASE_SEARCH_TOOL.description,
2163
+ inputSchema: codebaseSearchSchema,
2164
+ execute: async (params) => {
2165
+ searchCount++;
2166
+ const warpResult = await warpGrep.execute({
2167
+ searchTerm: params.searchRequest,
2168
+ repoRoot: config.repoRoot,
2169
+ excludes: config.excludes,
2170
+ includes: config.includes
2171
+ });
2172
+ if (warpResult.contexts) {
2173
+ allContexts.push(...warpResult.contexts);
2174
+ }
2175
+ callbacks.onStep?.({
2176
+ step: searchCount,
2177
+ searchRequest: params.searchRequest,
2178
+ contextsFound: warpResult.contexts?.length ?? 0,
2179
+ isFinal: false
2180
+ });
2181
+ return formatResult(warpResult);
2182
+ }
2183
+ }),
2184
+ send_message: (0, import_ai.tool)({
2185
+ description: SEND_MESSAGE_TOOL.description,
2186
+ inputSchema: sendMessageSchema,
2187
+ execute: async (params) => {
2188
+ const subagentMsg = {
2189
+ from: "explore",
2190
+ content: params.message,
2191
+ timestamp: Date.now()
2192
+ };
2193
+ const replyPromise = new Promise((resolve) => {
2194
+ if (callbacks.onMessage) {
2195
+ callbacks.onMessage(subagentMsg, (replyText) => {
2196
+ resolve(replyText);
2197
+ });
2198
+ } else {
2199
+ setTimeout(() => resolve(""), replyTimeout);
2200
+ }
2201
+ });
2202
+ const reply = await Promise.race([
2203
+ replyPromise,
2204
+ new Promise(
2205
+ (resolve) => setTimeout(() => resolve(""), replyTimeout)
2206
+ )
2207
+ ]);
2208
+ if (reply) {
2209
+ return `Response from orchestrator: ${reply}`;
2210
+ }
2211
+ return "No response. Continue with your best judgment.";
2212
+ }
2213
+ })
2214
+ },
2215
+ stopWhen: (0, import_ai.stepCountIs)(getMaxTurns(config))
2216
+ });
2217
+ callbacks.onStep?.({
2218
+ step: searchCount,
2219
+ searchRequest: "",
2220
+ contextsFound: allContexts.length,
2221
+ isFinal: true
2222
+ });
2223
+ const uniqueContexts = deduplicateContexts(allContexts);
2224
+ return {
2225
+ success: true,
2226
+ summary: result.text || "Exploration completed but no summary was generated.",
2227
+ contexts: uniqueContexts,
2228
+ searchCount,
2229
+ durationMs: Date.now() - startTime
2230
+ };
2231
+ } catch (error) {
2232
+ return {
2233
+ success: false,
2234
+ summary: "",
2235
+ contexts: deduplicateContexts(allContexts),
2236
+ searchCount,
2237
+ durationMs: Date.now() - startTime,
2238
+ error: error instanceof Error ? error.message : String(error)
2239
+ };
2240
+ }
2241
+ })();
2242
+ if (timeoutPromise) {
2243
+ try {
2244
+ return await Promise.race([runPromise, timeoutPromise]);
2245
+ } catch (error) {
2246
+ return {
2247
+ success: false,
2248
+ summary: "",
2249
+ contexts: deduplicateContexts(allContexts),
2250
+ searchCount,
2251
+ durationMs: Date.now() - startTime,
2252
+ error: error instanceof Error ? error.message : String(error)
2253
+ };
2254
+ }
2255
+ }
2256
+ return runPromise;
2257
+ }
2258
+ const exploreToolSchema = import_zod.z.object({
2259
+ searchRequest: import_zod.z.string().describe("What to explore in the codebase. Be specific about what you want to understand.")
2260
+ });
2261
+ const exploreTool = (0, import_ai.tool)({
2262
+ description: "Explore a codebase to answer questions about code structure, find implementations, trace call chains, and understand architecture. Returns a summary of findings. Use this for broad exploration rather than pinpoint keyword searches.",
2263
+ inputSchema: exploreToolSchema,
2264
+ execute: async (params) => {
2265
+ const result = await runExplore(params.searchRequest);
2266
+ return {
2267
+ success: result.success,
2268
+ summary: result.summary,
2269
+ searchCount: result.searchCount,
2270
+ error: result.error
2271
+ };
2272
+ }
2273
+ });
2274
+ return {
2275
+ /** Vercel AI SDK tool for use as a tool in parent agents */
2276
+ tool: exploreTool,
2277
+ /** Run exploration with messaging support */
2278
+ run(prompt) {
2279
+ const messageHandlers = [];
2280
+ const stepHandlers = [];
2281
+ let resultPromise = null;
2282
+ const session = {
2283
+ on(event, handler) {
2284
+ if (event === "message") messageHandlers.push(handler);
2285
+ if (event === "step") stepHandlers.push(handler);
2286
+ return session;
2287
+ },
2288
+ send(_text) {
2289
+ },
2290
+ get result() {
2291
+ if (!resultPromise) {
2292
+ resultPromise = runExplore(prompt, {
2293
+ onStep: (step) => {
2294
+ for (const handler of stepHandlers) handler(step);
2295
+ },
2296
+ onMessage: (msg, reply) => {
2297
+ if (messageHandlers.length > 0) {
2298
+ for (const handler of messageHandlers) handler(msg, reply);
2299
+ } else {
2300
+ reply("");
2301
+ }
2302
+ }
2303
+ });
2304
+ }
2305
+ return resultPromise;
2306
+ }
2307
+ };
2308
+ return session;
2309
+ },
2310
+ /** Stream exploration events as an async generator */
2311
+ async *stream(prompt) {
2312
+ const events = [];
2313
+ let resolveNext = null;
2314
+ let done = false;
2315
+ const resultPromise = runExplore(prompt, {
2316
+ onStep: (step) => {
2317
+ events.push({
2318
+ type: "step",
2319
+ step: step.step,
2320
+ searchRequest: step.searchRequest,
2321
+ contextsFound: step.contextsFound,
2322
+ isFinal: step.isFinal
2323
+ });
2324
+ resolveNext?.();
2325
+ },
2326
+ onMessage: (msg, reply) => {
2327
+ events.push({
2328
+ type: "message",
2329
+ from: msg.from,
2330
+ content: msg.content,
2331
+ timestamp: msg.timestamp
2332
+ });
2333
+ resolveNext?.();
2334
+ reply("Continue with your best judgment.");
2335
+ }
2336
+ });
2337
+ while (!done) {
2338
+ if (events.length > 0) {
2339
+ yield events.shift();
2340
+ } else {
2341
+ const raceResult = await Promise.race([
2342
+ resultPromise.then((r) => ({ type: "done", result: r })),
2343
+ new Promise((resolve) => {
2344
+ resolveNext = () => resolve({ type: "event" });
2345
+ })
2346
+ ]);
2347
+ if (raceResult.type === "done") {
2348
+ while (events.length > 0) {
2349
+ yield events.shift();
2350
+ }
2351
+ done = true;
2352
+ return raceResult.result;
2353
+ }
2354
+ }
2355
+ }
2356
+ return await resultPromise;
2357
+ }
2358
+ };
2359
+ }
2360
+ function deduplicateContexts(contexts) {
2361
+ const map = /* @__PURE__ */ new Map();
2362
+ for (const ctx of contexts) {
2363
+ const existing = map.get(ctx.file);
2364
+ if (!existing || ctx.content.length > existing.content.length) {
2365
+ map.set(ctx.file, ctx);
2366
+ }
2367
+ }
2368
+ return Array.from(map.values());
2369
+ }
2370
+ // Annotate the CommonJS export names for ESM import in node:
2371
+ 0 && (module.exports = {
2372
+ createExploreSubagent
2373
+ });
2374
+ //# sourceMappingURL=vercel.cjs.map