@morphllm/morphsdk 0.2.50 → 0.2.52
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-4MELBN55.js → chunk-FYQUSDOE.js} +4 -4
- package/dist/{chunk-Z2FBMSNE.js → chunk-HQO45BAJ.js} +5 -1
- package/dist/chunk-HQO45BAJ.js.map +1 -0
- package/dist/{chunk-NRWVMX4O.js → chunk-L5BMGLLQ.js} +29 -22
- package/dist/chunk-L5BMGLLQ.js.map +1 -0
- package/dist/{chunk-SWQPIKPY.js → chunk-LVPVVLTI.js} +70 -49
- package/dist/chunk-LVPVVLTI.js.map +1 -0
- package/dist/{chunk-2TXLSKGU.js → chunk-MZT6HVGD.js} +3 -3
- package/dist/{chunk-DZRBTNQR.js → chunk-PZDR5ZZ2.js} +5 -5
- package/dist/{chunk-KH3RKPPO.js → chunk-UU6XCZG3.js} +4 -4
- package/dist/{chunk-5ASRBH5I.js → chunk-YR53PPVM.js} +4 -4
- package/dist/{chunk-MLDK7SCW.js → chunk-ZJIIICRA.js} +29 -7
- package/dist/chunk-ZJIIICRA.js.map +1 -0
- package/dist/client.cjs +116 -68
- package/dist/client.cjs.map +1 -1
- package/dist/client.js +13 -13
- package/dist/index.cjs +116 -68
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +13 -13
- package/dist/tools/warp_grep/agent/parser.cjs +69 -48
- package/dist/tools/warp_grep/agent/parser.cjs.map +1 -1
- package/dist/tools/warp_grep/agent/parser.d.ts +2 -0
- package/dist/tools/warp_grep/agent/parser.js +1 -1
- package/dist/tools/warp_grep/agent/runner.cjs +88 -62
- package/dist/tools/warp_grep/agent/runner.cjs.map +1 -1
- package/dist/tools/warp_grep/agent/runner.js +7 -7
- package/dist/tools/warp_grep/agent/types.cjs.map +1 -1
- package/dist/tools/warp_grep/agent/types.d.ts +1 -1
- package/dist/tools/warp_grep/anthropic.cjs +116 -68
- package/dist/tools/warp_grep/anthropic.cjs.map +1 -1
- package/dist/tools/warp_grep/anthropic.js +10 -10
- package/dist/tools/warp_grep/index.cjs +116 -68
- 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 +116 -68
- package/dist/tools/warp_grep/openai.cjs.map +1 -1
- package/dist/tools/warp_grep/openai.js +10 -10
- package/dist/tools/warp_grep/providers/local.cjs +28 -6
- package/dist/tools/warp_grep/providers/local.cjs.map +1 -1
- package/dist/tools/warp_grep/providers/local.js +1 -1
- package/dist/tools/warp_grep/providers/types.cjs.map +1 -1
- package/dist/tools/warp_grep/providers/types.d.ts +2 -0
- package/dist/tools/warp_grep/tools/grep.cjs +3 -0
- package/dist/tools/warp_grep/tools/grep.cjs.map +1 -1
- package/dist/tools/warp_grep/tools/grep.js +3 -0
- package/dist/tools/warp_grep/tools/grep.js.map +1 -1
- package/dist/tools/warp_grep/tools/read.cjs +4 -0
- package/dist/tools/warp_grep/tools/read.cjs.map +1 -1
- package/dist/tools/warp_grep/tools/read.js +1 -1
- package/dist/tools/warp_grep/vercel.cjs +116 -68
- package/dist/tools/warp_grep/vercel.cjs.map +1 -1
- package/dist/tools/warp_grep/vercel.js +10 -10
- package/package.json +1 -1
- package/dist/chunk-MLDK7SCW.js.map +0 -1
- package/dist/chunk-NRWVMX4O.js.map +0 -1
- package/dist/chunk-SWQPIKPY.js.map +0 -1
- package/dist/chunk-Z2FBMSNE.js.map +0 -1
- /package/dist/{chunk-4MELBN55.js.map → chunk-FYQUSDOE.js.map} +0 -0
- /package/dist/{chunk-2TXLSKGU.js.map → chunk-MZT6HVGD.js.map} +0 -0
- /package/dist/{chunk-DZRBTNQR.js.map → chunk-PZDR5ZZ2.js.map} +0 -0
- /package/dist/{chunk-KH3RKPPO.js.map → chunk-UU6XCZG3.js.map} +0 -0
- /package/dist/{chunk-5ASRBH5I.js.map → chunk-YR53PPVM.js.map} +0 -0
|
@@ -252,12 +252,6 @@ function getSystemPrompt() {
|
|
|
252
252
|
}
|
|
253
253
|
|
|
254
254
|
// tools/warp_grep/agent/parser.ts
|
|
255
|
-
var LLMResponseParseError = class extends Error {
|
|
256
|
-
constructor(message) {
|
|
257
|
-
super(message);
|
|
258
|
-
this.name = "LLMResponseParseError";
|
|
259
|
-
}
|
|
260
|
-
};
|
|
261
255
|
var VALID_COMMANDS = ["analyse", "grep", "read", "finish"];
|
|
262
256
|
function preprocessText(text) {
|
|
263
257
|
let processed = text.replace(/<think>[\s\S]*?<\/think>/gi, "");
|
|
@@ -308,24 +302,23 @@ var LLMResponseParser = class {
|
|
|
308
302
|
const lines = preprocessText(text);
|
|
309
303
|
const commands = [];
|
|
310
304
|
let finishAccumulator = null;
|
|
311
|
-
lines.forEach((line
|
|
305
|
+
lines.forEach((line) => {
|
|
312
306
|
if (!line || line.startsWith("#")) return;
|
|
313
|
-
const
|
|
314
|
-
const parts = this.splitLine(line, ctx);
|
|
307
|
+
const parts = this.splitLine(line);
|
|
315
308
|
if (parts.length === 0) return;
|
|
316
309
|
const cmd = parts[0];
|
|
317
310
|
switch (cmd) {
|
|
318
311
|
case "analyse":
|
|
319
|
-
this.handleAnalyse(parts,
|
|
312
|
+
this.handleAnalyse(parts, line, commands);
|
|
320
313
|
break;
|
|
321
314
|
case "grep":
|
|
322
|
-
this.handleGrep(parts,
|
|
315
|
+
this.handleGrep(parts, line, commands);
|
|
323
316
|
break;
|
|
324
317
|
case "read":
|
|
325
|
-
this.handleRead(parts,
|
|
318
|
+
this.handleRead(parts, line, commands);
|
|
326
319
|
break;
|
|
327
320
|
case "finish":
|
|
328
|
-
finishAccumulator = this.handleFinish(parts,
|
|
321
|
+
finishAccumulator = this.handleFinish(parts, line, commands, finishAccumulator);
|
|
329
322
|
break;
|
|
330
323
|
default:
|
|
331
324
|
break;
|
|
@@ -342,53 +335,68 @@ var LLMResponseParser = class {
|
|
|
342
335
|
}
|
|
343
336
|
return commands;
|
|
344
337
|
}
|
|
345
|
-
splitLine(line
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
current = "";
|
|
359
|
-
}
|
|
360
|
-
} else {
|
|
361
|
-
current += ch;
|
|
338
|
+
splitLine(line) {
|
|
339
|
+
const parts = [];
|
|
340
|
+
let current = "";
|
|
341
|
+
let inSingle = false;
|
|
342
|
+
for (let i = 0; i < line.length; i++) {
|
|
343
|
+
const ch = line[i];
|
|
344
|
+
if (ch === "'" && line[i - 1] !== "\\") {
|
|
345
|
+
inSingle = !inSingle;
|
|
346
|
+
current += ch;
|
|
347
|
+
} else if (!inSingle && /\s/.test(ch)) {
|
|
348
|
+
if (current) {
|
|
349
|
+
parts.push(current);
|
|
350
|
+
current = "";
|
|
362
351
|
}
|
|
352
|
+
} else {
|
|
353
|
+
current += ch;
|
|
363
354
|
}
|
|
364
|
-
if (current) parts.push(current);
|
|
365
|
-
return parts;
|
|
366
|
-
} catch {
|
|
367
|
-
throw new LLMResponseParseError(`Line ${ctx.lineNumber}: Unable to parse line.`);
|
|
368
355
|
}
|
|
356
|
+
if (current) parts.push(current);
|
|
357
|
+
return parts;
|
|
358
|
+
}
|
|
359
|
+
/** Helper to create a _skip tool call with an error message */
|
|
360
|
+
skip(message) {
|
|
361
|
+
return { name: "_skip", arguments: { message } };
|
|
369
362
|
}
|
|
370
|
-
handleAnalyse(parts,
|
|
363
|
+
handleAnalyse(parts, rawLine, commands) {
|
|
371
364
|
if (parts.length < 2) {
|
|
372
|
-
|
|
365
|
+
commands.push(this.skip(
|
|
366
|
+
`[SKIPPED] Your command "${rawLine}" is missing a path. Correct format: analyse <path> [pattern]. Example: analyse src/`
|
|
367
|
+
));
|
|
368
|
+
return;
|
|
373
369
|
}
|
|
374
370
|
const path4 = parts[1];
|
|
375
371
|
const pattern = parts[2]?.replace(/^"|"$/g, "") ?? null;
|
|
376
372
|
commands.push({ name: "analyse", arguments: { path: path4, pattern } });
|
|
377
373
|
}
|
|
378
374
|
// no glob tool in MCP
|
|
379
|
-
handleGrep(parts,
|
|
375
|
+
handleGrep(parts, rawLine, commands) {
|
|
380
376
|
if (parts.length < 3) {
|
|
381
|
-
|
|
377
|
+
commands.push(this.skip(
|
|
378
|
+
`[SKIPPED] Your command "${rawLine}" is missing arguments. Correct format: grep '<pattern>' <path>. Example: grep 'TODO' src/`
|
|
379
|
+
));
|
|
380
|
+
return;
|
|
382
381
|
}
|
|
383
|
-
|
|
384
|
-
if (
|
|
385
|
-
|
|
382
|
+
let pat = parts[1];
|
|
383
|
+
if (pat.startsWith("'") && pat.endsWith("'")) {
|
|
384
|
+
pat = pat.slice(1, -1);
|
|
386
385
|
}
|
|
387
|
-
|
|
386
|
+
if (!pat) {
|
|
387
|
+
commands.push(this.skip(
|
|
388
|
+
`[SKIPPED] Your command "${rawLine}" has an empty pattern. Provide a non-empty search pattern. Example: grep 'function' src/`
|
|
389
|
+
));
|
|
390
|
+
return;
|
|
391
|
+
}
|
|
392
|
+
commands.push({ name: "grep", arguments: { pattern: pat, path: parts[2] } });
|
|
388
393
|
}
|
|
389
|
-
handleRead(parts,
|
|
394
|
+
handleRead(parts, rawLine, commands) {
|
|
390
395
|
if (parts.length < 2) {
|
|
391
|
-
|
|
396
|
+
commands.push(this.skip(
|
|
397
|
+
`[SKIPPED] Your command "${rawLine}" is missing a path. Correct format: read <path> or read <path>:<start>-<end>. Example: read src/index.ts:1-50`
|
|
398
|
+
));
|
|
399
|
+
return;
|
|
392
400
|
}
|
|
393
401
|
const spec = parts[1];
|
|
394
402
|
const rangeIdx = spec.indexOf(":");
|
|
@@ -396,31 +404,38 @@ var LLMResponseParser = class {
|
|
|
396
404
|
commands.push({ name: "read", arguments: { path: spec } });
|
|
397
405
|
return;
|
|
398
406
|
}
|
|
399
|
-
const
|
|
407
|
+
const filePath = spec.slice(0, rangeIdx);
|
|
400
408
|
const range = spec.slice(rangeIdx + 1);
|
|
401
409
|
const [s, e] = range.split("-").map((v) => parseInt(v, 10));
|
|
402
410
|
if (!Number.isFinite(s) || !Number.isFinite(e)) {
|
|
403
|
-
|
|
411
|
+
commands.push({ name: "read", arguments: { path: filePath } });
|
|
412
|
+
return;
|
|
404
413
|
}
|
|
405
|
-
commands.push({ name: "read", arguments: { path:
|
|
414
|
+
commands.push({ name: "read", arguments: { path: filePath, start: s, end: e } });
|
|
406
415
|
}
|
|
407
|
-
handleFinish(parts,
|
|
416
|
+
handleFinish(parts, rawLine, commands, acc) {
|
|
408
417
|
const map = acc ?? /* @__PURE__ */ new Map();
|
|
409
418
|
const args = parts.slice(1);
|
|
410
419
|
for (const token of args) {
|
|
411
|
-
const [
|
|
412
|
-
if (!
|
|
413
|
-
|
|
420
|
+
const [filePath, rangesText] = token.split(":", 2);
|
|
421
|
+
if (!filePath || !rangesText) {
|
|
422
|
+
commands.push(this.skip(
|
|
423
|
+
`[SKIPPED] Invalid finish token "${token}". Correct format: finish <path>:<start>-<end>. Example: finish src/index.ts:1-50`
|
|
424
|
+
));
|
|
425
|
+
continue;
|
|
414
426
|
}
|
|
415
427
|
const rangeSpecs = rangesText.split(",").filter(Boolean);
|
|
416
428
|
for (const spec of rangeSpecs) {
|
|
417
429
|
const [s, e] = spec.split("-").map((v) => parseInt(v, 10));
|
|
418
430
|
if (!Number.isFinite(s) || !Number.isFinite(e) || e < s) {
|
|
419
|
-
|
|
431
|
+
commands.push(this.skip(
|
|
432
|
+
`[SKIPPED] Invalid range "${spec}" in "${token}". Ranges must be <start>-<end> where start <= end. Example: 1-50`
|
|
433
|
+
));
|
|
434
|
+
continue;
|
|
420
435
|
}
|
|
421
|
-
const arr = map.get(
|
|
436
|
+
const arr = map.get(filePath) ?? [];
|
|
422
437
|
arr.push([s, e]);
|
|
423
|
-
map.set(
|
|
438
|
+
map.set(filePath, arr);
|
|
424
439
|
}
|
|
425
440
|
}
|
|
426
441
|
return map;
|
|
@@ -430,6 +445,10 @@ var LLMResponseParser = class {
|
|
|
430
445
|
// tools/warp_grep/tools/read.ts
|
|
431
446
|
async function toolRead(provider, args) {
|
|
432
447
|
const res = await provider.read({ path: args.path, start: args.start, end: args.end });
|
|
448
|
+
if (res.error) {
|
|
449
|
+
return res.error;
|
|
450
|
+
}
|
|
451
|
+
if (!res.lines.length) return "(empty file)";
|
|
433
452
|
return res.lines.join("\n");
|
|
434
453
|
}
|
|
435
454
|
|
|
@@ -815,14 +834,7 @@ async function runWarpGrep(config) {
|
|
|
815
834
|
});
|
|
816
835
|
if (!assistantContent) break;
|
|
817
836
|
messages.push({ role: "assistant", content: assistantContent });
|
|
818
|
-
|
|
819
|
-
try {
|
|
820
|
-
toolCalls = parser.parse(assistantContent);
|
|
821
|
-
} catch (e) {
|
|
822
|
-
errors.push({ message: e instanceof Error ? e.message : String(e) });
|
|
823
|
-
terminationReason = "terminated";
|
|
824
|
-
break;
|
|
825
|
-
}
|
|
837
|
+
const toolCalls = parser.parse(assistantContent);
|
|
826
838
|
if (toolCalls.length === 0) {
|
|
827
839
|
errors.push({ message: "No tool calls produced by the model." });
|
|
828
840
|
terminationReason = "terminated";
|
|
@@ -832,7 +844,12 @@ async function runWarpGrep(config) {
|
|
|
832
844
|
const grepCalls = toolCalls.filter((c) => c.name === "grep");
|
|
833
845
|
const analyseCalls = toolCalls.filter((c) => c.name === "analyse");
|
|
834
846
|
const readCalls = toolCalls.filter((c) => c.name === "read");
|
|
847
|
+
const skipCalls = toolCalls.filter((c) => c.name === "_skip");
|
|
835
848
|
const formatted = [];
|
|
849
|
+
for (const c of skipCalls) {
|
|
850
|
+
const msg = c.arguments?.message || "Command skipped due to parsing error";
|
|
851
|
+
formatted.push(msg);
|
|
852
|
+
}
|
|
836
853
|
const otherPromises = [];
|
|
837
854
|
for (const c of analyseCalls) {
|
|
838
855
|
const args = c.arguments ?? {};
|
|
@@ -858,6 +875,15 @@ async function runWarpGrep(config) {
|
|
|
858
875
|
const args = c.arguments ?? {};
|
|
859
876
|
try {
|
|
860
877
|
const grepRes = await provider.grep({ pattern: args.pattern, path: args.path });
|
|
878
|
+
if (grepRes.error) {
|
|
879
|
+
errors.push({ message: grepRes.error });
|
|
880
|
+
terminationReason = "terminated";
|
|
881
|
+
return {
|
|
882
|
+
terminationReason: "terminated",
|
|
883
|
+
messages,
|
|
884
|
+
errors
|
|
885
|
+
};
|
|
886
|
+
}
|
|
861
887
|
const rawOutput = Array.isArray(grepRes.lines) ? grepRes.lines.join("\n") : "";
|
|
862
888
|
const newMatches = parseAndFilterGrepOutput(rawOutput, grepState);
|
|
863
889
|
let formattedPayload = formatTurnGrepOutput(newMatches);
|
|
@@ -1069,10 +1095,22 @@ var LocalRipgrepProvider = class {
|
|
|
1069
1095
|
];
|
|
1070
1096
|
const res = await runRipgrep(args, { cwd: this.repoRoot });
|
|
1071
1097
|
if (res.exitCode === -1) {
|
|
1072
|
-
|
|
1098
|
+
return {
|
|
1099
|
+
lines: [],
|
|
1100
|
+
error: `[RIPGREP NOT AVAILABLE] ripgrep (rg) is required but failed to execute. Please install it:
|
|
1101
|
+
\u2022 macOS: brew install ripgrep
|
|
1102
|
+
\u2022 Ubuntu/Debian: apt install ripgrep
|
|
1103
|
+
\u2022 Windows: choco install ripgrep
|
|
1104
|
+
\u2022 Or visit: https://github.com/BurntSushi/ripgrep#installation
|
|
1105
|
+
Exit code: ${res.exitCode}${res.stderr ? `
|
|
1106
|
+
Details: ${res.stderr}` : ""}`
|
|
1107
|
+
};
|
|
1073
1108
|
}
|
|
1074
1109
|
if (res.exitCode !== 0 && res.exitCode !== 1) {
|
|
1075
|
-
|
|
1110
|
+
return {
|
|
1111
|
+
lines: [],
|
|
1112
|
+
error: `[RIPGREP ERROR] grep failed with exit code ${res.exitCode}${res.stderr ? `: ${res.stderr}` : ""}`
|
|
1113
|
+
};
|
|
1076
1114
|
}
|
|
1077
1115
|
const lines = (res.stdout || "").trim().split(/\r?\n/).filter((l) => l.length > 0);
|
|
1078
1116
|
return { lines };
|
|
@@ -1090,7 +1128,8 @@ var LocalRipgrepProvider = class {
|
|
|
1090
1128
|
];
|
|
1091
1129
|
const res = await runRipgrep(args, { cwd: this.repoRoot });
|
|
1092
1130
|
if (res.exitCode === -1) {
|
|
1093
|
-
|
|
1131
|
+
console.warn(`[warp_grep] ripgrep not available for glob: ${res.stderr || "execution failed"}`);
|
|
1132
|
+
return { files: [] };
|
|
1094
1133
|
}
|
|
1095
1134
|
const files = (res.stdout || "").trim().split(/\r?\n/).filter((l) => l.length > 0);
|
|
1096
1135
|
return { files };
|
|
@@ -1099,13 +1138,22 @@ var LocalRipgrepProvider = class {
|
|
|
1099
1138
|
const abs = resolveUnderRepo(this.repoRoot, params.path);
|
|
1100
1139
|
const stat = await import_promises3.default.stat(abs).catch(() => null);
|
|
1101
1140
|
if (!stat || !stat.isFile()) {
|
|
1102
|
-
|
|
1141
|
+
return {
|
|
1142
|
+
lines: [],
|
|
1143
|
+
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.`
|
|
1144
|
+
};
|
|
1103
1145
|
}
|
|
1104
1146
|
if (isSymlink(abs)) {
|
|
1105
|
-
|
|
1147
|
+
return {
|
|
1148
|
+
lines: [],
|
|
1149
|
+
error: `[SYMLINK] You tried to read "${params.path}" but this is a symlink. Try reading the actual file it points to instead.`
|
|
1150
|
+
};
|
|
1106
1151
|
}
|
|
1107
1152
|
if (!isTextualFile(abs)) {
|
|
1108
|
-
|
|
1153
|
+
return {
|
|
1154
|
+
lines: [],
|
|
1155
|
+
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.`
|
|
1156
|
+
};
|
|
1109
1157
|
}
|
|
1110
1158
|
const lines = await readAllLines(abs);
|
|
1111
1159
|
const total = lines.length;
|