@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.
Files changed (62) hide show
  1. package/dist/{chunk-4MELBN55.js → chunk-FYQUSDOE.js} +4 -4
  2. package/dist/{chunk-Z2FBMSNE.js → chunk-HQO45BAJ.js} +5 -1
  3. package/dist/chunk-HQO45BAJ.js.map +1 -0
  4. package/dist/{chunk-NRWVMX4O.js → chunk-L5BMGLLQ.js} +29 -22
  5. package/dist/chunk-L5BMGLLQ.js.map +1 -0
  6. package/dist/{chunk-SWQPIKPY.js → chunk-LVPVVLTI.js} +70 -49
  7. package/dist/chunk-LVPVVLTI.js.map +1 -0
  8. package/dist/{chunk-2TXLSKGU.js → chunk-MZT6HVGD.js} +3 -3
  9. package/dist/{chunk-DZRBTNQR.js → chunk-PZDR5ZZ2.js} +5 -5
  10. package/dist/{chunk-KH3RKPPO.js → chunk-UU6XCZG3.js} +4 -4
  11. package/dist/{chunk-5ASRBH5I.js → chunk-YR53PPVM.js} +4 -4
  12. package/dist/{chunk-MLDK7SCW.js → chunk-ZJIIICRA.js} +29 -7
  13. package/dist/chunk-ZJIIICRA.js.map +1 -0
  14. package/dist/client.cjs +116 -68
  15. package/dist/client.cjs.map +1 -1
  16. package/dist/client.js +13 -13
  17. package/dist/index.cjs +116 -68
  18. package/dist/index.cjs.map +1 -1
  19. package/dist/index.js +13 -13
  20. package/dist/tools/warp_grep/agent/parser.cjs +69 -48
  21. package/dist/tools/warp_grep/agent/parser.cjs.map +1 -1
  22. package/dist/tools/warp_grep/agent/parser.d.ts +2 -0
  23. package/dist/tools/warp_grep/agent/parser.js +1 -1
  24. package/dist/tools/warp_grep/agent/runner.cjs +88 -62
  25. package/dist/tools/warp_grep/agent/runner.cjs.map +1 -1
  26. package/dist/tools/warp_grep/agent/runner.js +7 -7
  27. package/dist/tools/warp_grep/agent/types.cjs.map +1 -1
  28. package/dist/tools/warp_grep/agent/types.d.ts +1 -1
  29. package/dist/tools/warp_grep/anthropic.cjs +116 -68
  30. package/dist/tools/warp_grep/anthropic.cjs.map +1 -1
  31. package/dist/tools/warp_grep/anthropic.js +10 -10
  32. package/dist/tools/warp_grep/index.cjs +116 -68
  33. package/dist/tools/warp_grep/index.cjs.map +1 -1
  34. package/dist/tools/warp_grep/index.js +12 -12
  35. package/dist/tools/warp_grep/openai.cjs +116 -68
  36. package/dist/tools/warp_grep/openai.cjs.map +1 -1
  37. package/dist/tools/warp_grep/openai.js +10 -10
  38. package/dist/tools/warp_grep/providers/local.cjs +28 -6
  39. package/dist/tools/warp_grep/providers/local.cjs.map +1 -1
  40. package/dist/tools/warp_grep/providers/local.js +1 -1
  41. package/dist/tools/warp_grep/providers/types.cjs.map +1 -1
  42. package/dist/tools/warp_grep/providers/types.d.ts +2 -0
  43. package/dist/tools/warp_grep/tools/grep.cjs +3 -0
  44. package/dist/tools/warp_grep/tools/grep.cjs.map +1 -1
  45. package/dist/tools/warp_grep/tools/grep.js +3 -0
  46. package/dist/tools/warp_grep/tools/grep.js.map +1 -1
  47. package/dist/tools/warp_grep/tools/read.cjs +4 -0
  48. package/dist/tools/warp_grep/tools/read.cjs.map +1 -1
  49. package/dist/tools/warp_grep/tools/read.js +1 -1
  50. package/dist/tools/warp_grep/vercel.cjs +116 -68
  51. package/dist/tools/warp_grep/vercel.cjs.map +1 -1
  52. package/dist/tools/warp_grep/vercel.js +10 -10
  53. package/package.json +1 -1
  54. package/dist/chunk-MLDK7SCW.js.map +0 -1
  55. package/dist/chunk-NRWVMX4O.js.map +0 -1
  56. package/dist/chunk-SWQPIKPY.js.map +0 -1
  57. package/dist/chunk-Z2FBMSNE.js.map +0 -1
  58. /package/dist/{chunk-4MELBN55.js.map → chunk-FYQUSDOE.js.map} +0 -0
  59. /package/dist/{chunk-2TXLSKGU.js.map → chunk-MZT6HVGD.js.map} +0 -0
  60. /package/dist/{chunk-DZRBTNQR.js.map → chunk-PZDR5ZZ2.js.map} +0 -0
  61. /package/dist/{chunk-KH3RKPPO.js.map → chunk-UU6XCZG3.js.map} +0 -0
  62. /package/dist/{chunk-5ASRBH5I.js.map → chunk-YR53PPVM.js.map} +0 -0
package/dist/client.cjs CHANGED
@@ -1103,12 +1103,6 @@ function getSystemPrompt() {
1103
1103
  }
1104
1104
 
1105
1105
  // tools/warp_grep/agent/parser.ts
1106
- var LLMResponseParseError = class extends Error {
1107
- constructor(message) {
1108
- super(message);
1109
- this.name = "LLMResponseParseError";
1110
- }
1111
- };
1112
1106
  var VALID_COMMANDS = ["analyse", "grep", "read", "finish"];
1113
1107
  function preprocessText(text) {
1114
1108
  let processed = text.replace(/<think>[\s\S]*?<\/think>/gi, "");
@@ -1159,24 +1153,23 @@ var LLMResponseParser = class {
1159
1153
  const lines = preprocessText(text);
1160
1154
  const commands = [];
1161
1155
  let finishAccumulator = null;
1162
- lines.forEach((line, idx) => {
1156
+ lines.forEach((line) => {
1163
1157
  if (!line || line.startsWith("#")) return;
1164
- const ctx = { lineNumber: idx + 1, raw: line };
1165
- const parts = this.splitLine(line, ctx);
1158
+ const parts = this.splitLine(line);
1166
1159
  if (parts.length === 0) return;
1167
1160
  const cmd = parts[0];
1168
1161
  switch (cmd) {
1169
1162
  case "analyse":
1170
- this.handleAnalyse(parts, ctx, commands);
1163
+ this.handleAnalyse(parts, line, commands);
1171
1164
  break;
1172
1165
  case "grep":
1173
- this.handleGrep(parts, ctx, commands);
1166
+ this.handleGrep(parts, line, commands);
1174
1167
  break;
1175
1168
  case "read":
1176
- this.handleRead(parts, ctx, commands);
1169
+ this.handleRead(parts, line, commands);
1177
1170
  break;
1178
1171
  case "finish":
1179
- finishAccumulator = this.handleFinish(parts, ctx, finishAccumulator);
1172
+ finishAccumulator = this.handleFinish(parts, line, commands, finishAccumulator);
1180
1173
  break;
1181
1174
  default:
1182
1175
  break;
@@ -1193,53 +1186,68 @@ var LLMResponseParser = class {
1193
1186
  }
1194
1187
  return commands;
1195
1188
  }
1196
- splitLine(line, ctx) {
1197
- try {
1198
- const parts = [];
1199
- let current = "";
1200
- let inSingle = false;
1201
- for (let i = 0; i < line.length; i++) {
1202
- const ch = line[i];
1203
- if (ch === "'" && line[i - 1] !== "\\") {
1204
- inSingle = !inSingle;
1205
- current += ch;
1206
- } else if (!inSingle && /\s/.test(ch)) {
1207
- if (current) {
1208
- parts.push(current);
1209
- current = "";
1210
- }
1211
- } else {
1212
- current += ch;
1189
+ splitLine(line) {
1190
+ const parts = [];
1191
+ let current = "";
1192
+ let inSingle = false;
1193
+ for (let i = 0; i < line.length; i++) {
1194
+ const ch = line[i];
1195
+ if (ch === "'" && line[i - 1] !== "\\") {
1196
+ inSingle = !inSingle;
1197
+ current += ch;
1198
+ } else if (!inSingle && /\s/.test(ch)) {
1199
+ if (current) {
1200
+ parts.push(current);
1201
+ current = "";
1213
1202
  }
1203
+ } else {
1204
+ current += ch;
1214
1205
  }
1215
- if (current) parts.push(current);
1216
- return parts;
1217
- } catch {
1218
- throw new LLMResponseParseError(`Line ${ctx.lineNumber}: Unable to parse line.`);
1219
1206
  }
1207
+ if (current) parts.push(current);
1208
+ return parts;
1209
+ }
1210
+ /** Helper to create a _skip tool call with an error message */
1211
+ skip(message) {
1212
+ return { name: "_skip", arguments: { message } };
1220
1213
  }
1221
- handleAnalyse(parts, ctx, commands) {
1214
+ handleAnalyse(parts, rawLine, commands) {
1222
1215
  if (parts.length < 2) {
1223
- throw new LLMResponseParseError(`Line ${ctx.lineNumber}: analyse requires <path>`);
1216
+ commands.push(this.skip(
1217
+ `[SKIPPED] Your command "${rawLine}" is missing a path. Correct format: analyse <path> [pattern]. Example: analyse src/`
1218
+ ));
1219
+ return;
1224
1220
  }
1225
1221
  const path4 = parts[1];
1226
1222
  const pattern = parts[2]?.replace(/^"|"$/g, "") ?? null;
1227
1223
  commands.push({ name: "analyse", arguments: { path: path4, pattern } });
1228
1224
  }
1229
1225
  // no glob tool in MCP
1230
- handleGrep(parts, ctx, commands) {
1226
+ handleGrep(parts, rawLine, commands) {
1231
1227
  if (parts.length < 3) {
1232
- throw new LLMResponseParseError(`Line ${ctx.lineNumber}: grep requires '<pattern>' and <path>`);
1228
+ commands.push(this.skip(
1229
+ `[SKIPPED] Your command "${rawLine}" is missing arguments. Correct format: grep '<pattern>' <path>. Example: grep 'TODO' src/`
1230
+ ));
1231
+ return;
1233
1232
  }
1234
- const pat = parts[1];
1235
- if (!pat.startsWith("'") || !pat.endsWith("'")) {
1236
- throw new LLMResponseParseError(`Line ${ctx.lineNumber}: grep pattern must be single-quoted`);
1233
+ let pat = parts[1];
1234
+ if (pat.startsWith("'") && pat.endsWith("'")) {
1235
+ pat = pat.slice(1, -1);
1237
1236
  }
1238
- commands.push({ name: "grep", arguments: { pattern: pat.slice(1, -1), path: parts[2] } });
1237
+ if (!pat) {
1238
+ commands.push(this.skip(
1239
+ `[SKIPPED] Your command "${rawLine}" has an empty pattern. Provide a non-empty search pattern. Example: grep 'function' src/`
1240
+ ));
1241
+ return;
1242
+ }
1243
+ commands.push({ name: "grep", arguments: { pattern: pat, path: parts[2] } });
1239
1244
  }
1240
- handleRead(parts, ctx, commands) {
1245
+ handleRead(parts, rawLine, commands) {
1241
1246
  if (parts.length < 2) {
1242
- throw new LLMResponseParseError(`Line ${ctx.lineNumber}: read requires <path> or <path>:<start-end>`);
1247
+ commands.push(this.skip(
1248
+ `[SKIPPED] Your command "${rawLine}" is missing a path. Correct format: read <path> or read <path>:<start>-<end>. Example: read src/index.ts:1-50`
1249
+ ));
1250
+ return;
1243
1251
  }
1244
1252
  const spec = parts[1];
1245
1253
  const rangeIdx = spec.indexOf(":");
@@ -1247,31 +1255,38 @@ var LLMResponseParser = class {
1247
1255
  commands.push({ name: "read", arguments: { path: spec } });
1248
1256
  return;
1249
1257
  }
1250
- const path4 = spec.slice(0, rangeIdx);
1258
+ const filePath = spec.slice(0, rangeIdx);
1251
1259
  const range = spec.slice(rangeIdx + 1);
1252
1260
  const [s, e] = range.split("-").map((v) => parseInt(v, 10));
1253
1261
  if (!Number.isFinite(s) || !Number.isFinite(e)) {
1254
- throw new LLMResponseParseError(`Line ${ctx.lineNumber}: invalid read range '${range}'`);
1262
+ commands.push({ name: "read", arguments: { path: filePath } });
1263
+ return;
1255
1264
  }
1256
- commands.push({ name: "read", arguments: { path: path4, start: s, end: e } });
1265
+ commands.push({ name: "read", arguments: { path: filePath, start: s, end: e } });
1257
1266
  }
1258
- handleFinish(parts, ctx, acc) {
1267
+ handleFinish(parts, rawLine, commands, acc) {
1259
1268
  const map = acc ?? /* @__PURE__ */ new Map();
1260
1269
  const args = parts.slice(1);
1261
1270
  for (const token of args) {
1262
- const [path4, rangesText] = token.split(":", 2);
1263
- if (!path4 || !rangesText) {
1264
- throw new LLMResponseParseError(`Line ${ctx.lineNumber}: invalid finish token '${token}'`);
1271
+ const [filePath, rangesText] = token.split(":", 2);
1272
+ if (!filePath || !rangesText) {
1273
+ commands.push(this.skip(
1274
+ `[SKIPPED] Invalid finish token "${token}". Correct format: finish <path>:<start>-<end>. Example: finish src/index.ts:1-50`
1275
+ ));
1276
+ continue;
1265
1277
  }
1266
1278
  const rangeSpecs = rangesText.split(",").filter(Boolean);
1267
1279
  for (const spec of rangeSpecs) {
1268
1280
  const [s, e] = spec.split("-").map((v) => parseInt(v, 10));
1269
1281
  if (!Number.isFinite(s) || !Number.isFinite(e) || e < s) {
1270
- throw new LLMResponseParseError(`Line ${ctx.lineNumber}: invalid range '${spec}'`);
1282
+ commands.push(this.skip(
1283
+ `[SKIPPED] Invalid range "${spec}" in "${token}". Ranges must be <start>-<end> where start <= end. Example: 1-50`
1284
+ ));
1285
+ continue;
1271
1286
  }
1272
- const arr = map.get(path4) ?? [];
1287
+ const arr = map.get(filePath) ?? [];
1273
1288
  arr.push([s, e]);
1274
- map.set(path4, arr);
1289
+ map.set(filePath, arr);
1275
1290
  }
1276
1291
  }
1277
1292
  return map;
@@ -1281,6 +1296,10 @@ var LLMResponseParser = class {
1281
1296
  // tools/warp_grep/tools/read.ts
1282
1297
  async function toolRead(provider, args) {
1283
1298
  const res = await provider.read({ path: args.path, start: args.start, end: args.end });
1299
+ if (res.error) {
1300
+ return res.error;
1301
+ }
1302
+ if (!res.lines.length) return "(empty file)";
1284
1303
  return res.lines.join("\n");
1285
1304
  }
1286
1305
 
@@ -1592,14 +1611,7 @@ async function runWarpGrep(config) {
1592
1611
  });
1593
1612
  if (!assistantContent) break;
1594
1613
  messages.push({ role: "assistant", content: assistantContent });
1595
- let toolCalls = [];
1596
- try {
1597
- toolCalls = parser.parse(assistantContent);
1598
- } catch (e) {
1599
- errors.push({ message: e instanceof Error ? e.message : String(e) });
1600
- terminationReason = "terminated";
1601
- break;
1602
- }
1614
+ const toolCalls = parser.parse(assistantContent);
1603
1615
  if (toolCalls.length === 0) {
1604
1616
  errors.push({ message: "No tool calls produced by the model." });
1605
1617
  terminationReason = "terminated";
@@ -1609,7 +1621,12 @@ async function runWarpGrep(config) {
1609
1621
  const grepCalls = toolCalls.filter((c) => c.name === "grep");
1610
1622
  const analyseCalls = toolCalls.filter((c) => c.name === "analyse");
1611
1623
  const readCalls = toolCalls.filter((c) => c.name === "read");
1624
+ const skipCalls = toolCalls.filter((c) => c.name === "_skip");
1612
1625
  const formatted = [];
1626
+ for (const c of skipCalls) {
1627
+ const msg = c.arguments?.message || "Command skipped due to parsing error";
1628
+ formatted.push(msg);
1629
+ }
1613
1630
  const otherPromises = [];
1614
1631
  for (const c of analyseCalls) {
1615
1632
  const args = c.arguments ?? {};
@@ -1635,6 +1652,15 @@ async function runWarpGrep(config) {
1635
1652
  const args = c.arguments ?? {};
1636
1653
  try {
1637
1654
  const grepRes = await provider.grep({ pattern: args.pattern, path: args.path });
1655
+ if (grepRes.error) {
1656
+ errors.push({ message: grepRes.error });
1657
+ terminationReason = "terminated";
1658
+ return {
1659
+ terminationReason: "terminated",
1660
+ messages,
1661
+ errors
1662
+ };
1663
+ }
1638
1664
  const rawOutput = Array.isArray(grepRes.lines) ? grepRes.lines.join("\n") : "";
1639
1665
  const newMatches = parseAndFilterGrepOutput(rawOutput, grepState);
1640
1666
  let formattedPayload = formatTurnGrepOutput(newMatches);
@@ -1846,10 +1872,22 @@ var LocalRipgrepProvider = class {
1846
1872
  ];
1847
1873
  const res = await runRipgrep(args, { cwd: this.repoRoot });
1848
1874
  if (res.exitCode === -1) {
1849
- throw new Error(res.stderr || "ripgrep (rg) execution failed.");
1875
+ return {
1876
+ lines: [],
1877
+ error: `[RIPGREP NOT AVAILABLE] ripgrep (rg) is required but failed to execute. Please install it:
1878
+ \u2022 macOS: brew install ripgrep
1879
+ \u2022 Ubuntu/Debian: apt install ripgrep
1880
+ \u2022 Windows: choco install ripgrep
1881
+ \u2022 Or visit: https://github.com/BurntSushi/ripgrep#installation
1882
+ Exit code: ${res.exitCode}${res.stderr ? `
1883
+ Details: ${res.stderr}` : ""}`
1884
+ };
1850
1885
  }
1851
1886
  if (res.exitCode !== 0 && res.exitCode !== 1) {
1852
- throw new Error(res.stderr || `ripgrep failed with code ${res.exitCode}`);
1887
+ return {
1888
+ lines: [],
1889
+ error: `[RIPGREP ERROR] grep failed with exit code ${res.exitCode}${res.stderr ? `: ${res.stderr}` : ""}`
1890
+ };
1853
1891
  }
1854
1892
  const lines = (res.stdout || "").trim().split(/\r?\n/).filter((l) => l.length > 0);
1855
1893
  return { lines };
@@ -1867,7 +1905,8 @@ var LocalRipgrepProvider = class {
1867
1905
  ];
1868
1906
  const res = await runRipgrep(args, { cwd: this.repoRoot });
1869
1907
  if (res.exitCode === -1) {
1870
- throw new Error(res.stderr || "ripgrep (rg) execution failed.");
1908
+ console.warn(`[warp_grep] ripgrep not available for glob: ${res.stderr || "execution failed"}`);
1909
+ return { files: [] };
1871
1910
  }
1872
1911
  const files = (res.stdout || "").trim().split(/\r?\n/).filter((l) => l.length > 0);
1873
1912
  return { files };
@@ -1876,13 +1915,22 @@ var LocalRipgrepProvider = class {
1876
1915
  const abs = resolveUnderRepo(this.repoRoot, params.path);
1877
1916
  const stat = await import_promises4.default.stat(abs).catch(() => null);
1878
1917
  if (!stat || !stat.isFile()) {
1879
- throw new Error(`Path is not a file: ${params.path}`);
1918
+ return {
1919
+ lines: [],
1920
+ 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.`
1921
+ };
1880
1922
  }
1881
1923
  if (isSymlink(abs)) {
1882
- throw new Error(`Refusing to read symlink: ${params.path}`);
1924
+ return {
1925
+ lines: [],
1926
+ error: `[SYMLINK] You tried to read "${params.path}" but this is a symlink. Try reading the actual file it points to instead.`
1927
+ };
1883
1928
  }
1884
1929
  if (!isTextualFile(abs)) {
1885
- throw new Error(`Non-text or too-large file: ${params.path}`);
1930
+ return {
1931
+ lines: [],
1932
+ 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.`
1933
+ };
1886
1934
  }
1887
1935
  const lines = await readAllLines(abs);
1888
1936
  const total = lines.length;