@morphllm/morphsdk 0.2.102 → 0.2.103
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.
- package/dist/chunk-2MAUPERG.js +129 -0
- package/dist/chunk-2MAUPERG.js.map +1 -0
- package/dist/{chunk-QH4BSXOD.js → chunk-4CZPXV6R.js} +8 -7
- package/dist/chunk-4CZPXV6R.js.map +1 -0
- package/dist/{chunk-AIXF4GQC.js → chunk-AFLEE2PO.js} +2 -2
- package/dist/{chunk-CP4NZGRY.js → chunk-EMMSRY32.js} +3 -3
- package/dist/chunk-EMMSRY32.js.map +1 -0
- package/dist/{chunk-QZNGKOCZ.js → chunk-HDRLLCAD.js} +4 -4
- package/dist/{chunk-BKIM7SNY.js → chunk-I3IN742Q.js} +4 -4
- package/dist/{chunk-7UYDS6OX.js → chunk-KQP6ZPYB.js} +4 -4
- package/dist/{chunk-OTPYEYMZ.js → chunk-MY4OU4ON.js} +2 -2
- package/dist/{chunk-UBX7QYBD.js → chunk-O5DA5V5S.js} +4 -4
- package/dist/{chunk-GJU7UOFL.js → chunk-OUEJ6XEO.js} +4 -4
- package/dist/{chunk-L5WXPMCH.js → chunk-QUIGATZE.js} +2 -2
- package/dist/chunk-TLC3QKE6.js +114 -0
- package/dist/chunk-TLC3QKE6.js.map +1 -0
- package/dist/{chunk-4J6NACK2.js → chunk-Y2OTK5WC.js} +15 -15
- package/dist/{chunk-4KMBU6T3.js → chunk-YJZP5ZL5.js} +4 -4
- package/dist/{chunk-76DJEQEP.js → chunk-ZRLEAPZV.js} +4 -4
- package/dist/{chunk-BGEEES52.js → chunk-ZROQPUCQ.js} +7 -7
- package/dist/client.cjs +2922 -2840
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.ts +1 -0
- package/dist/client.js +18 -21
- package/dist/edge.cjs +437 -0
- package/dist/edge.cjs.map +1 -0
- package/dist/edge.d.ts +5 -0
- package/dist/edge.js +25 -0
- package/dist/edge.js.map +1 -0
- package/dist/index.cjs +1981 -1888
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +28 -26
- package/dist/modelrouter/core.cjs +2 -2
- package/dist/modelrouter/core.cjs.map +1 -1
- package/dist/modelrouter/core.js +1 -1
- package/dist/modelrouter/index.cjs +2 -2
- package/dist/modelrouter/index.cjs.map +1 -1
- package/dist/modelrouter/index.js +1 -1
- package/dist/tools/browser/index.js +3 -3
- package/dist/tools/codebase_search/anthropic.js +2 -2
- package/dist/tools/codebase_search/index.js +6 -6
- package/dist/tools/codebase_search/openai.js +2 -2
- package/dist/tools/codebase_search/vercel.js +2 -2
- package/dist/tools/fastapply/anthropic.cjs +109 -40
- package/dist/tools/fastapply/anthropic.cjs.map +1 -1
- package/dist/tools/fastapply/anthropic.js +3 -2
- package/dist/tools/fastapply/apply.cjs +227 -0
- package/dist/tools/fastapply/apply.cjs.map +1 -0
- package/dist/tools/fastapply/apply.d.ts +59 -0
- package/dist/tools/fastapply/apply.js +15 -0
- package/dist/tools/fastapply/apply.js.map +1 -0
- package/dist/tools/fastapply/core.cjs +156 -116
- package/dist/tools/fastapply/core.cjs.map +1 -1
- package/dist/tools/fastapply/core.d.ts +5 -41
- package/dist/tools/fastapply/core.js +6 -2
- package/dist/tools/fastapply/index.cjs +113 -76
- package/dist/tools/fastapply/index.cjs.map +1 -1
- package/dist/tools/fastapply/index.d.ts +2 -1
- package/dist/tools/fastapply/index.js +11 -9
- package/dist/tools/fastapply/openai.cjs +110 -41
- package/dist/tools/fastapply/openai.cjs.map +1 -1
- package/dist/tools/fastapply/openai.js +3 -2
- package/dist/tools/fastapply/vercel.cjs +110 -41
- package/dist/tools/fastapply/vercel.cjs.map +1 -1
- package/dist/tools/fastapply/vercel.js +3 -2
- package/dist/tools/index.cjs +113 -76
- package/dist/tools/index.cjs.map +1 -1
- package/dist/tools/index.d.ts +2 -1
- package/dist/tools/index.js +11 -9
- package/dist/tools/warp_grep/agent/runner.js +3 -3
- package/dist/tools/warp_grep/anthropic.cjs +549 -500
- package/dist/tools/warp_grep/anthropic.cjs.map +1 -1
- package/dist/tools/warp_grep/anthropic.js +5 -9
- package/dist/tools/warp_grep/client.cjs +550 -501
- package/dist/tools/warp_grep/client.cjs.map +1 -1
- package/dist/tools/warp_grep/client.js +4 -8
- package/dist/tools/warp_grep/gemini.cjs +549 -500
- package/dist/tools/warp_grep/gemini.cjs.map +1 -1
- package/dist/tools/warp_grep/gemini.js +4 -8
- package/dist/tools/warp_grep/gemini.js.map +1 -1
- package/dist/tools/warp_grep/harness.js +12 -12
- package/dist/tools/warp_grep/index.cjs +559 -501
- package/dist/tools/warp_grep/index.cjs.map +1 -1
- package/dist/tools/warp_grep/index.js +12 -12
- package/dist/tools/warp_grep/openai.cjs +549 -500
- package/dist/tools/warp_grep/openai.cjs.map +1 -1
- package/dist/tools/warp_grep/openai.js +5 -9
- package/dist/tools/warp_grep/providers/local.js +2 -2
- package/dist/tools/warp_grep/vercel.cjs +549 -500
- package/dist/tools/warp_grep/vercel.cjs.map +1 -1
- package/dist/tools/warp_grep/vercel.js +5 -9
- package/package.json +7 -2
- package/dist/chunk-CKTA4AXM.js +0 -233
- package/dist/chunk-CKTA4AXM.js.map +0 -1
- package/dist/chunk-CP4NZGRY.js.map +0 -1
- package/dist/chunk-QH4BSXOD.js.map +0 -1
- /package/dist/{chunk-AIXF4GQC.js.map → chunk-AFLEE2PO.js.map} +0 -0
- /package/dist/{chunk-QZNGKOCZ.js.map → chunk-HDRLLCAD.js.map} +0 -0
- /package/dist/{chunk-BKIM7SNY.js.map → chunk-I3IN742Q.js.map} +0 -0
- /package/dist/{chunk-7UYDS6OX.js.map → chunk-KQP6ZPYB.js.map} +0 -0
- /package/dist/{chunk-OTPYEYMZ.js.map → chunk-MY4OU4ON.js.map} +0 -0
- /package/dist/{chunk-UBX7QYBD.js.map → chunk-O5DA5V5S.js.map} +0 -0
- /package/dist/{chunk-GJU7UOFL.js.map → chunk-OUEJ6XEO.js.map} +0 -0
- /package/dist/{chunk-L5WXPMCH.js.map → chunk-QUIGATZE.js.map} +0 -0
- /package/dist/{chunk-4J6NACK2.js.map → chunk-Y2OTK5WC.js.map} +0 -0
- /package/dist/{chunk-4KMBU6T3.js.map → chunk-YJZP5ZL5.js.map} +0 -0
- /package/dist/{chunk-76DJEQEP.js.map → chunk-ZRLEAPZV.js.map} +0 -0
- /package/dist/{chunk-BGEEES52.js.map → chunk-ZROQPUCQ.js.map} +0 -0
|
@@ -5,6 +5,9 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
|
5
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
6
|
var __getProtoOf = Object.getPrototypeOf;
|
|
7
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
|
+
};
|
|
8
11
|
var __export = (target, all) => {
|
|
9
12
|
for (var name in all)
|
|
10
13
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
@@ -27,6 +30,540 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
27
30
|
));
|
|
28
31
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
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-v1";
|
|
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) {
|
|
289
|
+
if (SKIP_NAMES2.has(name)) return true;
|
|
290
|
+
if (name.startsWith(".")) return true;
|
|
291
|
+
for (const ext of SKIP_EXTENSIONS2) {
|
|
292
|
+
if (name.endsWith(ext)) return true;
|
|
293
|
+
}
|
|
294
|
+
return false;
|
|
295
|
+
}
|
|
296
|
+
var import_promises2, import_path4, SKIP_NAMES2, SKIP_EXTENSIONS2, LocalRipgrepProvider;
|
|
297
|
+
var init_local = __esm({
|
|
298
|
+
"tools/warp_grep/providers/local.ts"() {
|
|
299
|
+
"use strict";
|
|
300
|
+
import_promises2 = __toESM(require("fs/promises"), 1);
|
|
301
|
+
import_path4 = __toESM(require("path"), 1);
|
|
302
|
+
init_ripgrep();
|
|
303
|
+
init_paths();
|
|
304
|
+
init_files();
|
|
305
|
+
init_config();
|
|
306
|
+
SKIP_NAMES2 = /* @__PURE__ */ new Set([
|
|
307
|
+
// Version control
|
|
308
|
+
".git",
|
|
309
|
+
".svn",
|
|
310
|
+
".hg",
|
|
311
|
+
".bzr",
|
|
312
|
+
// Dependencies
|
|
313
|
+
"node_modules",
|
|
314
|
+
"bower_components",
|
|
315
|
+
".pnpm",
|
|
316
|
+
".yarn",
|
|
317
|
+
"vendor",
|
|
318
|
+
"Pods",
|
|
319
|
+
".bundle",
|
|
320
|
+
// Python
|
|
321
|
+
"__pycache__",
|
|
322
|
+
".pytest_cache",
|
|
323
|
+
".mypy_cache",
|
|
324
|
+
".ruff_cache",
|
|
325
|
+
".venv",
|
|
326
|
+
"venv",
|
|
327
|
+
".tox",
|
|
328
|
+
".nox",
|
|
329
|
+
".eggs",
|
|
330
|
+
// Build outputs
|
|
331
|
+
"dist",
|
|
332
|
+
"build",
|
|
333
|
+
"out",
|
|
334
|
+
"output",
|
|
335
|
+
"target",
|
|
336
|
+
"_build",
|
|
337
|
+
".next",
|
|
338
|
+
".nuxt",
|
|
339
|
+
".output",
|
|
340
|
+
".vercel",
|
|
341
|
+
".netlify",
|
|
342
|
+
// Cache
|
|
343
|
+
".cache",
|
|
344
|
+
".parcel-cache",
|
|
345
|
+
".turbo",
|
|
346
|
+
".nx",
|
|
347
|
+
".gradle",
|
|
348
|
+
// IDE
|
|
349
|
+
".idea",
|
|
350
|
+
".vscode",
|
|
351
|
+
".vs",
|
|
352
|
+
// Coverage
|
|
353
|
+
"coverage",
|
|
354
|
+
".coverage",
|
|
355
|
+
"htmlcov",
|
|
356
|
+
".nyc_output",
|
|
357
|
+
// Temp
|
|
358
|
+
"tmp",
|
|
359
|
+
"temp",
|
|
360
|
+
".tmp",
|
|
361
|
+
".temp",
|
|
362
|
+
// Lock files
|
|
363
|
+
"package-lock.json",
|
|
364
|
+
"yarn.lock",
|
|
365
|
+
"pnpm-lock.yaml",
|
|
366
|
+
"bun.lockb",
|
|
367
|
+
"Cargo.lock",
|
|
368
|
+
"Gemfile.lock",
|
|
369
|
+
"poetry.lock"
|
|
370
|
+
]);
|
|
371
|
+
SKIP_EXTENSIONS2 = /* @__PURE__ */ new Set([
|
|
372
|
+
".min.js",
|
|
373
|
+
".min.css",
|
|
374
|
+
".bundle.js",
|
|
375
|
+
".wasm",
|
|
376
|
+
".so",
|
|
377
|
+
".dll",
|
|
378
|
+
".pyc",
|
|
379
|
+
".map",
|
|
380
|
+
".js.map"
|
|
381
|
+
]);
|
|
382
|
+
LocalRipgrepProvider = class {
|
|
383
|
+
constructor(repoRoot, excludes = DEFAULT_EXCLUDES) {
|
|
384
|
+
this.repoRoot = repoRoot;
|
|
385
|
+
this.excludes = excludes;
|
|
386
|
+
}
|
|
387
|
+
async grep(params) {
|
|
388
|
+
let abs;
|
|
389
|
+
try {
|
|
390
|
+
abs = resolveUnderRepo(this.repoRoot, params.path);
|
|
391
|
+
} catch (err) {
|
|
392
|
+
return {
|
|
393
|
+
lines: [],
|
|
394
|
+
error: `[PATH ERROR] ${err instanceof Error ? err.message : String(err)}`
|
|
395
|
+
};
|
|
396
|
+
}
|
|
397
|
+
const stat = await import_promises2.default.stat(abs).catch(() => null);
|
|
398
|
+
if (!stat) return { lines: [] };
|
|
399
|
+
const targetArg = abs === import_path4.default.resolve(this.repoRoot) ? "." : toRepoRelative(this.repoRoot, abs);
|
|
400
|
+
const args = [
|
|
401
|
+
"--no-config",
|
|
402
|
+
"--no-heading",
|
|
403
|
+
"--with-filename",
|
|
404
|
+
"--line-number",
|
|
405
|
+
"--color=never",
|
|
406
|
+
"--trim",
|
|
407
|
+
"--max-columns=400",
|
|
408
|
+
"-C",
|
|
409
|
+
"1",
|
|
410
|
+
...params.glob ? ["--glob", params.glob] : [],
|
|
411
|
+
...this.excludes.flatMap((e) => ["-g", `!${e}`]),
|
|
412
|
+
params.pattern,
|
|
413
|
+
targetArg || "."
|
|
414
|
+
];
|
|
415
|
+
const res = await runRipgrep(args, { cwd: this.repoRoot });
|
|
416
|
+
if (res.exitCode === -1) {
|
|
417
|
+
return {
|
|
418
|
+
lines: [],
|
|
419
|
+
error: `[RIPGREP NOT AVAILABLE] ripgrep (rg) is required but failed to execute. Please install it:
|
|
420
|
+
\u2022 macOS: brew install ripgrep
|
|
421
|
+
\u2022 Ubuntu/Debian: apt install ripgrep
|
|
422
|
+
\u2022 Windows: choco install ripgrep
|
|
423
|
+
\u2022 Or visit: https://github.com/BurntSushi/ripgrep#installation
|
|
424
|
+
Exit code: ${res.exitCode}${res.stderr ? `
|
|
425
|
+
Details: ${res.stderr}` : ""}`
|
|
426
|
+
};
|
|
427
|
+
}
|
|
428
|
+
if (res.exitCode !== 0 && res.exitCode !== 1) {
|
|
429
|
+
return {
|
|
430
|
+
lines: [],
|
|
431
|
+
error: `[RIPGREP ERROR] grep failed with exit code ${res.exitCode}${res.stderr ? `: ${res.stderr}` : ""}`
|
|
432
|
+
};
|
|
433
|
+
}
|
|
434
|
+
const lines = (res.stdout || "").trim().split(/\r?\n/).filter((l) => l.length > 0);
|
|
435
|
+
if (lines.length > AGENT_CONFIG.MAX_OUTPUT_LINES) {
|
|
436
|
+
return {
|
|
437
|
+
lines: [],
|
|
438
|
+
error: "query not specific enough, tool tried to return too much context and failed"
|
|
439
|
+
};
|
|
440
|
+
}
|
|
441
|
+
return { lines };
|
|
442
|
+
}
|
|
443
|
+
async read(params) {
|
|
444
|
+
let abs;
|
|
445
|
+
try {
|
|
446
|
+
abs = resolveUnderRepo(this.repoRoot, params.path);
|
|
447
|
+
} catch (err) {
|
|
448
|
+
return {
|
|
449
|
+
lines: [],
|
|
450
|
+
error: `[PATH ERROR] ${err instanceof Error ? err.message : String(err)}`
|
|
451
|
+
};
|
|
452
|
+
}
|
|
453
|
+
let stat = await import_promises2.default.stat(abs).catch(() => null);
|
|
454
|
+
if (!stat || !stat.isFile()) {
|
|
455
|
+
const fixedPath = fixPathRepetition(abs);
|
|
456
|
+
if (fixedPath) {
|
|
457
|
+
const fixedStat = await import_promises2.default.stat(fixedPath).catch(() => null);
|
|
458
|
+
if (fixedStat?.isFile()) {
|
|
459
|
+
abs = fixedPath;
|
|
460
|
+
stat = fixedStat;
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
if (!stat || !stat.isFile()) {
|
|
465
|
+
return {
|
|
466
|
+
lines: [],
|
|
467
|
+
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.`
|
|
468
|
+
};
|
|
469
|
+
}
|
|
470
|
+
if (isSymlink(abs)) {
|
|
471
|
+
return {
|
|
472
|
+
lines: [],
|
|
473
|
+
error: `[SYMLINK] You tried to read "${params.path}" but this is a symlink. Try reading the actual file it points to instead.`
|
|
474
|
+
};
|
|
475
|
+
}
|
|
476
|
+
if (!isTextualFile(abs)) {
|
|
477
|
+
return {
|
|
478
|
+
lines: [],
|
|
479
|
+
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.`
|
|
480
|
+
};
|
|
481
|
+
}
|
|
482
|
+
let lines;
|
|
483
|
+
try {
|
|
484
|
+
lines = await readAllLines(abs);
|
|
485
|
+
} catch (err) {
|
|
486
|
+
return {
|
|
487
|
+
lines: [],
|
|
488
|
+
error: `[READ ERROR] Failed to read "${params.path}": ${err instanceof Error ? err.message : String(err)}`
|
|
489
|
+
};
|
|
490
|
+
}
|
|
491
|
+
const total = lines.length;
|
|
492
|
+
const rawStart = params.start;
|
|
493
|
+
const rawEnd = params.end;
|
|
494
|
+
let s = 1;
|
|
495
|
+
let e = total;
|
|
496
|
+
const startValid = rawStart === void 0 || Number.isFinite(rawStart) && rawStart > 0;
|
|
497
|
+
const endValid = rawEnd === void 0 || Number.isFinite(rawEnd) && rawEnd > 0;
|
|
498
|
+
if (startValid && endValid) {
|
|
499
|
+
s = rawStart ?? 1;
|
|
500
|
+
e = Math.min(rawEnd ?? total, total);
|
|
501
|
+
if (s > total && total > 0 || s > e) {
|
|
502
|
+
s = 1;
|
|
503
|
+
e = total;
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
const out = [];
|
|
507
|
+
for (let i = s; i <= e; i += 1) {
|
|
508
|
+
const content = lines[i - 1] ?? "";
|
|
509
|
+
out.push(`${i}|${content}`);
|
|
510
|
+
}
|
|
511
|
+
if (out.length > AGENT_CONFIG.MAX_READ_LINES) {
|
|
512
|
+
const truncated = out.slice(0, AGENT_CONFIG.MAX_READ_LINES);
|
|
513
|
+
truncated.push(`... [truncated: showing ${AGENT_CONFIG.MAX_READ_LINES} of ${out.length} lines]`);
|
|
514
|
+
return { lines: truncated };
|
|
515
|
+
}
|
|
516
|
+
return { lines: out };
|
|
517
|
+
}
|
|
518
|
+
async listDirectory(params) {
|
|
519
|
+
let abs;
|
|
520
|
+
try {
|
|
521
|
+
abs = resolveUnderRepo(this.repoRoot, params.path);
|
|
522
|
+
} catch {
|
|
523
|
+
return [];
|
|
524
|
+
}
|
|
525
|
+
const stat = await import_promises2.default.stat(abs).catch(() => null);
|
|
526
|
+
if (!stat || !stat.isDirectory()) {
|
|
527
|
+
return [];
|
|
528
|
+
}
|
|
529
|
+
const maxResults = params.maxResults ?? AGENT_CONFIG.MAX_OUTPUT_LINES;
|
|
530
|
+
const maxDepth = params.maxDepth ?? AGENT_CONFIG.MAX_LIST_DEPTH;
|
|
531
|
+
const regex = params.pattern ? new RegExp(params.pattern) : null;
|
|
532
|
+
const repoRoot = this.repoRoot;
|
|
533
|
+
const results = [];
|
|
534
|
+
let timedOut = false;
|
|
535
|
+
const startTime = Date.now();
|
|
536
|
+
async function walk(dir, depth) {
|
|
537
|
+
if (Date.now() - startTime > AGENT_CONFIG.LIST_TIMEOUT_MS) {
|
|
538
|
+
timedOut = true;
|
|
539
|
+
return;
|
|
540
|
+
}
|
|
541
|
+
if (depth > maxDepth || results.length >= maxResults) return;
|
|
542
|
+
const entries = await import_promises2.default.readdir(dir, { withFileTypes: true });
|
|
543
|
+
for (const entry of entries) {
|
|
544
|
+
if (timedOut || results.length >= maxResults) break;
|
|
545
|
+
if (shouldSkip2(entry.name)) continue;
|
|
546
|
+
if (regex && !regex.test(entry.name)) continue;
|
|
547
|
+
const full = import_path4.default.join(dir, entry.name);
|
|
548
|
+
const isDir = entry.isDirectory();
|
|
549
|
+
results.push({
|
|
550
|
+
name: entry.name,
|
|
551
|
+
path: toRepoRelative(repoRoot, full),
|
|
552
|
+
type: isDir ? "dir" : "file",
|
|
553
|
+
depth
|
|
554
|
+
});
|
|
555
|
+
if (isDir) {
|
|
556
|
+
await walk(full, depth + 1);
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
await walk(abs, 0);
|
|
561
|
+
return results;
|
|
562
|
+
}
|
|
563
|
+
};
|
|
564
|
+
}
|
|
565
|
+
});
|
|
566
|
+
|
|
30
567
|
// tools/warp_grep/index.ts
|
|
31
568
|
var warp_grep_exports = {};
|
|
32
569
|
__export(warp_grep_exports, {
|
|
@@ -53,103 +590,8 @@ __export(warp_grep_exports, {
|
|
|
53
590
|
module.exports = __toCommonJS(warp_grep_exports);
|
|
54
591
|
var import_zod = require("zod");
|
|
55
592
|
|
|
56
|
-
// tools/warp_grep/agent/
|
|
57
|
-
|
|
58
|
-
if (!envValue) return defaultMs;
|
|
59
|
-
const parsed = parseInt(envValue, 10);
|
|
60
|
-
return isNaN(parsed) || parsed <= 0 ? defaultMs : parsed;
|
|
61
|
-
};
|
|
62
|
-
var AGENT_CONFIG = {
|
|
63
|
-
MAX_TURNS: 4,
|
|
64
|
-
/** Default timeout for model calls. Can be overridden via MORPH_WARP_GREP_TIMEOUT env var (in ms) */
|
|
65
|
-
TIMEOUT_MS: parseEnvTimeout(process.env.MORPH_WARP_GREP_TIMEOUT, 3e4),
|
|
66
|
-
MAX_CONTEXT_CHARS: 54e4,
|
|
67
|
-
MAX_OUTPUT_LINES: 200,
|
|
68
|
-
MAX_READ_LINES: 800,
|
|
69
|
-
MAX_LIST_DEPTH: 3,
|
|
70
|
-
LIST_TIMEOUT_MS: 2e3
|
|
71
|
-
};
|
|
72
|
-
var BUILTIN_EXCLUDES = [
|
|
73
|
-
// Version control
|
|
74
|
-
".git",
|
|
75
|
-
".svn",
|
|
76
|
-
".hg",
|
|
77
|
-
".bzr",
|
|
78
|
-
// Dependencies
|
|
79
|
-
"node_modules",
|
|
80
|
-
"bower_components",
|
|
81
|
-
".pnpm",
|
|
82
|
-
".yarn",
|
|
83
|
-
"vendor",
|
|
84
|
-
"packages",
|
|
85
|
-
"Pods",
|
|
86
|
-
".bundle",
|
|
87
|
-
// Python
|
|
88
|
-
"__pycache__",
|
|
89
|
-
".pytest_cache",
|
|
90
|
-
".mypy_cache",
|
|
91
|
-
".ruff_cache",
|
|
92
|
-
".venv",
|
|
93
|
-
"venv",
|
|
94
|
-
".tox",
|
|
95
|
-
".nox",
|
|
96
|
-
".eggs",
|
|
97
|
-
"*.egg-info",
|
|
98
|
-
// Build outputs
|
|
99
|
-
"dist",
|
|
100
|
-
"build",
|
|
101
|
-
"out",
|
|
102
|
-
"output",
|
|
103
|
-
"target",
|
|
104
|
-
"_build",
|
|
105
|
-
".next",
|
|
106
|
-
".nuxt",
|
|
107
|
-
".output",
|
|
108
|
-
".vercel",
|
|
109
|
-
".netlify",
|
|
110
|
-
// Cache directories
|
|
111
|
-
".cache",
|
|
112
|
-
".parcel-cache",
|
|
113
|
-
".turbo",
|
|
114
|
-
".nx",
|
|
115
|
-
".gradle",
|
|
116
|
-
// IDE/Editor
|
|
117
|
-
".idea",
|
|
118
|
-
".vscode",
|
|
119
|
-
".vs",
|
|
120
|
-
// Coverage
|
|
121
|
-
"coverage",
|
|
122
|
-
".coverage",
|
|
123
|
-
"htmlcov",
|
|
124
|
-
".nyc_output",
|
|
125
|
-
// Temporary
|
|
126
|
-
"tmp",
|
|
127
|
-
"temp",
|
|
128
|
-
".tmp",
|
|
129
|
-
".temp",
|
|
130
|
-
// Lock files
|
|
131
|
-
"package-lock.json",
|
|
132
|
-
"yarn.lock",
|
|
133
|
-
"pnpm-lock.yaml",
|
|
134
|
-
"bun.lockb",
|
|
135
|
-
"Cargo.lock",
|
|
136
|
-
"Gemfile.lock",
|
|
137
|
-
"poetry.lock",
|
|
138
|
-
// Binary/minified
|
|
139
|
-
"*.min.js",
|
|
140
|
-
"*.min.css",
|
|
141
|
-
"*.bundle.js",
|
|
142
|
-
"*.wasm",
|
|
143
|
-
"*.so",
|
|
144
|
-
"*.dll",
|
|
145
|
-
"*.pyc",
|
|
146
|
-
"*.map",
|
|
147
|
-
"*.js.map",
|
|
148
|
-
// Hidden directories catch-all
|
|
149
|
-
".*"
|
|
150
|
-
];
|
|
151
|
-
var DEFAULT_EXCLUDES = (process.env.MORPH_WARP_GREP_EXCLUDE || "").split(",").map((s) => s.trim()).filter(Boolean).concat(BUILTIN_EXCLUDES);
|
|
152
|
-
var DEFAULT_MODEL = "morph-warp-grep-v1";
|
|
593
|
+
// tools/warp_grep/agent/runner.ts
|
|
594
|
+
init_config();
|
|
153
595
|
|
|
154
596
|
// tools/warp_grep/agent/prompt.ts
|
|
155
597
|
var SYSTEM_PROMPT = `You are a code search agent. Your task is to find all relevant code for a given search_string.
|
|
@@ -665,6 +1107,7 @@ async function toolRead(provider, args) {
|
|
|
665
1107
|
}
|
|
666
1108
|
|
|
667
1109
|
// tools/warp_grep/agent/tools/list_directory.ts
|
|
1110
|
+
init_config();
|
|
668
1111
|
async function toolListDirectory(provider, args) {
|
|
669
1112
|
const maxResults = args.maxResults ?? AGENT_CONFIG.MAX_OUTPUT_LINES;
|
|
670
1113
|
const initialDepth = args.maxDepth ?? AGENT_CONFIG.MAX_LIST_DEPTH;
|
|
@@ -847,6 +1290,7 @@ function formatAgentToolOutput(toolName, args, output, options = {}) {
|
|
|
847
1290
|
|
|
848
1291
|
// tools/warp_grep/agent/helpers.ts
|
|
849
1292
|
var import_path = __toESM(require("path"), 1);
|
|
1293
|
+
init_config();
|
|
850
1294
|
var TRUNCATED_MARKER = "[truncated for context limit]";
|
|
851
1295
|
function formatTurnMessage(turnsUsed, maxTurns) {
|
|
852
1296
|
const turnsRemaining = maxTurns - turnsUsed;
|
|
@@ -1256,139 +1700,8 @@ async function* runWarpGrepStreaming(config) {
|
|
|
1256
1700
|
};
|
|
1257
1701
|
}
|
|
1258
1702
|
|
|
1259
|
-
// tools/warp_grep/providers/
|
|
1260
|
-
|
|
1261
|
-
var import_path4 = __toESM(require("path"), 1);
|
|
1262
|
-
|
|
1263
|
-
// tools/warp_grep/utils/ripgrep.ts
|
|
1264
|
-
var import_child_process = require("child_process");
|
|
1265
|
-
var import_ripgrep = require("@vscode/ripgrep");
|
|
1266
|
-
var resolvedRgPath = null;
|
|
1267
|
-
var rgPathChecked = false;
|
|
1268
|
-
function spawnRg(rgBinary, args, opts) {
|
|
1269
|
-
return new Promise((resolve) => {
|
|
1270
|
-
const child = (0, import_child_process.spawn)(rgBinary, args, {
|
|
1271
|
-
cwd: opts?.cwd,
|
|
1272
|
-
env: { ...process.env, ...opts?.env || {} },
|
|
1273
|
-
stdio: ["ignore", "pipe", "pipe"]
|
|
1274
|
-
});
|
|
1275
|
-
let stdout = "";
|
|
1276
|
-
let stderr = "";
|
|
1277
|
-
child.stdout.on("data", (d) => stdout += d.toString());
|
|
1278
|
-
child.stderr.on("data", (d) => stderr += d.toString());
|
|
1279
|
-
child.on("close", (code) => {
|
|
1280
|
-
resolve({ stdout, stderr, exitCode: typeof code === "number" ? code : -1 });
|
|
1281
|
-
});
|
|
1282
|
-
child.on("error", () => {
|
|
1283
|
-
resolve({ stdout: "", stderr: "Failed to spawn ripgrep.", exitCode: -1 });
|
|
1284
|
-
});
|
|
1285
|
-
});
|
|
1286
|
-
}
|
|
1287
|
-
function isBinaryFailure(result) {
|
|
1288
|
-
if (result.exitCode === -1) return true;
|
|
1289
|
-
if (result.stderr.includes("jemalloc") || result.stderr.includes("Unsupported system page size")) return true;
|
|
1290
|
-
if (result.exitCode === 134) return true;
|
|
1291
|
-
return false;
|
|
1292
|
-
}
|
|
1293
|
-
async function runRipgrep(args, opts) {
|
|
1294
|
-
if (rgPathChecked && resolvedRgPath) {
|
|
1295
|
-
return spawnRg(resolvedRgPath, args, opts);
|
|
1296
|
-
}
|
|
1297
|
-
if (!rgPathChecked) {
|
|
1298
|
-
const result = await spawnRg(import_ripgrep.rgPath, args, opts);
|
|
1299
|
-
if (!isBinaryFailure(result)) {
|
|
1300
|
-
resolvedRgPath = import_ripgrep.rgPath;
|
|
1301
|
-
rgPathChecked = true;
|
|
1302
|
-
return result;
|
|
1303
|
-
}
|
|
1304
|
-
const fallbackResult = await spawnRg("rg", args, opts);
|
|
1305
|
-
if (!isBinaryFailure(fallbackResult)) {
|
|
1306
|
-
resolvedRgPath = "rg";
|
|
1307
|
-
rgPathChecked = true;
|
|
1308
|
-
return fallbackResult;
|
|
1309
|
-
}
|
|
1310
|
-
rgPathChecked = true;
|
|
1311
|
-
return {
|
|
1312
|
-
stdout: "",
|
|
1313
|
-
stderr: "Failed to spawn ripgrep. Neither bundled nor system rg is available.",
|
|
1314
|
-
exitCode: -1
|
|
1315
|
-
};
|
|
1316
|
-
}
|
|
1317
|
-
return {
|
|
1318
|
-
stdout: "",
|
|
1319
|
-
stderr: "Failed to spawn ripgrep. Neither bundled nor system rg is available.",
|
|
1320
|
-
exitCode: -1
|
|
1321
|
-
};
|
|
1322
|
-
}
|
|
1323
|
-
|
|
1324
|
-
// tools/warp_grep/utils/paths.ts
|
|
1325
|
-
var import_fs = __toESM(require("fs"), 1);
|
|
1326
|
-
var import_path3 = __toESM(require("path"), 1);
|
|
1327
|
-
function resolveUnderRepo(repoRoot, targetPath) {
|
|
1328
|
-
const absRoot = import_path3.default.resolve(repoRoot);
|
|
1329
|
-
const resolved = import_path3.default.resolve(absRoot, targetPath);
|
|
1330
|
-
ensureWithinRepo(absRoot, resolved);
|
|
1331
|
-
return resolved;
|
|
1332
|
-
}
|
|
1333
|
-
function ensureWithinRepo(repoRoot, absTarget) {
|
|
1334
|
-
const rel = import_path3.default.relative(import_path3.default.resolve(repoRoot), import_path3.default.resolve(absTarget));
|
|
1335
|
-
if (rel.startsWith("..") || import_path3.default.isAbsolute(rel)) {
|
|
1336
|
-
throw new Error(`Path outside repository root: ${absTarget}`);
|
|
1337
|
-
}
|
|
1338
|
-
}
|
|
1339
|
-
function toRepoRelative(repoRoot, absPath) {
|
|
1340
|
-
return import_path3.default.relative(import_path3.default.resolve(repoRoot), import_path3.default.resolve(absPath));
|
|
1341
|
-
}
|
|
1342
|
-
function isSymlink(p) {
|
|
1343
|
-
try {
|
|
1344
|
-
const st = import_fs.default.lstatSync(p);
|
|
1345
|
-
return st.isSymbolicLink();
|
|
1346
|
-
} catch {
|
|
1347
|
-
return false;
|
|
1348
|
-
}
|
|
1349
|
-
}
|
|
1350
|
-
function fixPathRepetition(fullPath) {
|
|
1351
|
-
const segments = fullPath.split(import_path3.default.sep).filter(Boolean);
|
|
1352
|
-
if (segments.length < 2) return null;
|
|
1353
|
-
for (let len = Math.floor(segments.length / 2); len >= 1; len--) {
|
|
1354
|
-
for (let i = 0; i <= segments.length - 2 * len; i++) {
|
|
1355
|
-
const first = segments.slice(i, i + len);
|
|
1356
|
-
const second = segments.slice(i + len, i + 2 * len);
|
|
1357
|
-
if (first.every((seg, idx) => seg === second[idx])) {
|
|
1358
|
-
const fixed = [...segments.slice(0, i), ...segments.slice(i + len)];
|
|
1359
|
-
return import_path3.default.sep + fixed.join(import_path3.default.sep);
|
|
1360
|
-
}
|
|
1361
|
-
}
|
|
1362
|
-
}
|
|
1363
|
-
return null;
|
|
1364
|
-
}
|
|
1365
|
-
function isTextualFile(filePath, maxBytes = 2e6) {
|
|
1366
|
-
try {
|
|
1367
|
-
const st = import_fs.default.statSync(filePath);
|
|
1368
|
-
if (!st.isFile()) return false;
|
|
1369
|
-
if (st.size > maxBytes) return false;
|
|
1370
|
-
const fd = import_fs.default.openSync(filePath, "r");
|
|
1371
|
-
const buf = Buffer.alloc(512);
|
|
1372
|
-
const read = import_fs.default.readSync(fd, buf, 0, buf.length, 0);
|
|
1373
|
-
import_fs.default.closeSync(fd);
|
|
1374
|
-
for (let i = 0; i < read; i++) {
|
|
1375
|
-
const c = buf[i];
|
|
1376
|
-
if (c === 0) return false;
|
|
1377
|
-
}
|
|
1378
|
-
return true;
|
|
1379
|
-
} catch {
|
|
1380
|
-
return false;
|
|
1381
|
-
}
|
|
1382
|
-
}
|
|
1383
|
-
|
|
1384
|
-
// tools/warp_grep/utils/files.ts
|
|
1385
|
-
var import_promises = __toESM(require("fs/promises"), 1);
|
|
1386
|
-
async function readAllLines(filePath) {
|
|
1387
|
-
const content = await import_promises.default.readFile(filePath, "utf8");
|
|
1388
|
-
return content.split(/\r?\n/);
|
|
1389
|
-
}
|
|
1390
|
-
|
|
1391
|
-
// tools/warp_grep/providers/local.ts
|
|
1703
|
+
// tools/warp_grep/providers/remote.ts
|
|
1704
|
+
init_config();
|
|
1392
1705
|
var SKIP_NAMES = /* @__PURE__ */ new Set([
|
|
1393
1706
|
// Version control
|
|
1394
1707
|
".git",
|
|
@@ -1473,274 +1786,6 @@ function shouldSkip(name) {
|
|
|
1473
1786
|
}
|
|
1474
1787
|
return false;
|
|
1475
1788
|
}
|
|
1476
|
-
var LocalRipgrepProvider = class {
|
|
1477
|
-
constructor(repoRoot, excludes = DEFAULT_EXCLUDES) {
|
|
1478
|
-
this.repoRoot = repoRoot;
|
|
1479
|
-
this.excludes = excludes;
|
|
1480
|
-
}
|
|
1481
|
-
async grep(params) {
|
|
1482
|
-
let abs;
|
|
1483
|
-
try {
|
|
1484
|
-
abs = resolveUnderRepo(this.repoRoot, params.path);
|
|
1485
|
-
} catch (err) {
|
|
1486
|
-
return {
|
|
1487
|
-
lines: [],
|
|
1488
|
-
error: `[PATH ERROR] ${err instanceof Error ? err.message : String(err)}`
|
|
1489
|
-
};
|
|
1490
|
-
}
|
|
1491
|
-
const stat = await import_promises2.default.stat(abs).catch(() => null);
|
|
1492
|
-
if (!stat) return { lines: [] };
|
|
1493
|
-
const targetArg = abs === import_path4.default.resolve(this.repoRoot) ? "." : toRepoRelative(this.repoRoot, abs);
|
|
1494
|
-
const args = [
|
|
1495
|
-
"--no-config",
|
|
1496
|
-
"--no-heading",
|
|
1497
|
-
"--with-filename",
|
|
1498
|
-
"--line-number",
|
|
1499
|
-
"--color=never",
|
|
1500
|
-
"--trim",
|
|
1501
|
-
"--max-columns=400",
|
|
1502
|
-
"-C",
|
|
1503
|
-
"1",
|
|
1504
|
-
...params.glob ? ["--glob", params.glob] : [],
|
|
1505
|
-
...this.excludes.flatMap((e) => ["-g", `!${e}`]),
|
|
1506
|
-
params.pattern,
|
|
1507
|
-
targetArg || "."
|
|
1508
|
-
];
|
|
1509
|
-
const res = await runRipgrep(args, { cwd: this.repoRoot });
|
|
1510
|
-
if (res.exitCode === -1) {
|
|
1511
|
-
return {
|
|
1512
|
-
lines: [],
|
|
1513
|
-
error: `[RIPGREP NOT AVAILABLE] ripgrep (rg) is required but failed to execute. Please install it:
|
|
1514
|
-
\u2022 macOS: brew install ripgrep
|
|
1515
|
-
\u2022 Ubuntu/Debian: apt install ripgrep
|
|
1516
|
-
\u2022 Windows: choco install ripgrep
|
|
1517
|
-
\u2022 Or visit: https://github.com/BurntSushi/ripgrep#installation
|
|
1518
|
-
Exit code: ${res.exitCode}${res.stderr ? `
|
|
1519
|
-
Details: ${res.stderr}` : ""}`
|
|
1520
|
-
};
|
|
1521
|
-
}
|
|
1522
|
-
if (res.exitCode !== 0 && res.exitCode !== 1) {
|
|
1523
|
-
return {
|
|
1524
|
-
lines: [],
|
|
1525
|
-
error: `[RIPGREP ERROR] grep failed with exit code ${res.exitCode}${res.stderr ? `: ${res.stderr}` : ""}`
|
|
1526
|
-
};
|
|
1527
|
-
}
|
|
1528
|
-
const lines = (res.stdout || "").trim().split(/\r?\n/).filter((l) => l.length > 0);
|
|
1529
|
-
if (lines.length > AGENT_CONFIG.MAX_OUTPUT_LINES) {
|
|
1530
|
-
return {
|
|
1531
|
-
lines: [],
|
|
1532
|
-
error: "query not specific enough, tool tried to return too much context and failed"
|
|
1533
|
-
};
|
|
1534
|
-
}
|
|
1535
|
-
return { lines };
|
|
1536
|
-
}
|
|
1537
|
-
async read(params) {
|
|
1538
|
-
let abs;
|
|
1539
|
-
try {
|
|
1540
|
-
abs = resolveUnderRepo(this.repoRoot, params.path);
|
|
1541
|
-
} catch (err) {
|
|
1542
|
-
return {
|
|
1543
|
-
lines: [],
|
|
1544
|
-
error: `[PATH ERROR] ${err instanceof Error ? err.message : String(err)}`
|
|
1545
|
-
};
|
|
1546
|
-
}
|
|
1547
|
-
let stat = await import_promises2.default.stat(abs).catch(() => null);
|
|
1548
|
-
if (!stat || !stat.isFile()) {
|
|
1549
|
-
const fixedPath = fixPathRepetition(abs);
|
|
1550
|
-
if (fixedPath) {
|
|
1551
|
-
const fixedStat = await import_promises2.default.stat(fixedPath).catch(() => null);
|
|
1552
|
-
if (fixedStat?.isFile()) {
|
|
1553
|
-
abs = fixedPath;
|
|
1554
|
-
stat = fixedStat;
|
|
1555
|
-
}
|
|
1556
|
-
}
|
|
1557
|
-
}
|
|
1558
|
-
if (!stat || !stat.isFile()) {
|
|
1559
|
-
return {
|
|
1560
|
-
lines: [],
|
|
1561
|
-
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.`
|
|
1562
|
-
};
|
|
1563
|
-
}
|
|
1564
|
-
if (isSymlink(abs)) {
|
|
1565
|
-
return {
|
|
1566
|
-
lines: [],
|
|
1567
|
-
error: `[SYMLINK] You tried to read "${params.path}" but this is a symlink. Try reading the actual file it points to instead.`
|
|
1568
|
-
};
|
|
1569
|
-
}
|
|
1570
|
-
if (!isTextualFile(abs)) {
|
|
1571
|
-
return {
|
|
1572
|
-
lines: [],
|
|
1573
|
-
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.`
|
|
1574
|
-
};
|
|
1575
|
-
}
|
|
1576
|
-
let lines;
|
|
1577
|
-
try {
|
|
1578
|
-
lines = await readAllLines(abs);
|
|
1579
|
-
} catch (err) {
|
|
1580
|
-
return {
|
|
1581
|
-
lines: [],
|
|
1582
|
-
error: `[READ ERROR] Failed to read "${params.path}": ${err instanceof Error ? err.message : String(err)}`
|
|
1583
|
-
};
|
|
1584
|
-
}
|
|
1585
|
-
const total = lines.length;
|
|
1586
|
-
const rawStart = params.start;
|
|
1587
|
-
const rawEnd = params.end;
|
|
1588
|
-
let s = 1;
|
|
1589
|
-
let e = total;
|
|
1590
|
-
const startValid = rawStart === void 0 || Number.isFinite(rawStart) && rawStart > 0;
|
|
1591
|
-
const endValid = rawEnd === void 0 || Number.isFinite(rawEnd) && rawEnd > 0;
|
|
1592
|
-
if (startValid && endValid) {
|
|
1593
|
-
s = rawStart ?? 1;
|
|
1594
|
-
e = Math.min(rawEnd ?? total, total);
|
|
1595
|
-
if (s > total && total > 0 || s > e) {
|
|
1596
|
-
s = 1;
|
|
1597
|
-
e = total;
|
|
1598
|
-
}
|
|
1599
|
-
}
|
|
1600
|
-
const out = [];
|
|
1601
|
-
for (let i = s; i <= e; i += 1) {
|
|
1602
|
-
const content = lines[i - 1] ?? "";
|
|
1603
|
-
out.push(`${i}|${content}`);
|
|
1604
|
-
}
|
|
1605
|
-
if (out.length > AGENT_CONFIG.MAX_READ_LINES) {
|
|
1606
|
-
const truncated = out.slice(0, AGENT_CONFIG.MAX_READ_LINES);
|
|
1607
|
-
truncated.push(`... [truncated: showing ${AGENT_CONFIG.MAX_READ_LINES} of ${out.length} lines]`);
|
|
1608
|
-
return { lines: truncated };
|
|
1609
|
-
}
|
|
1610
|
-
return { lines: out };
|
|
1611
|
-
}
|
|
1612
|
-
async listDirectory(params) {
|
|
1613
|
-
let abs;
|
|
1614
|
-
try {
|
|
1615
|
-
abs = resolveUnderRepo(this.repoRoot, params.path);
|
|
1616
|
-
} catch {
|
|
1617
|
-
return [];
|
|
1618
|
-
}
|
|
1619
|
-
const stat = await import_promises2.default.stat(abs).catch(() => null);
|
|
1620
|
-
if (!stat || !stat.isDirectory()) {
|
|
1621
|
-
return [];
|
|
1622
|
-
}
|
|
1623
|
-
const maxResults = params.maxResults ?? AGENT_CONFIG.MAX_OUTPUT_LINES;
|
|
1624
|
-
const maxDepth = params.maxDepth ?? AGENT_CONFIG.MAX_LIST_DEPTH;
|
|
1625
|
-
const regex = params.pattern ? new RegExp(params.pattern) : null;
|
|
1626
|
-
const repoRoot = this.repoRoot;
|
|
1627
|
-
const results = [];
|
|
1628
|
-
let timedOut = false;
|
|
1629
|
-
const startTime = Date.now();
|
|
1630
|
-
async function walk(dir, depth) {
|
|
1631
|
-
if (Date.now() - startTime > AGENT_CONFIG.LIST_TIMEOUT_MS) {
|
|
1632
|
-
timedOut = true;
|
|
1633
|
-
return;
|
|
1634
|
-
}
|
|
1635
|
-
if (depth > maxDepth || results.length >= maxResults) return;
|
|
1636
|
-
const entries = await import_promises2.default.readdir(dir, { withFileTypes: true });
|
|
1637
|
-
for (const entry of entries) {
|
|
1638
|
-
if (timedOut || results.length >= maxResults) break;
|
|
1639
|
-
if (shouldSkip(entry.name)) continue;
|
|
1640
|
-
if (regex && !regex.test(entry.name)) continue;
|
|
1641
|
-
const full = import_path4.default.join(dir, entry.name);
|
|
1642
|
-
const isDir = entry.isDirectory();
|
|
1643
|
-
results.push({
|
|
1644
|
-
name: entry.name,
|
|
1645
|
-
path: toRepoRelative(repoRoot, full),
|
|
1646
|
-
type: isDir ? "dir" : "file",
|
|
1647
|
-
depth
|
|
1648
|
-
});
|
|
1649
|
-
if (isDir) {
|
|
1650
|
-
await walk(full, depth + 1);
|
|
1651
|
-
}
|
|
1652
|
-
}
|
|
1653
|
-
}
|
|
1654
|
-
await walk(abs, 0);
|
|
1655
|
-
return results;
|
|
1656
|
-
}
|
|
1657
|
-
};
|
|
1658
|
-
|
|
1659
|
-
// tools/warp_grep/providers/remote.ts
|
|
1660
|
-
var SKIP_NAMES2 = /* @__PURE__ */ new Set([
|
|
1661
|
-
// Version control
|
|
1662
|
-
".git",
|
|
1663
|
-
".svn",
|
|
1664
|
-
".hg",
|
|
1665
|
-
".bzr",
|
|
1666
|
-
// Dependencies
|
|
1667
|
-
"node_modules",
|
|
1668
|
-
"bower_components",
|
|
1669
|
-
".pnpm",
|
|
1670
|
-
".yarn",
|
|
1671
|
-
"vendor",
|
|
1672
|
-
"Pods",
|
|
1673
|
-
".bundle",
|
|
1674
|
-
// Python
|
|
1675
|
-
"__pycache__",
|
|
1676
|
-
".pytest_cache",
|
|
1677
|
-
".mypy_cache",
|
|
1678
|
-
".ruff_cache",
|
|
1679
|
-
".venv",
|
|
1680
|
-
"venv",
|
|
1681
|
-
".tox",
|
|
1682
|
-
".nox",
|
|
1683
|
-
".eggs",
|
|
1684
|
-
// Build outputs
|
|
1685
|
-
"dist",
|
|
1686
|
-
"build",
|
|
1687
|
-
"out",
|
|
1688
|
-
"output",
|
|
1689
|
-
"target",
|
|
1690
|
-
"_build",
|
|
1691
|
-
".next",
|
|
1692
|
-
".nuxt",
|
|
1693
|
-
".output",
|
|
1694
|
-
".vercel",
|
|
1695
|
-
".netlify",
|
|
1696
|
-
// Cache
|
|
1697
|
-
".cache",
|
|
1698
|
-
".parcel-cache",
|
|
1699
|
-
".turbo",
|
|
1700
|
-
".nx",
|
|
1701
|
-
".gradle",
|
|
1702
|
-
// IDE
|
|
1703
|
-
".idea",
|
|
1704
|
-
".vscode",
|
|
1705
|
-
".vs",
|
|
1706
|
-
// Coverage
|
|
1707
|
-
"coverage",
|
|
1708
|
-
".coverage",
|
|
1709
|
-
"htmlcov",
|
|
1710
|
-
".nyc_output",
|
|
1711
|
-
// Temp
|
|
1712
|
-
"tmp",
|
|
1713
|
-
"temp",
|
|
1714
|
-
".tmp",
|
|
1715
|
-
".temp",
|
|
1716
|
-
// Lock files
|
|
1717
|
-
"package-lock.json",
|
|
1718
|
-
"yarn.lock",
|
|
1719
|
-
"pnpm-lock.yaml",
|
|
1720
|
-
"bun.lockb",
|
|
1721
|
-
"Cargo.lock",
|
|
1722
|
-
"Gemfile.lock",
|
|
1723
|
-
"poetry.lock"
|
|
1724
|
-
]);
|
|
1725
|
-
var SKIP_EXTENSIONS2 = /* @__PURE__ */ new Set([
|
|
1726
|
-
".min.js",
|
|
1727
|
-
".min.css",
|
|
1728
|
-
".bundle.js",
|
|
1729
|
-
".wasm",
|
|
1730
|
-
".so",
|
|
1731
|
-
".dll",
|
|
1732
|
-
".pyc",
|
|
1733
|
-
".map",
|
|
1734
|
-
".js.map"
|
|
1735
|
-
]);
|
|
1736
|
-
function shouldSkip2(name) {
|
|
1737
|
-
if (SKIP_NAMES2.has(name)) return true;
|
|
1738
|
-
if (name.startsWith(".")) return true;
|
|
1739
|
-
for (const ext of SKIP_EXTENSIONS2) {
|
|
1740
|
-
if (name.endsWith(ext)) return true;
|
|
1741
|
-
}
|
|
1742
|
-
return false;
|
|
1743
|
-
}
|
|
1744
1789
|
var RemoteCommandsProvider = class {
|
|
1745
1790
|
constructor(repoRoot, commands) {
|
|
1746
1791
|
this.repoRoot = repoRoot;
|
|
@@ -1812,7 +1857,7 @@ var RemoteCommandsProvider = class {
|
|
|
1812
1857
|
for (const fullPath of paths) {
|
|
1813
1858
|
if (fullPath === params.path || fullPath === this.repoRoot) continue;
|
|
1814
1859
|
const name = fullPath.split("/").pop() || "";
|
|
1815
|
-
if (
|
|
1860
|
+
if (shouldSkip(name)) continue;
|
|
1816
1861
|
if (regex && !regex.test(name)) continue;
|
|
1817
1862
|
let relativePath = fullPath;
|
|
1818
1863
|
if (fullPath.startsWith(this.repoRoot)) {
|
|
@@ -1837,6 +1882,10 @@ var RemoteCommandsProvider = class {
|
|
|
1837
1882
|
};
|
|
1838
1883
|
|
|
1839
1884
|
// tools/warp_grep/client.ts
|
|
1885
|
+
async function getLocalProvider(repoRoot, excludes) {
|
|
1886
|
+
const { LocalRipgrepProvider: LocalRipgrepProvider2 } = await Promise.resolve().then(() => (init_local(), local_exports));
|
|
1887
|
+
return new LocalRipgrepProvider2(repoRoot, excludes);
|
|
1888
|
+
}
|
|
1840
1889
|
var WarpGrepClient = class {
|
|
1841
1890
|
config;
|
|
1842
1891
|
constructor(config = {}) {
|
|
@@ -1876,7 +1925,7 @@ function executeWarpGrep(input, config) {
|
|
|
1876
1925
|
}
|
|
1877
1926
|
async function executeToolCall(input, config) {
|
|
1878
1927
|
const parsed = typeof input === "string" ? JSON.parse(input) : input;
|
|
1879
|
-
const provider = config.remoteCommands ? new RemoteCommandsProvider(config.repoRoot, config.remoteCommands) : config.provider ??
|
|
1928
|
+
const provider = config.remoteCommands ? new RemoteCommandsProvider(config.repoRoot, config.remoteCommands) : config.provider ?? await getLocalProvider(config.repoRoot, config.excludes);
|
|
1880
1929
|
const result = await runWarpGrep({
|
|
1881
1930
|
query: parsed.query,
|
|
1882
1931
|
repoRoot: config.repoRoot,
|
|
@@ -1912,7 +1961,7 @@ function processAgentResult(result) {
|
|
|
1912
1961
|
}
|
|
1913
1962
|
async function* executeToolCallStreaming(input, config) {
|
|
1914
1963
|
const parsed = typeof input === "string" ? JSON.parse(input) : input;
|
|
1915
|
-
const provider = config.remoteCommands ? new RemoteCommandsProvider(config.repoRoot, config.remoteCommands) : config.provider ??
|
|
1964
|
+
const provider = config.remoteCommands ? new RemoteCommandsProvider(config.repoRoot, config.remoteCommands) : config.provider ?? await getLocalProvider(config.repoRoot, config.excludes);
|
|
1916
1965
|
const generator = runWarpGrepStreaming({
|
|
1917
1966
|
query: parsed.query,
|
|
1918
1967
|
repoRoot: config.repoRoot,
|
|
@@ -1963,6 +2012,15 @@ function formatResult(result) {
|
|
|
1963
2012
|
var WARP_GREP_TOOL_NAME = "warpgrep_codebase_search";
|
|
1964
2013
|
var WARP_GREP_DESCRIPTION = 'IMPORTANT: If you need to explore the codebase to gather context, and the task does not involve a single file or function which is provided by name, you should ALWAYS use the warpgrep codebase search tool first instead of running search commands. When the task requires exploration beyond a single known file, invoke warpgrep first with a natural-language query describing the target functionality, bug, or architectural concern. Warp Grep is a fast and accurate tool that can search for all relevant context in a codebase. Keep queries action-oriented (e.g., "Find where billing invoices are generated and emailed"), and after reviewing the summarized results, you may verify important findings with other search tools or direct file reads to ensure completeness. Warp Grep can be used for query types like: find function responsible for <small feature>; find code that does <description>; find code path for <big feature>; Where does <minimal error message> come from?; or any query of that type. When a task requires exploration beyond a single known file, ALWAYS default to warpgrep codebase search before other search mechanisms.';
|
|
1965
2014
|
|
|
2015
|
+
// tools/warp_grep/providers/index.ts
|
|
2016
|
+
init_local();
|
|
2017
|
+
|
|
2018
|
+
// tools/warp_grep/index.ts
|
|
2019
|
+
init_paths();
|
|
2020
|
+
|
|
2021
|
+
// tools/warp_grep/agent/index.ts
|
|
2022
|
+
init_config();
|
|
2023
|
+
|
|
1966
2024
|
// tools/warp_grep/index.ts
|
|
1967
2025
|
var warpGrepInputSchema = import_zod.z.object({
|
|
1968
2026
|
query: import_zod.z.string().describe("Free-form repository question")
|