@morphllm/morphsdk 0.2.21 → 0.2.22

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 (180) hide show
  1. package/dist/{chunk-DF2ZOO7R.js → chunk-5VQEQSJQ.js} +3 -52
  2. package/dist/chunk-5VQEQSJQ.js.map +1 -0
  3. package/dist/chunk-73RQWOQC.js +16 -0
  4. package/dist/chunk-73RQWOQC.js.map +1 -0
  5. package/dist/{chunk-2DXRTGRH.js → chunk-74ZHKB54.js} +1 -1
  6. package/dist/{chunk-2DXRTGRH.js.map → chunk-74ZHKB54.js.map} +1 -1
  7. package/dist/chunk-AFEPUNAO.js +15 -0
  8. package/dist/chunk-AFEPUNAO.js.map +1 -0
  9. package/dist/chunk-EAA7D24N.js +201 -0
  10. package/dist/chunk-EAA7D24N.js.map +1 -0
  11. package/dist/chunk-EK7OQPWD.js +44 -0
  12. package/dist/chunk-EK7OQPWD.js.map +1 -0
  13. package/dist/chunk-FSVBNZMU.js +44 -0
  14. package/dist/chunk-FSVBNZMU.js.map +1 -0
  15. package/dist/chunk-G2RSY56Q.js +11 -0
  16. package/dist/chunk-G2RSY56Q.js.map +1 -0
  17. package/dist/chunk-GTOXMAF2.js +140 -0
  18. package/dist/chunk-GTOXMAF2.js.map +1 -0
  19. package/dist/chunk-HKZB23U7.js +85 -0
  20. package/dist/chunk-HKZB23U7.js.map +1 -0
  21. package/dist/chunk-JZGU5UC6.js +53 -0
  22. package/dist/chunk-JZGU5UC6.js.map +1 -0
  23. package/dist/chunk-NDZO5IPV.js +121 -0
  24. package/dist/chunk-NDZO5IPV.js.map +1 -0
  25. package/dist/{chunk-34F3D6JD.js → chunk-NSQGPBMU.js} +9 -9
  26. package/dist/chunk-RSLIOCOE.js +26 -0
  27. package/dist/chunk-RSLIOCOE.js.map +1 -0
  28. package/dist/chunk-SMGZ6A64.js +53 -0
  29. package/dist/chunk-SMGZ6A64.js.map +1 -0
  30. package/dist/chunk-TICMYDII.js +81 -0
  31. package/dist/chunk-TICMYDII.js.map +1 -0
  32. package/dist/chunk-UYBIKZPM.js +135 -0
  33. package/dist/chunk-UYBIKZPM.js.map +1 -0
  34. package/dist/chunk-VBBJGWHY.js +73 -0
  35. package/dist/chunk-VBBJGWHY.js.map +1 -0
  36. package/dist/chunk-XQLKK2ZH.js +56 -0
  37. package/dist/chunk-XQLKK2ZH.js.map +1 -0
  38. package/dist/chunk-XYPMN4A3.js +1 -0
  39. package/dist/chunk-XYPMN4A3.js.map +1 -0
  40. package/dist/chunk-Z2FBMSNE.js +10 -0
  41. package/dist/chunk-Z2FBMSNE.js.map +1 -0
  42. package/dist/client.cjs +2 -51
  43. package/dist/client.cjs.map +1 -1
  44. package/dist/client.js +4 -4
  45. package/dist/git/client.cjs +2 -51
  46. package/dist/git/client.cjs.map +1 -1
  47. package/dist/git/client.js +1 -1
  48. package/dist/git/index.cjs +2 -51
  49. package/dist/git/index.cjs.map +1 -1
  50. package/dist/git/index.js +2 -2
  51. package/dist/git/types.cjs.map +1 -1
  52. package/dist/index.cjs +2 -51
  53. package/dist/index.cjs.map +1 -1
  54. package/dist/index.js +10 -10
  55. package/dist/tools/warp_grep/agent/config.cjs +41 -0
  56. package/dist/tools/warp_grep/agent/config.cjs.map +1 -0
  57. package/dist/tools/warp_grep/agent/config.js +12 -0
  58. package/dist/tools/warp_grep/agent/config.js.map +1 -0
  59. package/dist/tools/warp_grep/agent/formatter.cjs +106 -0
  60. package/dist/tools/warp_grep/agent/formatter.cjs.map +1 -0
  61. package/dist/tools/warp_grep/agent/formatter.js +10 -0
  62. package/dist/tools/warp_grep/agent/formatter.js.map +1 -0
  63. package/dist/tools/warp_grep/agent/grep_helpers.cjs +148 -0
  64. package/dist/tools/warp_grep/agent/grep_helpers.cjs.map +1 -0
  65. package/dist/tools/warp_grep/agent/grep_helpers.js +14 -0
  66. package/dist/tools/warp_grep/agent/grep_helpers.js.map +1 -0
  67. package/dist/tools/warp_grep/agent/parser.cjs +165 -0
  68. package/dist/tools/warp_grep/agent/parser.cjs.map +1 -0
  69. package/dist/tools/warp_grep/agent/parser.js +10 -0
  70. package/dist/tools/warp_grep/agent/parser.js.map +1 -0
  71. package/dist/tools/warp_grep/agent/prompt.cjs +110 -0
  72. package/dist/tools/warp_grep/agent/prompt.cjs.map +1 -0
  73. package/dist/tools/warp_grep/agent/prompt.js +10 -0
  74. package/dist/tools/warp_grep/agent/prompt.js.map +1 -0
  75. package/dist/tools/warp_grep/agent/runner.cjs +744 -0
  76. package/dist/tools/warp_grep/agent/runner.cjs.map +1 -0
  77. package/dist/tools/warp_grep/agent/runner.js +17 -0
  78. package/dist/tools/warp_grep/agent/runner.js.map +1 -0
  79. package/dist/tools/warp_grep/agent/types.cjs +19 -0
  80. package/dist/tools/warp_grep/agent/types.cjs.map +1 -0
  81. package/dist/tools/warp_grep/agent/types.js +2 -0
  82. package/dist/tools/warp_grep/agent/types.js.map +1 -0
  83. package/dist/tools/warp_grep/anthropic.cjs +977 -0
  84. package/dist/tools/warp_grep/anthropic.cjs.map +1 -0
  85. package/dist/tools/warp_grep/anthropic.js +22 -0
  86. package/dist/tools/warp_grep/anthropic.js.map +1 -0
  87. package/dist/tools/warp_grep/index.cjs +1136 -0
  88. package/dist/tools/warp_grep/index.cjs.map +1 -0
  89. package/dist/tools/warp_grep/index.js +48 -0
  90. package/dist/tools/warp_grep/index.js.map +1 -0
  91. package/dist/tools/warp_grep/openai.cjs +980 -0
  92. package/dist/tools/warp_grep/openai.cjs.map +1 -0
  93. package/dist/tools/warp_grep/openai.js +22 -0
  94. package/dist/tools/warp_grep/openai.js.map +1 -0
  95. package/dist/tools/warp_grep/providers/command.cjs +98 -0
  96. package/dist/tools/warp_grep/providers/command.cjs.map +1 -0
  97. package/dist/tools/warp_grep/providers/command.js +9 -0
  98. package/dist/tools/warp_grep/providers/command.js.map +1 -0
  99. package/dist/tools/warp_grep/providers/local.cjs +232 -0
  100. package/dist/tools/warp_grep/providers/local.cjs.map +1 -0
  101. package/dist/tools/warp_grep/providers/local.js +12 -0
  102. package/dist/tools/warp_grep/providers/local.js.map +1 -0
  103. package/dist/tools/warp_grep/providers/types.cjs +19 -0
  104. package/dist/tools/warp_grep/providers/types.cjs.map +1 -0
  105. package/dist/tools/warp_grep/providers/types.js +1 -0
  106. package/dist/tools/warp_grep/providers/types.js.map +1 -0
  107. package/dist/tools/warp_grep/tools/analyse.cjs +40 -0
  108. package/dist/tools/warp_grep/tools/analyse.cjs.map +1 -0
  109. package/dist/tools/warp_grep/tools/analyse.js +8 -0
  110. package/dist/tools/warp_grep/tools/analyse.js.map +1 -0
  111. package/dist/tools/warp_grep/tools/finish.cjs +69 -0
  112. package/dist/tools/warp_grep/tools/finish.cjs.map +1 -0
  113. package/dist/tools/warp_grep/tools/finish.js +10 -0
  114. package/dist/tools/warp_grep/tools/finish.js.map +1 -0
  115. package/dist/tools/warp_grep/tools/grep.cjs +35 -0
  116. package/dist/tools/warp_grep/tools/grep.cjs.map +1 -0
  117. package/dist/tools/warp_grep/tools/grep.js +12 -0
  118. package/dist/tools/warp_grep/tools/grep.js.map +1 -0
  119. package/dist/tools/warp_grep/tools/read.cjs +34 -0
  120. package/dist/tools/warp_grep/tools/read.cjs.map +1 -0
  121. package/dist/tools/warp_grep/tools/read.js +8 -0
  122. package/dist/tools/warp_grep/tools/read.js.map +1 -0
  123. package/dist/tools/warp_grep/utils/files.cjs +45 -0
  124. package/dist/tools/warp_grep/utils/files.cjs.map +1 -0
  125. package/dist/tools/warp_grep/utils/files.js +8 -0
  126. package/dist/tools/warp_grep/utils/files.js.map +1 -0
  127. package/dist/tools/warp_grep/utils/format.cjs +42 -0
  128. package/dist/tools/warp_grep/utils/format.cjs.map +1 -0
  129. package/dist/tools/warp_grep/utils/format.js +18 -0
  130. package/dist/tools/warp_grep/utils/format.js.map +1 -0
  131. package/dist/tools/warp_grep/utils/paths.cjs +91 -0
  132. package/dist/tools/warp_grep/utils/paths.cjs.map +1 -0
  133. package/dist/tools/warp_grep/utils/paths.js +16 -0
  134. package/dist/tools/warp_grep/utils/paths.js.map +1 -0
  135. package/dist/tools/warp_grep/utils/ripgrep.cjs +50 -0
  136. package/dist/tools/warp_grep/utils/ripgrep.cjs.map +1 -0
  137. package/dist/tools/warp_grep/utils/ripgrep.js +8 -0
  138. package/dist/tools/warp_grep/utils/ripgrep.js.map +1 -0
  139. package/dist/tools/warp_grep/vercel.cjs +968 -0
  140. package/dist/tools/warp_grep/vercel.cjs.map +1 -0
  141. package/dist/tools/warp_grep/vercel.js +22 -0
  142. package/dist/tools/warp_grep/vercel.js.map +1 -0
  143. package/package.json +23 -3
  144. package/dist/anthropic-CknfcMoO.d.ts +0 -64
  145. package/dist/chunk-DF2ZOO7R.js.map +0 -1
  146. package/dist/client.d.ts +0 -114
  147. package/dist/git/client.d.ts +0 -255
  148. package/dist/git/config.d.ts +0 -11
  149. package/dist/git/index.d.ts +0 -5
  150. package/dist/git/types.d.ts +0 -102
  151. package/dist/index.d.ts +0 -14
  152. package/dist/modelrouter/core.d.ts +0 -56
  153. package/dist/modelrouter/index.d.ts +0 -2
  154. package/dist/modelrouter/types.d.ts +0 -35
  155. package/dist/openai-BkKsS30n.d.ts +0 -111
  156. package/dist/tools/browser/anthropic.d.ts +0 -51
  157. package/dist/tools/browser/core.d.ts +0 -196
  158. package/dist/tools/browser/index.d.ts +0 -72
  159. package/dist/tools/browser/openai.d.ts +0 -69
  160. package/dist/tools/browser/prompts.d.ts +0 -7
  161. package/dist/tools/browser/types.d.ts +0 -227
  162. package/dist/tools/browser/vercel.d.ts +0 -69
  163. package/dist/tools/codebase_search/anthropic.d.ts +0 -40
  164. package/dist/tools/codebase_search/core.d.ts +0 -40
  165. package/dist/tools/codebase_search/index.d.ts +0 -10
  166. package/dist/tools/codebase_search/openai.d.ts +0 -87
  167. package/dist/tools/codebase_search/prompts.d.ts +0 -7
  168. package/dist/tools/codebase_search/types.d.ts +0 -46
  169. package/dist/tools/codebase_search/vercel.d.ts +0 -65
  170. package/dist/tools/fastapply/anthropic.d.ts +0 -4
  171. package/dist/tools/fastapply/core.d.ts +0 -41
  172. package/dist/tools/fastapply/index.d.ts +0 -10
  173. package/dist/tools/fastapply/openai.d.ts +0 -4
  174. package/dist/tools/fastapply/prompts.d.ts +0 -7
  175. package/dist/tools/fastapply/types.d.ts +0 -77
  176. package/dist/tools/fastapply/vercel.d.ts +0 -4
  177. package/dist/tools/index.d.ts +0 -10
  178. package/dist/tools/utils/resilience.d.ts +0 -58
  179. package/dist/vercel-B1GZ_g9N.d.ts +0 -69
  180. /package/dist/{chunk-34F3D6JD.js.map → chunk-NSQGPBMU.js.map} +0 -0
@@ -0,0 +1,1136 @@
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/index.ts
31
+ var warp_grep_exports = {};
32
+ __export(warp_grep_exports, {
33
+ AGENT_CONFIG: () => AGENT_CONFIG,
34
+ CommandExecProvider: () => CommandExecProvider,
35
+ DEFAULT_EXCLUDES: () => DEFAULT_EXCLUDES,
36
+ DEFAULT_MODEL: () => DEFAULT_MODEL,
37
+ LocalRipgrepProvider: () => LocalRipgrepProvider,
38
+ createAnthropicWarpGrepTool: () => createMorphWarpGrepTool2,
39
+ createOpenAIWarpGrepTool: () => createMorphWarpGrepTool,
40
+ createVercelWarpGrepTool: () => createMorphWarpGrepTool3,
41
+ runWarpGrep: () => runWarpGrep
42
+ });
43
+ module.exports = __toCommonJS(warp_grep_exports);
44
+
45
+ // tools/warp_grep/agent/config.ts
46
+ var AGENT_CONFIG = {
47
+ // Give the model freedom; failsafe cap to prevent infinite loops
48
+ MAX_ROUNDS: 10,
49
+ TIMEOUT_MS: 3e4
50
+ };
51
+ var DEFAULT_EXCLUDES = (process.env.MORPH_WARP_GREP_EXCLUDE || "").split(",").map((s) => s.trim()).filter(Boolean).concat(["node_modules", ".git", "dist", "build", ".cache", "venv", "target"]);
52
+ var DEFAULT_MODEL = "morph-warp-grep";
53
+
54
+ // tools/warp_grep/agent/prompt.ts
55
+ var SYSTEM_PROMPT = `You are a code search agent. Your task is to find relevant code snippets based on a search query.
56
+
57
+ <workflow>
58
+ You operate in exactly 3 rounds of tool exploration, followed by a final answer:
59
+
60
+ 1. In each round, you can make MULTIPLE tool calls (up to 8) to search in parallel. All tool results will be returned together after each round.
61
+ 2. After your third round of tool calls, your next turn MUST be a single call to the \`finish\` tool with all the context you have found.
62
+ </workflow>
63
+
64
+ <tool_calling>
65
+ You have tools at your disposal to solve the coding task. Follow these rules regarding tool calls:
66
+
67
+ ### 1. \`analyse\` - Explore Directories
68
+ Explore directory structure in a tree-like format.
69
+ **Syntax:** \`analyse <path> [pattern]\`
70
+ - \`<path>\`: Directory path to analyze (defaults to \`.\`)
71
+ - \`[pattern]\`: Optional regex pattern to filter names
72
+
73
+ For example:
74
+ \`\`\`
75
+ analyse src/api
76
+ analyse . "test"
77
+ \`\`\`
78
+
79
+ ### 2. \`read\` - Read File Contents
80
+ Read entire files or specific line ranges.
81
+ **Syntax:** \`read <path>[:start-end]\`
82
+ - \`<path>\`: File path to read
83
+ - \`[:start-end]\`: Optional 1-based, inclusive line range
84
+
85
+ For example:
86
+ \`\`\`
87
+ read src/main.py
88
+ read src/database/connection.py:10-50
89
+ \`\`\`
90
+
91
+ ### 3. \`grep\` - Search with Regex
92
+ Search for regex patterns across files using ripgrep.
93
+ **Syntax:** \`grep '<pattern>' <path>\`
94
+ - \`'<pattern>'\`: Regex pattern (always wrap in single quotes)
95
+ - \`<path>\`: Directory or file to search (use \`.\` for the repo root)
96
+
97
+ For example:
98
+ \`\`\`
99
+ grep 'create_user' .
100
+ grep 'import.*requests' src/api
101
+ grep 'class\\\\s+AuthService' controllers/auth.py
102
+ \`\`\`
103
+
104
+ ### 4. \`finish\` - Submit Final Answer
105
+ Submit your findings when complete.
106
+ **Syntax:** \`finish <file1:range1,range2...> [file2:range3...]\`
107
+ - Provide file paths with colon-separated, comma-separated line ranges
108
+
109
+ For example:
110
+ \`\`\`
111
+ finish src/api/auth.py:25-50,75-80 src/models/user.py:10-15
112
+ \`\`\`
113
+ </tool_calling>
114
+
115
+ <strategy>
116
+ - Use the \`analyse\`, \`grep\`, and \`read\` tools to gather information about the codebase.
117
+ - Leverage the tools smartly to make full use of their potential
118
+ - Make parallel tool calls within each round to investigate multiple paths or files efficiently
119
+ - Be systematic and thorough within your 3-round limit
120
+ </strategy>
121
+
122
+ <output_format>
123
+ - Only output tool calls themselves
124
+ - Do not include explanatory text, reasoning, or commentary
125
+ - Each tool call should be on its own line
126
+ - After 3 rounds of exploration, call \`finish\` with all relevant code snippets you found
127
+ </output_format>
128
+
129
+ Begin your exploration now to find code relevant to the query.`;
130
+ function getSystemPrompt() {
131
+ return SYSTEM_PROMPT;
132
+ }
133
+
134
+ // tools/warp_grep/agent/parser.ts
135
+ var LLMResponseParseError = class extends Error {
136
+ constructor(message) {
137
+ super(message);
138
+ this.name = "LLMResponseParseError";
139
+ }
140
+ };
141
+ var LLMResponseParser = class {
142
+ finishSpecSplitRe = /,(?=[^,\s]+:)/;
143
+ parse(text) {
144
+ if (typeof text !== "string") {
145
+ throw new TypeError("Command text must be a string.");
146
+ }
147
+ const lines = text.split(/\r?\n/).map((l) => l.trim());
148
+ const commands = [];
149
+ let finishAccumulator = null;
150
+ lines.forEach((line, idx) => {
151
+ if (!line || line.startsWith("#")) return;
152
+ const ctx = { lineNumber: idx + 1, raw: line };
153
+ const parts = this.splitLine(line, ctx);
154
+ if (parts.length === 0) return;
155
+ const cmd = parts[0];
156
+ switch (cmd) {
157
+ case "analyse":
158
+ this.handleAnalyse(parts, ctx, commands);
159
+ break;
160
+ case "grep":
161
+ this.handleGrep(parts, ctx, commands);
162
+ break;
163
+ case "read":
164
+ this.handleRead(parts, ctx, commands);
165
+ break;
166
+ case "finish":
167
+ finishAccumulator = this.handleFinish(parts, ctx, finishAccumulator);
168
+ break;
169
+ default:
170
+ throw new LLMResponseParseError(`Line ${ctx.lineNumber}: Unsupported command '${cmd}'`);
171
+ }
172
+ });
173
+ if (finishAccumulator) {
174
+ const map = finishAccumulator;
175
+ const entries = [...map.entries()];
176
+ const filesPayload = entries.map(([path4, ranges]) => ({
177
+ path: path4,
178
+ lines: [...ranges].sort((a, b) => a[0] - b[0])
179
+ }));
180
+ commands.push({ name: "finish", arguments: { files: filesPayload } });
181
+ }
182
+ return commands;
183
+ }
184
+ splitLine(line, ctx) {
185
+ try {
186
+ const parts = [];
187
+ let current = "";
188
+ let inSingle = false;
189
+ for (let i = 0; i < line.length; i++) {
190
+ const ch = line[i];
191
+ if (ch === "'" && line[i - 1] !== "\\") {
192
+ inSingle = !inSingle;
193
+ current += ch;
194
+ } else if (!inSingle && /\s/.test(ch)) {
195
+ if (current) {
196
+ parts.push(current);
197
+ current = "";
198
+ }
199
+ } else {
200
+ current += ch;
201
+ }
202
+ }
203
+ if (current) parts.push(current);
204
+ return parts;
205
+ } catch {
206
+ throw new LLMResponseParseError(`Line ${ctx.lineNumber}: Unable to parse line.`);
207
+ }
208
+ }
209
+ handleAnalyse(parts, ctx, commands) {
210
+ if (parts.length < 2) {
211
+ throw new LLMResponseParseError(`Line ${ctx.lineNumber}: analyse requires <path>`);
212
+ }
213
+ const path4 = parts[1];
214
+ const pattern = parts[2]?.replace(/^"|"$/g, "") ?? null;
215
+ commands.push({ name: "analyse", arguments: { path: path4, pattern } });
216
+ }
217
+ // no glob tool in MCP
218
+ handleGrep(parts, ctx, commands) {
219
+ if (parts.length < 3) {
220
+ throw new LLMResponseParseError(`Line ${ctx.lineNumber}: grep requires '<pattern>' and <path>`);
221
+ }
222
+ const pat = parts[1];
223
+ if (!pat.startsWith("'") || !pat.endsWith("'")) {
224
+ throw new LLMResponseParseError(`Line ${ctx.lineNumber}: grep pattern must be single-quoted`);
225
+ }
226
+ commands.push({ name: "grep", arguments: { pattern: pat.slice(1, -1), path: parts[2] } });
227
+ }
228
+ handleRead(parts, ctx, commands) {
229
+ if (parts.length < 2) {
230
+ throw new LLMResponseParseError(`Line ${ctx.lineNumber}: read requires <path> or <path>:<start-end>`);
231
+ }
232
+ const spec = parts[1];
233
+ const rangeIdx = spec.indexOf(":");
234
+ if (rangeIdx === -1) {
235
+ commands.push({ name: "read", arguments: { path: spec } });
236
+ return;
237
+ }
238
+ const path4 = spec.slice(0, rangeIdx);
239
+ const range = spec.slice(rangeIdx + 1);
240
+ const [s, e] = range.split("-").map((v) => parseInt(v, 10));
241
+ if (!Number.isFinite(s) || !Number.isFinite(e)) {
242
+ throw new LLMResponseParseError(`Line ${ctx.lineNumber}: invalid read range '${range}'`);
243
+ }
244
+ commands.push({ name: "read", arguments: { path: path4, start: s, end: e } });
245
+ }
246
+ handleFinish(parts, ctx, acc) {
247
+ const map = acc ?? /* @__PURE__ */ new Map();
248
+ const args = parts.slice(1);
249
+ for (const token of args) {
250
+ const [path4, rangesText] = token.split(":", 2);
251
+ if (!path4 || !rangesText) {
252
+ throw new LLMResponseParseError(`Line ${ctx.lineNumber}: invalid finish token '${token}'`);
253
+ }
254
+ const rangeSpecs = rangesText.split(",").filter(Boolean);
255
+ for (const spec of rangeSpecs) {
256
+ const [s, e] = spec.split("-").map((v) => parseInt(v, 10));
257
+ if (!Number.isFinite(s) || !Number.isFinite(e) || e < s) {
258
+ throw new LLMResponseParseError(`Line ${ctx.lineNumber}: invalid range '${spec}'`);
259
+ }
260
+ const arr = map.get(path4) ?? [];
261
+ arr.push([s, e]);
262
+ map.set(path4, arr);
263
+ }
264
+ }
265
+ return map;
266
+ }
267
+ };
268
+
269
+ // tools/warp_grep/tools/read.ts
270
+ async function toolRead(provider, args) {
271
+ const res = await provider.read({ path: args.path, start: args.start, end: args.end });
272
+ return res.lines.join("\n");
273
+ }
274
+
275
+ // tools/warp_grep/tools/analyse.ts
276
+ async function toolAnalyse(provider, args) {
277
+ const list = await provider.analyse({
278
+ path: args.path,
279
+ pattern: args.pattern ?? null,
280
+ maxResults: args.maxResults ?? 100,
281
+ maxDepth: args.maxDepth ?? 2
282
+ });
283
+ if (!list.length) return "empty";
284
+ return list.map((e) => `${" ".repeat(e.depth)}- ${e.type === "dir" ? "[D]" : "[F]"} ${e.name}`).join("\n");
285
+ }
286
+
287
+ // tools/utils/resilience.ts
288
+ var DEFAULT_RETRY_CONFIG = {
289
+ maxRetries: 3,
290
+ initialDelay: 1e3,
291
+ maxDelay: 3e4,
292
+ backoffMultiplier: 2,
293
+ retryableErrors: ["ECONNREFUSED", "ETIMEDOUT", "ENOTFOUND"]
294
+ };
295
+ async function fetchWithRetry(url, options, retryConfig = {}) {
296
+ const {
297
+ maxRetries = DEFAULT_RETRY_CONFIG.maxRetries,
298
+ initialDelay = DEFAULT_RETRY_CONFIG.initialDelay,
299
+ maxDelay = DEFAULT_RETRY_CONFIG.maxDelay,
300
+ backoffMultiplier = DEFAULT_RETRY_CONFIG.backoffMultiplier,
301
+ retryableErrors = DEFAULT_RETRY_CONFIG.retryableErrors,
302
+ onRetry
303
+ } = retryConfig;
304
+ let lastError = null;
305
+ let delay = initialDelay;
306
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
307
+ try {
308
+ const response = await fetch(url, options);
309
+ if (response.status === 429 || response.status === 503) {
310
+ if (attempt < maxRetries) {
311
+ const retryAfter = response.headers.get("Retry-After");
312
+ const waitTime = retryAfter ? parseInt(retryAfter) * 1e3 : Math.min(delay, maxDelay);
313
+ const error = new Error(`HTTP ${response.status}: Retrying after ${waitTime}ms`);
314
+ if (onRetry) {
315
+ onRetry(attempt + 1, error);
316
+ }
317
+ await sleep(waitTime);
318
+ delay *= backoffMultiplier;
319
+ continue;
320
+ }
321
+ }
322
+ return response;
323
+ } catch (error) {
324
+ lastError = error;
325
+ const isRetryable = retryableErrors.some(
326
+ (errType) => lastError?.message?.includes(errType)
327
+ );
328
+ if (!isRetryable || attempt === maxRetries) {
329
+ throw lastError;
330
+ }
331
+ const waitTime = Math.min(delay, maxDelay);
332
+ if (onRetry) {
333
+ onRetry(attempt + 1, lastError);
334
+ }
335
+ await sleep(waitTime);
336
+ delay *= backoffMultiplier;
337
+ }
338
+ }
339
+ throw lastError || new Error("Max retries exceeded");
340
+ }
341
+ async function withTimeout(promise, timeoutMs, errorMessage) {
342
+ let timeoutId;
343
+ const timeoutPromise = new Promise((_, reject) => {
344
+ timeoutId = setTimeout(() => {
345
+ reject(new Error(errorMessage || `Operation timed out after ${timeoutMs}ms`));
346
+ }, timeoutMs);
347
+ });
348
+ try {
349
+ const result = await Promise.race([promise, timeoutPromise]);
350
+ clearTimeout(timeoutId);
351
+ return result;
352
+ } catch (error) {
353
+ clearTimeout(timeoutId);
354
+ throw error;
355
+ }
356
+ }
357
+ function sleep(ms) {
358
+ return new Promise((resolve) => setTimeout(resolve, ms));
359
+ }
360
+
361
+ // tools/warp_grep/agent/formatter.ts
362
+ var ToolOutputFormatter = class {
363
+ format(toolName, args, output, options = {}) {
364
+ const name = (toolName ?? "").trim();
365
+ if (!name) {
366
+ return "";
367
+ }
368
+ const payload = output?.toString?.()?.trim?.() ?? "";
369
+ const isError = Boolean(options.isError);
370
+ const safeArgs = args ?? {};
371
+ if (!payload && !isError) {
372
+ return "";
373
+ }
374
+ switch (name) {
375
+ case "read":
376
+ return this.formatRead(safeArgs, payload, isError);
377
+ case "analyse":
378
+ return this.formatAnalyse(safeArgs, payload, isError);
379
+ case "grep":
380
+ return this.formatGrep(safeArgs, payload, isError);
381
+ default:
382
+ return payload ? `<tool_output>
383
+ ${payload}
384
+ </tool_output>` : "";
385
+ }
386
+ }
387
+ formatRead(args, payload, isError) {
388
+ if (isError) {
389
+ return payload;
390
+ }
391
+ const path4 = this.asString(args.path) || "...";
392
+ return `<file path="${path4}">
393
+ ${payload}
394
+ </file>`;
395
+ }
396
+ formatAnalyse(args, payload, isError) {
397
+ const path4 = this.asString(args.path) || ".";
398
+ if (isError) {
399
+ return `<analyse_results path="${path4}" status="error">
400
+ ${payload}
401
+ </analyse_results>`;
402
+ }
403
+ return `<analyse_results path="${path4}">
404
+ ${payload}
405
+ </analyse_results>`;
406
+ }
407
+ formatGrep(args, payload, isError) {
408
+ const pattern = this.asString(args.pattern);
409
+ const path4 = this.asString(args.path);
410
+ const attributes = [];
411
+ if (pattern !== void 0) {
412
+ attributes.push(`pattern="${pattern}"`);
413
+ }
414
+ if (path4 !== void 0) {
415
+ attributes.push(`path="${path4}"`);
416
+ }
417
+ if (isError) {
418
+ attributes.push('status="error"');
419
+ }
420
+ const attrText = attributes.length ? ` ${attributes.join(" ")}` : "";
421
+ return `<grep_output${attrText}>
422
+ ${payload}
423
+ </grep_output>`;
424
+ }
425
+ asString(value) {
426
+ if (value === null || value === void 0) {
427
+ return void 0;
428
+ }
429
+ return String(value);
430
+ }
431
+ };
432
+ var sharedFormatter = new ToolOutputFormatter();
433
+ function formatAgentToolOutput(toolName, args, output, options = {}) {
434
+ return sharedFormatter.format(toolName, args, output, options);
435
+ }
436
+
437
+ // tools/warp_grep/agent/grep_helpers.ts
438
+ var GrepState = class {
439
+ seenLines = /* @__PURE__ */ new Set();
440
+ isNew(path4, lineNumber) {
441
+ const key = this.makeKey(path4, lineNumber);
442
+ return !this.seenLines.has(key);
443
+ }
444
+ add(path4, lineNumber) {
445
+ this.seenLines.add(this.makeKey(path4, lineNumber));
446
+ }
447
+ makeKey(path4, lineNumber) {
448
+ return `${path4}:${lineNumber}`;
449
+ }
450
+ };
451
+ var MAX_GREP_OUTPUT_CHARS_PER_TURN = 6e4;
452
+ function extractMatchFields(payload) {
453
+ const text = payload.replace(/\r?\n$/, "");
454
+ if (!text || text.startsWith("[error]")) {
455
+ return null;
456
+ }
457
+ const firstSep = text.indexOf(":");
458
+ if (firstSep === -1) {
459
+ return null;
460
+ }
461
+ let filePath = text.slice(0, firstSep).trim();
462
+ if (!filePath) {
463
+ return null;
464
+ }
465
+ if (filePath.startsWith("./") || filePath.startsWith(".\\")) {
466
+ filePath = filePath.slice(2);
467
+ }
468
+ const remainder = text.slice(firstSep + 1);
469
+ const secondSep = remainder.indexOf(":");
470
+ if (secondSep === -1) {
471
+ return null;
472
+ }
473
+ const linePart = remainder.slice(0, secondSep);
474
+ const lineNumber = Number.parseInt(linePart, 10);
475
+ if (!Number.isInteger(lineNumber) || lineNumber <= 0) {
476
+ return null;
477
+ }
478
+ let contentSegment = remainder.slice(secondSep + 1);
479
+ const columnSep = contentSegment.indexOf(":");
480
+ if (columnSep !== -1 && /^\d+$/.test(contentSegment.slice(0, columnSep))) {
481
+ contentSegment = contentSegment.slice(columnSep + 1);
482
+ }
483
+ const content = contentSegment.trim();
484
+ if (!content) {
485
+ return null;
486
+ }
487
+ return { path: filePath, lineNumber, content };
488
+ }
489
+ function parseAndFilterGrepOutput(rawOutput, state) {
490
+ const matches = [];
491
+ if (typeof rawOutput !== "string" || !rawOutput.trim()) {
492
+ return matches;
493
+ }
494
+ for (const line of rawOutput.split(/\r?\n/)) {
495
+ const fields = extractMatchFields(line);
496
+ if (!fields) {
497
+ continue;
498
+ }
499
+ if (state.isNew(fields.path, fields.lineNumber)) {
500
+ matches.push(fields);
501
+ state.add(fields.path, fields.lineNumber);
502
+ }
503
+ }
504
+ return matches;
505
+ }
506
+ function truncateOutput(payload, maxChars) {
507
+ if (payload.length <= maxChars) {
508
+ return payload;
509
+ }
510
+ const note = "... (output truncated)";
511
+ const available = maxChars - note.length - 1;
512
+ if (available <= 0) {
513
+ return note;
514
+ }
515
+ if (payload.length <= available) {
516
+ return `${payload.slice(0, available).replace(/\n$/, "")}
517
+ ${note}`;
518
+ }
519
+ const core = payload.slice(0, Math.max(0, available - 1));
520
+ const trimmed = core.replace(/\n$/, "").replace(/\s+$/, "");
521
+ const snippet = trimmed ? `${trimmed}\u2026` : "\u2026";
522
+ return `${snippet}
523
+ ${note}`;
524
+ }
525
+ function formatTurnGrepOutput(matches, maxChars = MAX_GREP_OUTPUT_CHARS_PER_TURN) {
526
+ if (!matches || matches.length === 0) {
527
+ return "No new matches found.";
528
+ }
529
+ const matchesByFile = /* @__PURE__ */ new Map();
530
+ for (const match of matches) {
531
+ if (!matchesByFile.has(match.path)) {
532
+ matchesByFile.set(match.path, []);
533
+ }
534
+ matchesByFile.get(match.path).push(match);
535
+ }
536
+ const lines = [];
537
+ const sortedPaths = Array.from(matchesByFile.keys()).sort();
538
+ sortedPaths.forEach((filePath, index) => {
539
+ if (index > 0) {
540
+ lines.push("");
541
+ }
542
+ lines.push(filePath);
543
+ const sortedMatches = matchesByFile.get(filePath).slice().sort((a, b) => a.lineNumber - b.lineNumber);
544
+ for (const match of sortedMatches) {
545
+ lines.push(`${match.lineNumber}:${match.content}`);
546
+ }
547
+ });
548
+ return truncateOutput(lines.join("\n"), maxChars);
549
+ }
550
+
551
+ // tools/warp_grep/tools/finish.ts
552
+ async function readFinishFiles(repoRoot, files, reader) {
553
+ const out = [];
554
+ for (const f of files) {
555
+ const ranges = mergeRanges(f.lines);
556
+ const chunks = [];
557
+ for (const [s, e] of ranges) {
558
+ const lines = await reader(f.path, s, e);
559
+ chunks.push(lines.join("\n"));
560
+ }
561
+ out.push({ path: f.path, ranges, content: chunks.join("\n") });
562
+ }
563
+ return out;
564
+ }
565
+ function mergeRanges(ranges) {
566
+ if (!ranges.length) return [];
567
+ const sorted = [...ranges].sort((a, b) => a[0] - b[0]);
568
+ const merged = [];
569
+ let [cs, ce] = sorted[0];
570
+ for (let i = 1; i < sorted.length; i++) {
571
+ const [s, e] = sorted[i];
572
+ if (s <= ce + 1) {
573
+ ce = Math.max(ce, e);
574
+ } else {
575
+ merged.push([cs, ce]);
576
+ cs = s;
577
+ ce = e;
578
+ }
579
+ }
580
+ merged.push([cs, ce]);
581
+ return merged;
582
+ }
583
+
584
+ // tools/warp_grep/agent/runner.ts
585
+ var import_path = __toESM(require("path"), 1);
586
+ var import_promises = __toESM(require("fs/promises"), 1);
587
+ var parser = new LLMResponseParser();
588
+ async function buildInitialState(repoRoot, query) {
589
+ try {
590
+ const entries = await import_promises.default.readdir(repoRoot, { withFileTypes: true });
591
+ const dirs = entries.filter((e) => e.isDirectory()).map((d) => d.name).slice(0, 50);
592
+ const files = entries.filter((e) => e.isFile()).map((f) => f.name).slice(0, 50);
593
+ const parts = [
594
+ `<repo_root>${repoRoot}</repo_root>`,
595
+ `<top_dirs>${dirs.join(", ")}</top_dirs>`,
596
+ `<top_files>${files.join(", ")}</top_files>`
597
+ ];
598
+ return parts.join("\n");
599
+ } catch {
600
+ return `<repo_root>${repoRoot}</repo_root>`;
601
+ }
602
+ }
603
+ async function callModel(messages, model, apiKey) {
604
+ const api = "https://api.morphllm.com/v1/chat/completions";
605
+ const fetchPromise = fetchWithRetry(
606
+ api,
607
+ {
608
+ method: "POST",
609
+ headers: {
610
+ "Content-Type": "application/json",
611
+ Authorization: `Bearer ${apiKey || process.env.MORPH_API_KEY || ""}`
612
+ },
613
+ body: JSON.stringify({
614
+ model,
615
+ temperature: 0,
616
+ max_tokens: 1024,
617
+ messages
618
+ })
619
+ },
620
+ {}
621
+ );
622
+ const resp = await withTimeout(fetchPromise, AGENT_CONFIG.TIMEOUT_MS, "morph-warp-grep request timed out");
623
+ if (!resp.ok) {
624
+ const t = await resp.text();
625
+ throw new Error(`morph-warp-grep error ${resp.status}: ${t}`);
626
+ }
627
+ const data = await resp.json();
628
+ const content = data?.choices?.[0]?.message?.content;
629
+ if (!content || typeof content !== "string") {
630
+ throw new Error("Invalid response from model");
631
+ }
632
+ return content;
633
+ }
634
+ async function runWarpGrep(config) {
635
+ const repoRoot = import_path.default.resolve(config.repoRoot || process.cwd());
636
+ const messages = [];
637
+ const systemMessage = { role: "system", content: getSystemPrompt() };
638
+ messages.push(systemMessage);
639
+ const queryContent = `<query>${config.query}</query>`;
640
+ messages.push({ role: "user", content: queryContent });
641
+ const initialState = await buildInitialState(repoRoot, config.query);
642
+ messages.push({ role: "user", content: initialState });
643
+ const maxRounds = AGENT_CONFIG.MAX_ROUNDS;
644
+ const model = config.model || DEFAULT_MODEL;
645
+ const provider = config.provider;
646
+ const errors = [];
647
+ const grepState = new GrepState();
648
+ let finishMeta;
649
+ let terminationReason = "terminated";
650
+ for (let round = 1; round <= maxRounds; round += 1) {
651
+ const assistantContent = await callModel(messages, model, config.apiKey).catch((e) => {
652
+ errors.push({ message: e instanceof Error ? e.message : String(e) });
653
+ return "";
654
+ });
655
+ if (!assistantContent) break;
656
+ messages.push({ role: "assistant", content: assistantContent });
657
+ let toolCalls = [];
658
+ try {
659
+ toolCalls = parser.parse(assistantContent);
660
+ } catch (e) {
661
+ errors.push({ message: e instanceof Error ? e.message : String(e) });
662
+ terminationReason = "terminated";
663
+ break;
664
+ }
665
+ if (toolCalls.length === 0) {
666
+ errors.push({ message: "No tool calls produced by the model." });
667
+ terminationReason = "terminated";
668
+ break;
669
+ }
670
+ const finishCalls = toolCalls.filter((c) => c.name === "finish");
671
+ const grepCalls = toolCalls.filter((c) => c.name === "grep");
672
+ const analyseCalls = toolCalls.filter((c) => c.name === "analyse");
673
+ const readCalls = toolCalls.filter((c) => c.name === "read");
674
+ const formatted = [];
675
+ const otherPromises = [];
676
+ for (const c of analyseCalls) {
677
+ const args = c.arguments ?? {};
678
+ otherPromises.push(
679
+ toolAnalyse(provider, args).then(
680
+ (p) => formatAgentToolOutput("analyse", args, p, { isError: false }),
681
+ (err) => formatAgentToolOutput("analyse", args, String(err), { isError: true })
682
+ )
683
+ );
684
+ }
685
+ for (const c of readCalls) {
686
+ const args = c.arguments ?? {};
687
+ otherPromises.push(
688
+ toolRead(provider, args).then(
689
+ (p) => formatAgentToolOutput("read", args, p, { isError: false }),
690
+ (err) => formatAgentToolOutput("read", args, String(err), { isError: true })
691
+ )
692
+ );
693
+ }
694
+ const otherResults = await Promise.all(otherPromises);
695
+ formatted.push(...otherResults);
696
+ for (const c of grepCalls) {
697
+ const args = c.arguments ?? {};
698
+ try {
699
+ const grepRes = await provider.grep({ pattern: args.pattern, path: args.path });
700
+ const rawOutput = Array.isArray(grepRes.lines) ? grepRes.lines.join("\n") : "";
701
+ const newMatches = parseAndFilterGrepOutput(rawOutput, grepState);
702
+ let formattedPayload = formatTurnGrepOutput(newMatches);
703
+ if (formattedPayload === "No new matches found.") {
704
+ formattedPayload = "no new matches";
705
+ }
706
+ formatted.push(formatAgentToolOutput("grep", args, formattedPayload, { isError: false }));
707
+ } catch (err) {
708
+ formatted.push(formatAgentToolOutput("grep", args, String(err), { isError: true }));
709
+ }
710
+ }
711
+ if (formatted.length > 0) {
712
+ messages.push({ role: "user", content: formatted.join("\n") });
713
+ }
714
+ if (finishCalls.length) {
715
+ const fc = finishCalls[0];
716
+ const files = fc.arguments?.files ?? [];
717
+ finishMeta = { files };
718
+ terminationReason = "completed";
719
+ break;
720
+ }
721
+ }
722
+ if (terminationReason !== "completed" || !finishMeta) {
723
+ return { terminationReason, messages, errors };
724
+ }
725
+ const parts = ["Relevant context found:"];
726
+ for (const f of finishMeta.files) {
727
+ const ranges = f.lines.map(([s, e]) => `${s}-${e}`).join(", ");
728
+ parts.push(`- ${f.path}: ${ranges}`);
729
+ }
730
+ const payload = parts.join("\n");
731
+ const resolved = await readFinishFiles(
732
+ repoRoot,
733
+ finishMeta.files,
734
+ async (p, s, e) => {
735
+ const rr = await provider.read({ path: p, start: s, end: e });
736
+ return rr.lines.map((l) => {
737
+ const idx = l.indexOf("|");
738
+ return idx >= 0 ? l.slice(idx + 1) : l;
739
+ });
740
+ }
741
+ );
742
+ return {
743
+ terminationReason: "completed",
744
+ messages,
745
+ finish: { payload, metadata: finishMeta, resolved }
746
+ };
747
+ }
748
+
749
+ // tools/warp_grep/providers/local.ts
750
+ var import_promises3 = __toESM(require("fs/promises"), 1);
751
+ var import_path3 = __toESM(require("path"), 1);
752
+
753
+ // tools/warp_grep/utils/ripgrep.ts
754
+ var import_child_process = require("child_process");
755
+ function runRipgrep(args, opts) {
756
+ return new Promise((resolve) => {
757
+ const child = (0, import_child_process.spawn)("rg", args, {
758
+ cwd: opts?.cwd,
759
+ env: { ...process.env, ...opts?.env || {} },
760
+ stdio: ["ignore", "pipe", "pipe"]
761
+ });
762
+ let stdout = "";
763
+ let stderr = "";
764
+ child.stdout.on("data", (d) => stdout += d.toString());
765
+ child.stderr.on("data", (d) => stderr += d.toString());
766
+ child.on("close", (code) => {
767
+ resolve({ stdout, stderr, exitCode: typeof code === "number" ? code : -1 });
768
+ });
769
+ child.on("error", () => {
770
+ resolve({ stdout: "", stderr: "Failed to spawn ripgrep (rg). Ensure it is installed.", exitCode: -1 });
771
+ });
772
+ });
773
+ }
774
+
775
+ // tools/warp_grep/utils/paths.ts
776
+ var import_fs = __toESM(require("fs"), 1);
777
+ var import_path2 = __toESM(require("path"), 1);
778
+ function resolveUnderRepo(repoRoot, targetPath) {
779
+ const absRoot = import_path2.default.resolve(repoRoot);
780
+ const resolved = import_path2.default.resolve(absRoot, targetPath);
781
+ ensureWithinRepo(absRoot, resolved);
782
+ return resolved;
783
+ }
784
+ function ensureWithinRepo(repoRoot, absTarget) {
785
+ const rel = import_path2.default.relative(import_path2.default.resolve(repoRoot), import_path2.default.resolve(absTarget));
786
+ if (rel.startsWith("..") || import_path2.default.isAbsolute(rel)) {
787
+ throw new Error(`Path outside repository root: ${absTarget}`);
788
+ }
789
+ }
790
+ function toRepoRelative(repoRoot, absPath) {
791
+ return import_path2.default.relative(import_path2.default.resolve(repoRoot), import_path2.default.resolve(absPath));
792
+ }
793
+ function isSymlink(p) {
794
+ try {
795
+ const st = import_fs.default.lstatSync(p);
796
+ return st.isSymbolicLink();
797
+ } catch {
798
+ return false;
799
+ }
800
+ }
801
+ function isTextualFile(filePath, maxBytes = 2e6) {
802
+ try {
803
+ const st = import_fs.default.statSync(filePath);
804
+ if (!st.isFile()) return false;
805
+ if (st.size > maxBytes) return false;
806
+ const fd = import_fs.default.openSync(filePath, "r");
807
+ const buf = Buffer.alloc(512);
808
+ const read = import_fs.default.readSync(fd, buf, 0, buf.length, 0);
809
+ import_fs.default.closeSync(fd);
810
+ for (let i = 0; i < read; i++) {
811
+ const c = buf[i];
812
+ if (c === 0) return false;
813
+ }
814
+ return true;
815
+ } catch {
816
+ return false;
817
+ }
818
+ }
819
+
820
+ // tools/warp_grep/utils/files.ts
821
+ var import_promises2 = __toESM(require("fs/promises"), 1);
822
+ async function readAllLines(filePath) {
823
+ const content = await import_promises2.default.readFile(filePath, "utf8");
824
+ return content.split(/\r?\n/);
825
+ }
826
+
827
+ // tools/warp_grep/providers/local.ts
828
+ var LocalRipgrepProvider = class {
829
+ constructor(repoRoot, excludes = DEFAULT_EXCLUDES) {
830
+ this.repoRoot = repoRoot;
831
+ this.excludes = excludes;
832
+ }
833
+ async grep(params) {
834
+ const abs = resolveUnderRepo(this.repoRoot, params.path);
835
+ const stat = await import_promises3.default.stat(abs).catch(() => null);
836
+ if (!stat) return { lines: [] };
837
+ const targetArg = abs === import_path3.default.resolve(this.repoRoot) ? "." : toRepoRelative(this.repoRoot, abs);
838
+ const args = [
839
+ "--no-config",
840
+ "--no-heading",
841
+ "--with-filename",
842
+ "--line-number",
843
+ "--color=never",
844
+ "--trim",
845
+ "--max-columns=400",
846
+ ...this.excludes.flatMap((e) => ["-g", `!${e}`]),
847
+ params.pattern,
848
+ targetArg || "."
849
+ ];
850
+ const res = await runRipgrep(args, { cwd: this.repoRoot });
851
+ if (res.exitCode === -1) {
852
+ throw new Error(res.stderr || "ripgrep (rg) execution failed.");
853
+ }
854
+ if (res.exitCode !== 0 && res.exitCode !== 1) {
855
+ throw new Error(res.stderr || `ripgrep failed with code ${res.exitCode}`);
856
+ }
857
+ const lines = (res.stdout || "").trim().split(/\r?\n/).filter((l) => l.length > 0);
858
+ return { lines };
859
+ }
860
+ async glob(params) {
861
+ const abs = resolveUnderRepo(this.repoRoot, params.path);
862
+ const targetArg = abs === import_path3.default.resolve(this.repoRoot) ? "." : toRepoRelative(this.repoRoot, abs);
863
+ const args = [
864
+ "--no-config",
865
+ "--files",
866
+ "-g",
867
+ params.pattern,
868
+ ...this.excludes.flatMap((e) => ["-g", `!${e}`]),
869
+ targetArg || "."
870
+ ];
871
+ const res = await runRipgrep(args, { cwd: this.repoRoot });
872
+ if (res.exitCode === -1) {
873
+ throw new Error(res.stderr || "ripgrep (rg) execution failed.");
874
+ }
875
+ const files = (res.stdout || "").trim().split(/\r?\n/).filter((l) => l.length > 0);
876
+ return { files };
877
+ }
878
+ async read(params) {
879
+ const abs = resolveUnderRepo(this.repoRoot, params.path);
880
+ const stat = await import_promises3.default.stat(abs).catch(() => null);
881
+ if (!stat || !stat.isFile()) {
882
+ throw new Error(`Path is not a file: ${params.path}`);
883
+ }
884
+ if (isSymlink(abs)) {
885
+ throw new Error(`Refusing to read symlink: ${params.path}`);
886
+ }
887
+ if (!isTextualFile(abs)) {
888
+ throw new Error(`Non-text or too-large file: ${params.path}`);
889
+ }
890
+ const lines = await readAllLines(abs);
891
+ const total = lines.length;
892
+ const s = params.start ?? 1;
893
+ const e = Math.min(params.end ?? total, total);
894
+ if (s > total && total > 0) {
895
+ throw new Error(`start ${s} exceeds file length (${total})`);
896
+ }
897
+ const out = [];
898
+ for (let i = s; i <= e; i += 1) {
899
+ const content = lines[i - 1] ?? "";
900
+ out.push(`${i}|${content}`);
901
+ }
902
+ return { lines: out };
903
+ }
904
+ async analyse(params) {
905
+ const abs = resolveUnderRepo(this.repoRoot, params.path);
906
+ const stat = await import_promises3.default.stat(abs).catch(() => null);
907
+ if (!stat || !stat.isDirectory()) {
908
+ return [];
909
+ }
910
+ const maxResults = params.maxResults ?? 100;
911
+ const maxDepth = params.maxDepth ?? 2;
912
+ const regex = params.pattern ? new RegExp(params.pattern) : null;
913
+ const results = [];
914
+ async function walk(dir, depth) {
915
+ if (depth > maxDepth || results.length >= maxResults) return;
916
+ const entries = await import_promises3.default.readdir(dir, { withFileTypes: true });
917
+ for (const entry of entries) {
918
+ const full = import_path3.default.join(dir, entry.name);
919
+ const rel = toRepoRelative(abs, full).replace(/^[.][/\\]?/, "");
920
+ if (DEFAULT_EXCLUDES.some((ex) => rel.split(import_path3.default.sep).includes(ex))) continue;
921
+ if (regex && !regex.test(entry.name)) continue;
922
+ if (results.length >= maxResults) break;
923
+ results.push({
924
+ name: entry.name,
925
+ path: toRepoRelative(import_path3.default.resolve(""), full),
926
+ // relative display
927
+ type: entry.isDirectory() ? "dir" : "file",
928
+ depth
929
+ });
930
+ if (entry.isDirectory()) {
931
+ await walk(full, depth + 1);
932
+ }
933
+ }
934
+ }
935
+ await walk(abs, 0);
936
+ return results;
937
+ }
938
+ };
939
+
940
+ // tools/warp_grep/providers/command.ts
941
+ var CommandExecProvider = class {
942
+ constructor(opts) {
943
+ this.opts = opts;
944
+ }
945
+ map(path4) {
946
+ return this.opts.pathMap ? this.opts.pathMap(path4) : path4;
947
+ }
948
+ async grep(params) {
949
+ const remotePath = this.map(params.path);
950
+ const args = [
951
+ "--no-config",
952
+ "--no-heading",
953
+ "--with-filename",
954
+ "--line-number",
955
+ "--color=never",
956
+ "--trim",
957
+ "--max-columns=400",
958
+ ...(this.opts.excludes ?? DEFAULT_EXCLUDES).flatMap((e) => ["-g", `!${e}`]),
959
+ params.pattern,
960
+ remotePath || "."
961
+ ];
962
+ const res = await this.opts.run("rg", args, { cwd: this.opts.cwd, env: this.opts.env });
963
+ if (res.exitCode === -1) throw new Error(res.stderr || "ripgrep execution failed");
964
+ if (res.exitCode !== 0 && res.exitCode !== 1) throw new Error(res.stderr || `ripgrep failed (${res.exitCode})`);
965
+ const lines = (res.stdout || "").trim().split(/\r?\n/).filter((l) => l.length > 0);
966
+ return { lines };
967
+ }
968
+ async glob(params) {
969
+ const remotePath = this.map(params.path);
970
+ const args = [
971
+ "--no-config",
972
+ "--files",
973
+ "-g",
974
+ params.pattern,
975
+ ...(this.opts.excludes ?? DEFAULT_EXCLUDES).flatMap((e) => ["-g", `!${e}`]),
976
+ remotePath || "."
977
+ ];
978
+ const res = await this.opts.run("rg", args, { cwd: this.opts.cwd, env: this.opts.env });
979
+ if (res.exitCode === -1) throw new Error(res.stderr || "ripgrep execution failed");
980
+ const files = (res.stdout || "").trim().split(/\r?\n/).filter((l) => l.length > 0);
981
+ return { files };
982
+ }
983
+ async read(params) {
984
+ const remotePath = this.map(params.path);
985
+ const rc = this.opts.readCommand ? this.opts.readCommand(remotePath, params.start, params.end) : { cmd: "sed", args: ["-n", `${params.start ?? 1},${params.end ?? 1e6}p`, remotePath] };
986
+ const res = await this.opts.run(rc.cmd, rc.args, { cwd: this.opts.cwd, env: this.opts.env });
987
+ if (res.exitCode !== 0) throw new Error(res.stderr || `read failed (${res.exitCode})`);
988
+ const text = res.stdout || "";
989
+ const lines = text.split(/\r?\n/).map((line, idx) => `${(params.start ?? 1) + idx}|${line}`);
990
+ return { lines: lines.filter((l) => l !== `${(params.start ?? 1) + (lines.length - 1)}|`) };
991
+ }
992
+ async analyse(params) {
993
+ const target = this.map(params.path);
994
+ const pattern = params.pattern ?? "*";
995
+ const files = await this.glob({ pattern, path: target }).catch(() => ({ files: [] }));
996
+ return files.files.slice(0, params.maxResults ?? 100).map((f) => ({
997
+ name: f.split("/").pop() || f,
998
+ path: f,
999
+ type: f.endsWith("/") ? "dir" : "file",
1000
+ depth: 0
1001
+ }));
1002
+ }
1003
+ };
1004
+
1005
+ // tools/warp_grep/openai.ts
1006
+ var import_zod = require("zod");
1007
+ var INPUT_SCHEMA = import_zod.z.object({
1008
+ query: import_zod.z.string().describe("Free-form repository question")
1009
+ });
1010
+ function createMorphWarpGrepTool(config) {
1011
+ const tool2 = {
1012
+ type: "function",
1013
+ function: {
1014
+ name: "morph-warp-grep",
1015
+ description: "A fast and accurate tool that can search for all relevant context in a codebase. You must use this tool to save time and avoid context pollution.",
1016
+ parameters: {
1017
+ type: "object",
1018
+ properties: {
1019
+ query: { type: "string", description: "Free-form repository question" }
1020
+ },
1021
+ required: ["query"]
1022
+ }
1023
+ }
1024
+ };
1025
+ return Object.assign(tool2, {
1026
+ execute: async (input) => {
1027
+ const parsed = INPUT_SCHEMA.parse(typeof input === "string" ? JSON.parse(input) : input);
1028
+ const provider = config.provider ?? new LocalRipgrepProvider(config.repoRoot, config.excludes);
1029
+ const result = await runWarpGrep({
1030
+ query: parsed.query,
1031
+ repoRoot: config.repoRoot,
1032
+ provider,
1033
+ excludes: config.excludes,
1034
+ includes: config.includes,
1035
+ debug: config.debug ?? false,
1036
+ apiKey: config.apiKey
1037
+ });
1038
+ if (result.terminationReason !== "completed" || !result.finish?.metadata) {
1039
+ return { success: false, error: "Search did not complete", messages: result.messages };
1040
+ }
1041
+ const contexts = (result.finish.resolved || []).map((r) => ({
1042
+ file: r.path,
1043
+ content: r.content
1044
+ }));
1045
+ return { success: true, contexts, summary: result.finish.payload };
1046
+ }
1047
+ });
1048
+ }
1049
+
1050
+ // tools/warp_grep/anthropic.ts
1051
+ var import_zod2 = require("zod");
1052
+ var INPUT_SCHEMA2 = import_zod2.z.object({
1053
+ query: import_zod2.z.string().describe("Free-form repository question")
1054
+ });
1055
+ function createMorphWarpGrepTool2(config) {
1056
+ const tool2 = {
1057
+ name: "morph-warp-grep",
1058
+ description: "A fast and accurate tool that can search for all relevant context in a codebase. You must use this tool to save time and avoid context pollution.",
1059
+ input_schema: {
1060
+ type: "object",
1061
+ properties: {
1062
+ query: { type: "string", description: "Free-form repository question" }
1063
+ },
1064
+ required: ["query"]
1065
+ }
1066
+ };
1067
+ return Object.assign(tool2, {
1068
+ execute: async (input) => {
1069
+ const parsed = INPUT_SCHEMA2.parse(typeof input === "string" ? JSON.parse(input) : input);
1070
+ const provider = config.provider ?? new LocalRipgrepProvider(config.repoRoot, config.excludes);
1071
+ const result = await runWarpGrep({
1072
+ query: parsed.query,
1073
+ repoRoot: config.repoRoot,
1074
+ provider,
1075
+ excludes: config.excludes,
1076
+ includes: config.includes,
1077
+ debug: config.debug ?? false,
1078
+ apiKey: config.apiKey
1079
+ });
1080
+ if (result.terminationReason !== "completed" || !result.finish?.metadata) {
1081
+ return { success: false, error: "Search did not complete", messages: result.messages };
1082
+ }
1083
+ const contexts = (result.finish.resolved || []).map((r) => ({
1084
+ file: r.path,
1085
+ content: r.content
1086
+ }));
1087
+ return { success: true, contexts, summary: result.finish.payload };
1088
+ }
1089
+ });
1090
+ }
1091
+
1092
+ // tools/warp_grep/vercel.ts
1093
+ var import_ai = require("ai");
1094
+ var import_zod3 = require("zod");
1095
+ function createMorphWarpGrepTool3(config) {
1096
+ const schema = import_zod3.z.object({
1097
+ query: import_zod3.z.string().describe("Free-form repository question")
1098
+ });
1099
+ return (0, import_ai.tool)({
1100
+ description: "A fast and accurate tool that can search for all relevant context in a codebase. You must use this tool to save time and avoid context pollution.",
1101
+ inputSchema: schema,
1102
+ execute: async (params) => {
1103
+ const provider = config.provider ?? new LocalRipgrepProvider(config.repoRoot, config.excludes);
1104
+ const result = await runWarpGrep({
1105
+ query: params.query,
1106
+ repoRoot: config.repoRoot,
1107
+ provider,
1108
+ excludes: config.excludes,
1109
+ includes: config.includes,
1110
+ debug: config.debug ?? false,
1111
+ apiKey: config.apiKey
1112
+ });
1113
+ if (result.terminationReason !== "completed" || !result.finish?.metadata) {
1114
+ return { success: false, error: "Search did not complete", messages: result.messages };
1115
+ }
1116
+ const contexts = (result.finish.resolved || []).map((r) => ({
1117
+ file: r.path,
1118
+ content: r.content
1119
+ }));
1120
+ return { success: true, contexts, summary: result.finish.payload };
1121
+ }
1122
+ });
1123
+ }
1124
+ // Annotate the CommonJS export names for ESM import in node:
1125
+ 0 && (module.exports = {
1126
+ AGENT_CONFIG,
1127
+ CommandExecProvider,
1128
+ DEFAULT_EXCLUDES,
1129
+ DEFAULT_MODEL,
1130
+ LocalRipgrepProvider,
1131
+ createAnthropicWarpGrepTool,
1132
+ createOpenAIWarpGrepTool,
1133
+ createVercelWarpGrepTool,
1134
+ runWarpGrep
1135
+ });
1136
+ //# sourceMappingURL=index.cjs.map