@morphllm/morphsdk 0.2.55 → 0.2.57

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 (59) hide show
  1. package/dist/{chunk-37SRI4GW.js → chunk-6X5UOY7B.js} +34 -39
  2. package/dist/chunk-6X5UOY7B.js.map +1 -0
  3. package/dist/chunk-7OQOOB3R.js +1 -0
  4. package/dist/{chunk-X5HNQ7SB.js → chunk-CFF636UC.js} +3 -3
  5. package/dist/{chunk-KO6JQFRE.js → chunk-GJ5TYNRD.js} +2 -2
  6. package/dist/{chunk-ZWY434TS.js → chunk-IMYQOKFO.js} +3 -3
  7. package/dist/{chunk-BSHJGJ25.js → chunk-KBQWGT5L.js} +3 -3
  8. package/dist/{chunk-C6QQL6FX.js → chunk-QFIHUCTF.js} +5 -5
  9. package/dist/client.cjs +28 -142
  10. package/dist/client.cjs.map +1 -1
  11. package/dist/client.js +8 -9
  12. package/dist/index.cjs +28 -209
  13. package/dist/index.cjs.map +1 -1
  14. package/dist/index.d.ts +0 -1
  15. package/dist/index.js +9 -14
  16. package/dist/tools/warp_grep/agent/runner.cjs +28 -142
  17. package/dist/tools/warp_grep/agent/runner.cjs.map +1 -1
  18. package/dist/tools/warp_grep/agent/runner.js +3 -4
  19. package/dist/tools/warp_grep/anthropic.cjs +28 -142
  20. package/dist/tools/warp_grep/anthropic.cjs.map +1 -1
  21. package/dist/tools/warp_grep/anthropic.js +5 -6
  22. package/dist/tools/warp_grep/harness.cjs +859 -0
  23. package/dist/tools/warp_grep/harness.cjs.map +1 -0
  24. package/dist/tools/warp_grep/harness.d.ts +176 -0
  25. package/dist/tools/warp_grep/harness.js +76 -0
  26. package/dist/tools/warp_grep/harness.js.map +1 -0
  27. package/dist/tools/warp_grep/index.cjs +28 -209
  28. package/dist/tools/warp_grep/index.cjs.map +1 -1
  29. package/dist/tools/warp_grep/index.d.ts +0 -1
  30. package/dist/tools/warp_grep/index.js +8 -13
  31. package/dist/tools/warp_grep/openai.cjs +28 -142
  32. package/dist/tools/warp_grep/openai.cjs.map +1 -1
  33. package/dist/tools/warp_grep/openai.js +5 -6
  34. package/dist/tools/warp_grep/vercel.cjs +28 -142
  35. package/dist/tools/warp_grep/vercel.cjs.map +1 -1
  36. package/dist/tools/warp_grep/vercel.js +5 -6
  37. package/package.json +7 -2
  38. package/dist/chunk-37SRI4GW.js.map +0 -1
  39. package/dist/chunk-JYBVRF72.js +0 -1
  40. package/dist/chunk-NDZO5IPV.js +0 -121
  41. package/dist/chunk-NDZO5IPV.js.map +0 -1
  42. package/dist/chunk-P2XKFWFD.js +0 -73
  43. package/dist/chunk-P2XKFWFD.js.map +0 -1
  44. package/dist/tools/warp_grep/agent/grep_helpers.cjs +0 -148
  45. package/dist/tools/warp_grep/agent/grep_helpers.cjs.map +0 -1
  46. package/dist/tools/warp_grep/agent/grep_helpers.d.ts +0 -16
  47. package/dist/tools/warp_grep/agent/grep_helpers.js +0 -14
  48. package/dist/tools/warp_grep/agent/grep_helpers.js.map +0 -1
  49. package/dist/tools/warp_grep/providers/command.cjs +0 -177
  50. package/dist/tools/warp_grep/providers/command.cjs.map +0 -1
  51. package/dist/tools/warp_grep/providers/command.d.ts +0 -48
  52. package/dist/tools/warp_grep/providers/command.js +0 -9
  53. package/dist/tools/warp_grep/providers/command.js.map +0 -1
  54. /package/dist/{chunk-JYBVRF72.js.map → chunk-7OQOOB3R.js.map} +0 -0
  55. /package/dist/{chunk-X5HNQ7SB.js.map → chunk-CFF636UC.js.map} +0 -0
  56. /package/dist/{chunk-KO6JQFRE.js.map → chunk-GJ5TYNRD.js.map} +0 -0
  57. /package/dist/{chunk-ZWY434TS.js.map → chunk-IMYQOKFO.js.map} +0 -0
  58. /package/dist/{chunk-BSHJGJ25.js.map → chunk-KBQWGT5L.js.map} +0 -0
  59. /package/dist/{chunk-C6QQL6FX.js.map → chunk-QFIHUCTF.js.map} +0 -0
@@ -0,0 +1,859 @@
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 __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // tools/warp_grep/harness.ts
31
+ var harness_exports = {};
32
+ __export(harness_exports, {
33
+ DEFAULT_EXCLUDES: () => DEFAULT_EXCLUDES,
34
+ LocalRipgrepProvider: () => LocalRipgrepProvider,
35
+ MAX_TURNS: () => MAX_TURNS,
36
+ SYSTEM_PROMPT: () => SYSTEM_PROMPT,
37
+ TIMEOUT_MS: () => TIMEOUT_MS,
38
+ formatAnalyseTree: () => formatAnalyseTree,
39
+ formatToolResult: () => formatToolResult,
40
+ formatTurnMessage: () => formatTurnMessage,
41
+ parseToolCalls: () => parseToolCalls,
42
+ resolveFinishFiles: () => resolveFinishFiles
43
+ });
44
+ module.exports = __toCommonJS(harness_exports);
45
+
46
+ // tools/warp_grep/agent/parser.ts
47
+ var VALID_COMMANDS = ["analyse", "grep", "read", "finish"];
48
+ function preprocessText(text) {
49
+ let processed = text.replace(/<think>[\s\S]*?<\/think>/gi, "");
50
+ const openingTagRegex = /<tool_call>|<tool>/gi;
51
+ const closingTagRegex = /<\/tool_call>|<\/tool>/gi;
52
+ const openingMatches = processed.match(openingTagRegex) || [];
53
+ const closingMatches = processed.match(closingTagRegex) || [];
54
+ if (openingMatches.length > closingMatches.length) {
55
+ const lastClosingMatch = /<\/tool_call>|<\/tool>/gi;
56
+ let lastClosingIndex = -1;
57
+ let match;
58
+ while ((match = lastClosingMatch.exec(processed)) !== null) {
59
+ lastClosingIndex = match.index + match[0].length;
60
+ }
61
+ if (lastClosingIndex > 0) {
62
+ processed = processed.slice(0, lastClosingIndex);
63
+ }
64
+ }
65
+ const toolCallLines = [];
66
+ const toolTagRegex = /<tool_call>([\s\S]*?)<\/tool_call>|<tool>([\s\S]*?)<\/tool>/gi;
67
+ let tagMatch;
68
+ while ((tagMatch = toolTagRegex.exec(processed)) !== null) {
69
+ const content = (tagMatch[1] || tagMatch[2] || "").trim();
70
+ if (content) {
71
+ const lines = content.split(/\r?\n/).map((l) => l.trim()).filter((l) => l);
72
+ toolCallLines.push(...lines);
73
+ }
74
+ }
75
+ const allLines = processed.split(/\r?\n/).map((l) => l.trim());
76
+ for (const line of allLines) {
77
+ if (!line) continue;
78
+ if (line.startsWith("<")) continue;
79
+ const firstWord = line.split(/\s/)[0];
80
+ if (VALID_COMMANDS.includes(firstWord)) {
81
+ if (!toolCallLines.includes(line)) {
82
+ toolCallLines.push(line);
83
+ }
84
+ }
85
+ }
86
+ return toolCallLines;
87
+ }
88
+ var LLMResponseParser = class {
89
+ finishSpecSplitRe = /,(?=[^,\s]+:)/;
90
+ parse(text) {
91
+ if (typeof text !== "string") {
92
+ throw new TypeError("Command text must be a string.");
93
+ }
94
+ const lines = preprocessText(text);
95
+ const commands = [];
96
+ let finishAccumulator = null;
97
+ lines.forEach((line) => {
98
+ if (!line || line.startsWith("#")) return;
99
+ const parts = this.splitLine(line);
100
+ if (parts.length === 0) return;
101
+ const cmd = parts[0];
102
+ switch (cmd) {
103
+ case "analyse":
104
+ this.handleAnalyse(parts, line, commands);
105
+ break;
106
+ case "grep":
107
+ this.handleGrep(parts, line, commands);
108
+ break;
109
+ case "read":
110
+ this.handleRead(parts, line, commands);
111
+ break;
112
+ case "finish":
113
+ finishAccumulator = this.handleFinish(parts, line, commands, finishAccumulator);
114
+ break;
115
+ default:
116
+ break;
117
+ }
118
+ });
119
+ if (finishAccumulator) {
120
+ const map = finishAccumulator;
121
+ const entries = [...map.entries()];
122
+ const filesPayload = entries.map(([path3, ranges]) => ({
123
+ path: path3,
124
+ lines: [...ranges].sort((a, b) => a[0] - b[0])
125
+ }));
126
+ commands.push({ name: "finish", arguments: { files: filesPayload } });
127
+ }
128
+ return commands;
129
+ }
130
+ splitLine(line) {
131
+ const parts = [];
132
+ let current = "";
133
+ let inSingle = false;
134
+ for (let i = 0; i < line.length; i++) {
135
+ const ch = line[i];
136
+ if (ch === "'" && line[i - 1] !== "\\") {
137
+ inSingle = !inSingle;
138
+ current += ch;
139
+ } else if (!inSingle && /\s/.test(ch)) {
140
+ if (current) {
141
+ parts.push(current);
142
+ current = "";
143
+ }
144
+ } else {
145
+ current += ch;
146
+ }
147
+ }
148
+ if (current) parts.push(current);
149
+ return parts;
150
+ }
151
+ /** Helper to create a _skip tool call with an error message */
152
+ skip(message) {
153
+ return { name: "_skip", arguments: { message } };
154
+ }
155
+ handleAnalyse(parts, rawLine, commands) {
156
+ if (parts.length < 2) {
157
+ commands.push(this.skip(
158
+ `[SKIPPED] Your command "${rawLine}" is missing a path. Correct format: analyse <path> [pattern]. Example: analyse src/`
159
+ ));
160
+ return;
161
+ }
162
+ const path3 = parts[1];
163
+ const pattern = parts[2]?.replace(/^"|"$/g, "") ?? null;
164
+ commands.push({ name: "analyse", arguments: { path: path3, pattern } });
165
+ }
166
+ // no glob tool in MCP
167
+ handleGrep(parts, rawLine, commands) {
168
+ if (parts.length < 3) {
169
+ commands.push(this.skip(
170
+ `[SKIPPED] Your command "${rawLine}" is missing arguments. Correct format: grep '<pattern>' <path>. Example: grep 'TODO' src/`
171
+ ));
172
+ return;
173
+ }
174
+ let pat = parts[1];
175
+ if (pat.startsWith("'") && pat.endsWith("'")) {
176
+ pat = pat.slice(1, -1);
177
+ }
178
+ if (!pat) {
179
+ commands.push(this.skip(
180
+ `[SKIPPED] Your command "${rawLine}" has an empty pattern. Provide a non-empty search pattern. Example: grep 'function' src/`
181
+ ));
182
+ return;
183
+ }
184
+ commands.push({ name: "grep", arguments: { pattern: pat, path: parts[2] } });
185
+ }
186
+ handleRead(parts, rawLine, commands) {
187
+ if (parts.length < 2) {
188
+ commands.push(this.skip(
189
+ `[SKIPPED] Your command "${rawLine}" is missing a path. Correct format: read <path> or read <path>:<start>-<end>. Example: read src/index.ts:1-50`
190
+ ));
191
+ return;
192
+ }
193
+ const spec = parts[1];
194
+ const rangeIdx = spec.indexOf(":");
195
+ if (rangeIdx === -1) {
196
+ commands.push({ name: "read", arguments: { path: spec } });
197
+ return;
198
+ }
199
+ const filePath = spec.slice(0, rangeIdx);
200
+ const range = spec.slice(rangeIdx + 1);
201
+ const [s, e] = range.split("-").map((v) => parseInt(v, 10));
202
+ if (!Number.isFinite(s) || !Number.isFinite(e)) {
203
+ commands.push({ name: "read", arguments: { path: filePath } });
204
+ return;
205
+ }
206
+ commands.push({ name: "read", arguments: { path: filePath, start: s, end: e } });
207
+ }
208
+ handleFinish(parts, rawLine, commands, acc) {
209
+ const map = acc ?? /* @__PURE__ */ new Map();
210
+ const args = parts.slice(1);
211
+ for (const token of args) {
212
+ const [filePath, rangesText] = token.split(":", 2);
213
+ if (!filePath || !rangesText) {
214
+ commands.push(this.skip(
215
+ `[SKIPPED] Invalid finish token "${token}". Correct format: finish <path>:<start>-<end>. Example: finish src/index.ts:1-50`
216
+ ));
217
+ continue;
218
+ }
219
+ const rangeSpecs = rangesText.split(",").filter(Boolean);
220
+ for (const spec of rangeSpecs) {
221
+ const [s, e] = spec.split("-").map((v) => parseInt(v, 10));
222
+ if (!Number.isFinite(s) || !Number.isFinite(e) || e < s) {
223
+ commands.push(this.skip(
224
+ `[SKIPPED] Invalid range "${spec}" in "${token}". Ranges must be <start>-<end> where start <= end. Example: 1-50`
225
+ ));
226
+ continue;
227
+ }
228
+ const arr = map.get(filePath) ?? [];
229
+ arr.push([s, e]);
230
+ map.set(filePath, arr);
231
+ }
232
+ }
233
+ return map;
234
+ }
235
+ };
236
+
237
+ // tools/warp_grep/agent/formatter.ts
238
+ var ToolOutputFormatter = class {
239
+ format(toolName, args, output, options = {}) {
240
+ const name = (toolName ?? "").trim();
241
+ if (!name) {
242
+ return "";
243
+ }
244
+ const payload = output?.toString?.()?.trim?.() ?? "";
245
+ const isError = Boolean(options.isError);
246
+ const safeArgs = args ?? {};
247
+ if (!payload && !isError) {
248
+ return "";
249
+ }
250
+ switch (name) {
251
+ case "read":
252
+ return this.formatRead(safeArgs, payload, isError);
253
+ case "analyse":
254
+ return this.formatAnalyse(safeArgs, payload, isError);
255
+ case "grep":
256
+ return this.formatGrep(safeArgs, payload, isError);
257
+ default:
258
+ return payload ? `<tool_output>
259
+ ${payload}
260
+ </tool_output>` : "";
261
+ }
262
+ }
263
+ formatRead(args, payload, isError) {
264
+ if (isError) {
265
+ return payload;
266
+ }
267
+ const path3 = this.asString(args.path) || "...";
268
+ return `<file path="${path3}">
269
+ ${payload}
270
+ </file>`;
271
+ }
272
+ formatAnalyse(args, payload, isError) {
273
+ const path3 = this.asString(args.path) || ".";
274
+ if (isError) {
275
+ return `<analyse_results path="${path3}" status="error">
276
+ ${payload}
277
+ </analyse_results>`;
278
+ }
279
+ return `<analyse_results path="${path3}">
280
+ ${payload}
281
+ </analyse_results>`;
282
+ }
283
+ formatGrep(args, payload, isError) {
284
+ const pattern = this.asString(args.pattern);
285
+ const path3 = this.asString(args.path);
286
+ const attributes = [];
287
+ if (pattern !== void 0) {
288
+ attributes.push(`pattern="${pattern}"`);
289
+ }
290
+ if (path3 !== void 0) {
291
+ attributes.push(`path="${path3}"`);
292
+ }
293
+ if (isError) {
294
+ attributes.push('status="error"');
295
+ }
296
+ const attrText = attributes.length ? ` ${attributes.join(" ")}` : "";
297
+ return `<grep_output${attrText}>
298
+ ${payload}
299
+ </grep_output>`;
300
+ }
301
+ asString(value) {
302
+ if (value === null || value === void 0) {
303
+ return void 0;
304
+ }
305
+ return String(value);
306
+ }
307
+ };
308
+ var sharedFormatter = new ToolOutputFormatter();
309
+ function formatAgentToolOutput(toolName, args, output, options = {}) {
310
+ return sharedFormatter.format(toolName, args, output, options);
311
+ }
312
+
313
+ // tools/warp_grep/agent/prompt.ts
314
+ var SYSTEM_PROMPT = `You are a code search agent. Your task is to find all relevant code for a given query.
315
+
316
+ <workflow>
317
+ You have exactly 4 turns. The 4th turn MUST be a \`finish\` call. Each turn allows up to 8 parallel tool calls.
318
+
319
+ - Turn 1: Map the territory OR dive deep (based on query specificity)
320
+ - Turn 2-3: Refine based on findings
321
+ - Turn 4: MUST call \`finish\` with all relevant code locations
322
+ - You MAY call \`finish\` early if confident\u2014but never before at least 1 search turn.
323
+
324
+ Remember, if the task feels easy to you, it is strongly desirable to call \`finish\` early using fewer turns, but quality over speed.
325
+ </workflow>
326
+
327
+ <tools>
328
+ ### \`analyse <path> [pattern]\`
329
+ Directory tree or file search. Shows structure of a path, optionally filtered by regex pattern.
330
+ - \`path\`: Required. Directory or file path (use \`.\` for repo root)
331
+ - \`pattern\`: Optional regex to filter results
332
+
333
+ Examples:
334
+ \`\`\`
335
+ analyse .
336
+ analyse src/api
337
+ analyse . ".*\\.ts$"
338
+ analyse src "test.*"
339
+ \`\`\`
340
+
341
+ ### \`read <path>[:start-end]\`
342
+ Read file contents. Line range is 1-based, inclusive.
343
+ - Returns numbered lines for easy reference
344
+ - Omit range to read entire file
345
+
346
+ Examples:
347
+ \`\`\`
348
+ read src/main.py
349
+ read src/db/conn.py:10-50
350
+ read package.json:1-20
351
+ \`\`\`
352
+
353
+ ### \`grep '<pattern>' <path>\`
354
+ Ripgrep search. Finds pattern matches across files.
355
+ - \`'<pattern>'\`: Required. Regex pattern wrapped in single quotes
356
+ - \`<path>\`: Required. Directory or file to search (use \`.\` for repo root)
357
+
358
+ Examples:
359
+ \`\`\`
360
+ grep 'class.*Service' src/
361
+ grep 'def authenticate' .
362
+ grep 'import.*from' src/components/
363
+ grep 'TODO' .
364
+ \`\`\`
365
+
366
+ ### \`finish <file1:ranges> [file2:ranges ...]\`
367
+ Submit final answer with all relevant code locations.
368
+ - Include generous line ranges\u2014don't be stingy with context
369
+ - Ranges are comma-separated: \`file.py:10-30,50-60\`
370
+ - ALWAYS include import statements at the top of files (usually lines 1-20)
371
+ - If code spans multiple files, include ALL of them
372
+ - Small files can be returned in full
373
+
374
+ Examples:
375
+ \`\`\`
376
+ finish src/auth.py:1-15,25-50,75-80 src/models/user.py:1-10,20-45
377
+ finish src/index.ts:1-100
378
+ \`\`\`
379
+ </tools>
380
+
381
+ <strategy>
382
+ **Before your first tool call, classify the query:**
383
+
384
+ | Query Type | Turn 1 Strategy | Early Finish? |
385
+ |------------|-----------------|---------------|
386
+ | **Specific** (function name, error string, unique identifier) | 8 parallel greps on likely paths | Often by turn 2 |
387
+ | **Conceptual** (how does X work, where is Y handled) | analyse + 2-3 broad greps | Rarely early |
388
+ | **Exploratory** (find all tests, list API endpoints) | analyse at multiple depths | Usually needs 3 turns |
389
+
390
+ **Parallel call patterns:**
391
+ - **Shotgun grep**: Same pattern, 8 different directories\u2014fast coverage
392
+ - **Variant grep**: 8 pattern variations (synonyms, naming conventions)\u2014catches inconsistent codebases
393
+ - **Funnel**: 1 analyse + 7 greps\u2014orient and search simultaneously
394
+ - **Deep read**: 8 reads on files you already identified\u2014gather full context fast
395
+ </strategy>
396
+
397
+ <output_format>
398
+ EVERY response MUST follow this exact format:
399
+
400
+ 1. First, wrap your reasoning in \`<think>...</think>\` tags containing:
401
+ - Query classification (specific/conceptual/exploratory)
402
+ - Confidence estimate (can I finish in 1-2 turns?)
403
+ - This turn's parallel strategy
404
+ - What signals would let me finish early?
405
+
406
+ 2. Then, output tool calls wrapped in \`<tool_call>...</tool_call>\` tags, one per line.
407
+
408
+ Example:
409
+ \`\`\`
410
+ <think>
411
+ This is a specific query about authentication. I'll grep for auth-related patterns.
412
+ High confidence I can finish in 2 turns if I find the auth module.
413
+ Strategy: Shotgun grep across likely directories.
414
+ </think>
415
+ <tool_call>grep 'authenticate' src/</tool_call>
416
+ <tool_call>grep 'login' src/</tool_call>
417
+ <tool_call>analyse src/auth</tool_call>
418
+ \`\`\`
419
+
420
+ No commentary outside \`<think>\`. No explanations after tool calls.
421
+ </output_format>
422
+
423
+ <finishing_requirements>
424
+ When calling \`finish\`:
425
+ - Include the import section (typically lines 1-20) of each file
426
+ - Include all function/class definitions that are relevant
427
+ - Include any type definitions, interfaces, or constants used
428
+ - Better to over-include than leave the user missing context
429
+ - If unsure about boundaries, include more rather than less
430
+ </finishing_requirements>
431
+
432
+ Begin your exploration now to find code relevant to the query.`;
433
+
434
+ // tools/warp_grep/agent/config.ts
435
+ var AGENT_CONFIG = {
436
+ // Give the model freedom; failsafe cap to prevent infinite loops
437
+ MAX_ROUNDS: 10,
438
+ TIMEOUT_MS: 3e4
439
+ };
440
+ var BUILTIN_EXCLUDES = [
441
+ // Version control
442
+ ".git",
443
+ ".svn",
444
+ ".hg",
445
+ ".bzr",
446
+ // Dependencies
447
+ "node_modules",
448
+ "bower_components",
449
+ ".pnpm",
450
+ ".yarn",
451
+ "vendor",
452
+ "packages",
453
+ "Pods",
454
+ ".bundle",
455
+ // Python
456
+ "__pycache__",
457
+ ".pytest_cache",
458
+ ".mypy_cache",
459
+ ".ruff_cache",
460
+ ".venv",
461
+ "venv",
462
+ ".tox",
463
+ ".nox",
464
+ ".eggs",
465
+ "*.egg-info",
466
+ // Build outputs
467
+ "dist",
468
+ "build",
469
+ "out",
470
+ "output",
471
+ "target",
472
+ "_build",
473
+ ".next",
474
+ ".nuxt",
475
+ ".output",
476
+ ".vercel",
477
+ ".netlify",
478
+ // Cache directories
479
+ ".cache",
480
+ ".parcel-cache",
481
+ ".turbo",
482
+ ".nx",
483
+ ".gradle",
484
+ // IDE/Editor
485
+ ".idea",
486
+ ".vscode",
487
+ ".vs",
488
+ // Coverage
489
+ "coverage",
490
+ ".coverage",
491
+ "htmlcov",
492
+ ".nyc_output",
493
+ // Temporary
494
+ "tmp",
495
+ "temp",
496
+ ".tmp",
497
+ ".temp",
498
+ // Lock files
499
+ "package-lock.json",
500
+ "yarn.lock",
501
+ "pnpm-lock.yaml",
502
+ "bun.lockb",
503
+ "Cargo.lock",
504
+ "Gemfile.lock",
505
+ "poetry.lock",
506
+ // Binary/minified
507
+ "*.min.js",
508
+ "*.min.css",
509
+ "*.bundle.js",
510
+ "*.wasm",
511
+ "*.so",
512
+ "*.dll",
513
+ "*.pyc",
514
+ "*.map",
515
+ "*.js.map",
516
+ // Hidden directories catch-all
517
+ ".*"
518
+ ];
519
+ var DEFAULT_EXCLUDES = (process.env.MORPH_WARP_GREP_EXCLUDE || "").split(",").map((s) => s.trim()).filter(Boolean).concat(BUILTIN_EXCLUDES);
520
+
521
+ // tools/warp_grep/tools/finish.ts
522
+ async function readFinishFiles(repoRoot, files, reader) {
523
+ const out = [];
524
+ for (const f of files) {
525
+ const ranges = mergeRanges(f.lines);
526
+ const chunks = [];
527
+ for (const [s, e] of ranges) {
528
+ const lines = await reader(f.path, s, e);
529
+ chunks.push(lines.join("\n"));
530
+ }
531
+ out.push({ path: f.path, ranges, content: chunks.join("\n") });
532
+ }
533
+ return out;
534
+ }
535
+ function mergeRanges(ranges) {
536
+ if (!ranges.length) return [];
537
+ const sorted = [...ranges].sort((a, b) => a[0] - b[0]);
538
+ const merged = [];
539
+ let [cs, ce] = sorted[0];
540
+ for (let i = 1; i < sorted.length; i++) {
541
+ const [s, e] = sorted[i];
542
+ if (s <= ce + 1) {
543
+ ce = Math.max(ce, e);
544
+ } else {
545
+ merged.push([cs, ce]);
546
+ cs = s;
547
+ ce = e;
548
+ }
549
+ }
550
+ merged.push([cs, ce]);
551
+ return merged;
552
+ }
553
+
554
+ // tools/warp_grep/providers/local.ts
555
+ var import_promises2 = __toESM(require("fs/promises"), 1);
556
+ var import_path2 = __toESM(require("path"), 1);
557
+
558
+ // tools/warp_grep/utils/ripgrep.ts
559
+ var import_child_process = require("child_process");
560
+ var import_ripgrep = require("@vscode/ripgrep");
561
+ var resolvedRgPath = null;
562
+ var rgPathChecked = false;
563
+ function spawnRg(rgBinary, args, opts) {
564
+ return new Promise((resolve) => {
565
+ const child = (0, import_child_process.spawn)(rgBinary, args, {
566
+ cwd: opts?.cwd,
567
+ env: { ...process.env, ...opts?.env || {} },
568
+ stdio: ["ignore", "pipe", "pipe"]
569
+ });
570
+ let stdout = "";
571
+ let stderr = "";
572
+ child.stdout.on("data", (d) => stdout += d.toString());
573
+ child.stderr.on("data", (d) => stderr += d.toString());
574
+ child.on("close", (code) => {
575
+ resolve({ stdout, stderr, exitCode: typeof code === "number" ? code : -1 });
576
+ });
577
+ child.on("error", () => {
578
+ resolve({ stdout: "", stderr: "Failed to spawn ripgrep.", exitCode: -1 });
579
+ });
580
+ });
581
+ }
582
+ function isBinaryFailure(result) {
583
+ if (result.exitCode === -1) return true;
584
+ if (result.stderr.includes("jemalloc") || result.stderr.includes("Unsupported system page size")) return true;
585
+ if (result.exitCode === 134) return true;
586
+ return false;
587
+ }
588
+ async function runRipgrep(args, opts) {
589
+ if (rgPathChecked && resolvedRgPath) {
590
+ return spawnRg(resolvedRgPath, args, opts);
591
+ }
592
+ if (!rgPathChecked) {
593
+ const result = await spawnRg(import_ripgrep.rgPath, args, opts);
594
+ if (!isBinaryFailure(result)) {
595
+ resolvedRgPath = import_ripgrep.rgPath;
596
+ rgPathChecked = true;
597
+ return result;
598
+ }
599
+ const fallbackResult = await spawnRg("rg", args, opts);
600
+ if (!isBinaryFailure(fallbackResult)) {
601
+ resolvedRgPath = "rg";
602
+ rgPathChecked = true;
603
+ return fallbackResult;
604
+ }
605
+ rgPathChecked = true;
606
+ return {
607
+ stdout: "",
608
+ stderr: "Failed to spawn ripgrep. Neither bundled nor system rg is available.",
609
+ exitCode: -1
610
+ };
611
+ }
612
+ return {
613
+ stdout: "",
614
+ stderr: "Failed to spawn ripgrep. Neither bundled nor system rg is available.",
615
+ exitCode: -1
616
+ };
617
+ }
618
+
619
+ // tools/warp_grep/utils/paths.ts
620
+ var import_fs = __toESM(require("fs"), 1);
621
+ var import_path = __toESM(require("path"), 1);
622
+ function resolveUnderRepo(repoRoot, targetPath) {
623
+ const absRoot = import_path.default.resolve(repoRoot);
624
+ const resolved = import_path.default.resolve(absRoot, targetPath);
625
+ ensureWithinRepo(absRoot, resolved);
626
+ return resolved;
627
+ }
628
+ function ensureWithinRepo(repoRoot, absTarget) {
629
+ const rel = import_path.default.relative(import_path.default.resolve(repoRoot), import_path.default.resolve(absTarget));
630
+ if (rel.startsWith("..") || import_path.default.isAbsolute(rel)) {
631
+ throw new Error(`Path outside repository root: ${absTarget}`);
632
+ }
633
+ }
634
+ function toRepoRelative(repoRoot, absPath) {
635
+ return import_path.default.relative(import_path.default.resolve(repoRoot), import_path.default.resolve(absPath));
636
+ }
637
+ function isSymlink(p) {
638
+ try {
639
+ const st = import_fs.default.lstatSync(p);
640
+ return st.isSymbolicLink();
641
+ } catch {
642
+ return false;
643
+ }
644
+ }
645
+ function isTextualFile(filePath, maxBytes = 2e6) {
646
+ try {
647
+ const st = import_fs.default.statSync(filePath);
648
+ if (!st.isFile()) return false;
649
+ if (st.size > maxBytes) return false;
650
+ const fd = import_fs.default.openSync(filePath, "r");
651
+ const buf = Buffer.alloc(512);
652
+ const read = import_fs.default.readSync(fd, buf, 0, buf.length, 0);
653
+ import_fs.default.closeSync(fd);
654
+ for (let i = 0; i < read; i++) {
655
+ const c = buf[i];
656
+ if (c === 0) return false;
657
+ }
658
+ return true;
659
+ } catch {
660
+ return false;
661
+ }
662
+ }
663
+
664
+ // tools/warp_grep/utils/files.ts
665
+ var import_promises = __toESM(require("fs/promises"), 1);
666
+ async function readAllLines(filePath) {
667
+ const content = await import_promises.default.readFile(filePath, "utf8");
668
+ return content.split(/\r?\n/);
669
+ }
670
+
671
+ // tools/warp_grep/providers/local.ts
672
+ var LocalRipgrepProvider = class {
673
+ constructor(repoRoot, excludes = DEFAULT_EXCLUDES) {
674
+ this.repoRoot = repoRoot;
675
+ this.excludes = excludes;
676
+ }
677
+ async grep(params) {
678
+ const abs = resolveUnderRepo(this.repoRoot, params.path);
679
+ const stat = await import_promises2.default.stat(abs).catch(() => null);
680
+ if (!stat) return { lines: [] };
681
+ const targetArg = abs === import_path2.default.resolve(this.repoRoot) ? "." : toRepoRelative(this.repoRoot, abs);
682
+ const args = [
683
+ "--no-config",
684
+ "--no-heading",
685
+ "--with-filename",
686
+ "--line-number",
687
+ "--color=never",
688
+ "--trim",
689
+ "--max-columns=400",
690
+ ...this.excludes.flatMap((e) => ["-g", `!${e}`]),
691
+ params.pattern,
692
+ targetArg || "."
693
+ ];
694
+ const res = await runRipgrep(args, { cwd: this.repoRoot });
695
+ if (res.exitCode === -1) {
696
+ return {
697
+ lines: [],
698
+ error: `[RIPGREP NOT AVAILABLE] ripgrep (rg) is required but failed to execute. Please install it:
699
+ \u2022 macOS: brew install ripgrep
700
+ \u2022 Ubuntu/Debian: apt install ripgrep
701
+ \u2022 Windows: choco install ripgrep
702
+ \u2022 Or visit: https://github.com/BurntSushi/ripgrep#installation
703
+ Exit code: ${res.exitCode}${res.stderr ? `
704
+ Details: ${res.stderr}` : ""}`
705
+ };
706
+ }
707
+ if (res.exitCode !== 0 && res.exitCode !== 1) {
708
+ return {
709
+ lines: [],
710
+ error: `[RIPGREP ERROR] grep failed with exit code ${res.exitCode}${res.stderr ? `: ${res.stderr}` : ""}`
711
+ };
712
+ }
713
+ const lines = (res.stdout || "").trim().split(/\r?\n/).filter((l) => l.length > 0);
714
+ return { lines };
715
+ }
716
+ async glob(params) {
717
+ const abs = resolveUnderRepo(this.repoRoot, params.path);
718
+ const targetArg = abs === import_path2.default.resolve(this.repoRoot) ? "." : toRepoRelative(this.repoRoot, abs);
719
+ const args = [
720
+ "--no-config",
721
+ "--files",
722
+ "-g",
723
+ params.pattern,
724
+ ...this.excludes.flatMap((e) => ["-g", `!${e}`]),
725
+ targetArg || "."
726
+ ];
727
+ const res = await runRipgrep(args, { cwd: this.repoRoot });
728
+ if (res.exitCode === -1) {
729
+ console.warn(`[warp_grep] ripgrep not available for glob: ${res.stderr || "execution failed"}`);
730
+ return { files: [] };
731
+ }
732
+ const files = (res.stdout || "").trim().split(/\r?\n/).filter((l) => l.length > 0);
733
+ return { files };
734
+ }
735
+ async read(params) {
736
+ const abs = resolveUnderRepo(this.repoRoot, params.path);
737
+ const stat = await import_promises2.default.stat(abs).catch(() => null);
738
+ if (!stat || !stat.isFile()) {
739
+ return {
740
+ lines: [],
741
+ 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.`
742
+ };
743
+ }
744
+ if (isSymlink(abs)) {
745
+ return {
746
+ lines: [],
747
+ error: `[SYMLINK] You tried to read "${params.path}" but this is a symlink. Try reading the actual file it points to instead.`
748
+ };
749
+ }
750
+ if (!isTextualFile(abs)) {
751
+ return {
752
+ lines: [],
753
+ 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.`
754
+ };
755
+ }
756
+ const lines = await readAllLines(abs);
757
+ const total = lines.length;
758
+ let s = params.start ?? 1;
759
+ let e = Math.min(params.end ?? total, total);
760
+ if (s > total && total > 0) {
761
+ s = 1;
762
+ e = total;
763
+ }
764
+ const out = [];
765
+ for (let i = s; i <= e; i += 1) {
766
+ const content = lines[i - 1] ?? "";
767
+ out.push(`${i}|${content}`);
768
+ }
769
+ return { lines: out };
770
+ }
771
+ async analyse(params) {
772
+ const abs = resolveUnderRepo(this.repoRoot, params.path);
773
+ const stat = await import_promises2.default.stat(abs).catch(() => null);
774
+ if (!stat || !stat.isDirectory()) {
775
+ return [];
776
+ }
777
+ const maxResults = params.maxResults ?? 100;
778
+ const maxDepth = params.maxDepth ?? 2;
779
+ const regex = params.pattern ? new RegExp(params.pattern) : null;
780
+ const results = [];
781
+ async function walk(dir, depth) {
782
+ if (depth > maxDepth || results.length >= maxResults) return;
783
+ const entries = await import_promises2.default.readdir(dir, { withFileTypes: true });
784
+ for (const entry of entries) {
785
+ const full = import_path2.default.join(dir, entry.name);
786
+ const rel = toRepoRelative(abs, full).replace(/^[.][/\\]?/, "");
787
+ if (DEFAULT_EXCLUDES.some((ex) => rel.split(import_path2.default.sep).includes(ex))) continue;
788
+ if (regex && !regex.test(entry.name)) continue;
789
+ if (results.length >= maxResults) break;
790
+ results.push({
791
+ name: entry.name,
792
+ path: toRepoRelative(import_path2.default.resolve(""), full),
793
+ // relative display
794
+ type: entry.isDirectory() ? "dir" : "file",
795
+ depth
796
+ });
797
+ if (entry.isDirectory()) {
798
+ await walk(full, depth + 1);
799
+ }
800
+ }
801
+ }
802
+ await walk(abs, 0);
803
+ return results;
804
+ }
805
+ };
806
+
807
+ // tools/warp_grep/harness.ts
808
+ var parser = new LLMResponseParser();
809
+ function parseToolCalls(text) {
810
+ return parser.parse(text);
811
+ }
812
+ function formatToolResult(name, args, output, options) {
813
+ return formatAgentToolOutput(name, args, output, options ?? {});
814
+ }
815
+ function formatTurnMessage(turn, maxTurns = 4) {
816
+ const remaining = maxTurns - turn;
817
+ if (remaining === 0) {
818
+ return `
819
+
820
+ [Turn ${turn}/${maxTurns}] This is your LAST turn. You MUST call finish now.`;
821
+ }
822
+ if (remaining === 1) {
823
+ return `
824
+
825
+ [Turn ${turn}/${maxTurns}] You have 1 turn remaining.`;
826
+ }
827
+ return `
828
+
829
+ [Turn ${turn}/${maxTurns}] You have ${remaining} turns remaining.`;
830
+ }
831
+ function formatAnalyseTree(entries) {
832
+ if (!entries.length) return "empty";
833
+ return entries.map((e) => `${" ".repeat(e.depth)}- ${e.type === "dir" ? "[D]" : "[F]"} ${e.name}`).join("\n");
834
+ }
835
+ async function resolveFinishFiles(provider, files) {
836
+ return readFinishFiles("", files, async (p, s, e) => {
837
+ const r = await provider.read({ path: p, start: s, end: e });
838
+ return r.lines.map((l) => {
839
+ const idx = l.indexOf("|");
840
+ return idx >= 0 ? l.slice(idx + 1) : l;
841
+ });
842
+ });
843
+ }
844
+ var MAX_TURNS = 4;
845
+ var TIMEOUT_MS = AGENT_CONFIG.TIMEOUT_MS;
846
+ // Annotate the CommonJS export names for ESM import in node:
847
+ 0 && (module.exports = {
848
+ DEFAULT_EXCLUDES,
849
+ LocalRipgrepProvider,
850
+ MAX_TURNS,
851
+ SYSTEM_PROMPT,
852
+ TIMEOUT_MS,
853
+ formatAnalyseTree,
854
+ formatToolResult,
855
+ formatTurnMessage,
856
+ parseToolCalls,
857
+ resolveFinishFiles
858
+ });
859
+ //# sourceMappingURL=harness.cjs.map