@ordewell/core 0.6.4 → 0.7.0

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 (45) hide show
  1. package/README.md +1 -1
  2. package/dist/{IFileSystem-DQEKyC6H.d.ts → IFileSystem-D4ADfTrX.d.ts} +1 -1
  3. package/dist/{IFileSystem-Qj2MWHn_.d.mts → IFileSystem-DgpX0BU7.d.mts} +1 -1
  4. package/dist/{ModeResolver-ByNpC0EP.d.ts → ModeResolver-BEcRAz1c.d.ts} +3 -3
  5. package/dist/{ModeResolver-rqaY_4Ex.d.mts → ModeResolver-Cv01ZDd9.d.mts} +3 -3
  6. package/dist/{Task-xqdxugt2.d.mts → Task-CoKhvBa1.d.mts} +275 -2
  7. package/dist/{Task-xqdxugt2.d.ts → Task-CoKhvBa1.d.ts} +275 -2
  8. package/dist/{chunk-M4KXBEFJ.mjs → chunk-J3YSTPCE.mjs} +41 -41
  9. package/dist/chunk-J3YSTPCE.mjs.map +1 -0
  10. package/dist/{chunk-I6U3PVHL.mjs → chunk-LSGY7AIZ.mjs} +74 -23
  11. package/dist/chunk-LSGY7AIZ.mjs.map +1 -0
  12. package/dist/{chunk-JRZPSNRO.mjs → chunk-YU4UKKKI.mjs} +1 -1
  13. package/dist/chunk-YU4UKKKI.mjs.map +1 -0
  14. package/dist/index.d.mts +250 -34
  15. package/dist/index.d.ts +250 -34
  16. package/dist/index.js +2002 -670
  17. package/dist/index.js.map +1 -1
  18. package/dist/index.mjs +1642 -366
  19. package/dist/index.mjs.map +1 -1
  20. package/dist/order-labels.d.mts +2 -1
  21. package/dist/order-labels.d.ts +2 -1
  22. package/dist/{parsing-DDZ1rUYa.d.mts → parsing-B4OCHH1_.d.mts} +24 -3
  23. package/dist/{parsing-COPG8-Ep.d.ts → parsing-DMdOq-BV.d.ts} +24 -3
  24. package/dist/parsing.d.mts +4 -3
  25. package/dist/parsing.d.ts +4 -3
  26. package/dist/parsing.js +36 -38
  27. package/dist/parsing.js.map +1 -1
  28. package/dist/parsing.mjs +2 -2
  29. package/dist/{plan-utils-Br8UAoiu.d.ts → plan-utils-BdYPRBno.d.ts} +28 -3
  30. package/dist/{plan-utils-DMgajMvd.d.mts → plan-utils-CD1Xu65s.d.mts} +28 -3
  31. package/dist/plan-utils.d.mts +4 -3
  32. package/dist/plan-utils.d.ts +4 -3
  33. package/dist/plan-utils.js +111 -58
  34. package/dist/plan-utils.js.map +1 -1
  35. package/dist/plan-utils.mjs +8 -2
  36. package/dist/testing.d.mts +11 -2
  37. package/dist/testing.d.ts +11 -2
  38. package/dist/testing.js +17 -0
  39. package/dist/testing.js.map +1 -1
  40. package/dist/testing.mjs +17 -0
  41. package/dist/testing.mjs.map +1 -1
  42. package/package.json +4 -2
  43. package/dist/chunk-I6U3PVHL.mjs.map +0 -1
  44. package/dist/chunk-JRZPSNRO.mjs.map +0 -1
  45. package/dist/chunk-M4KXBEFJ.mjs.map +0 -1
@@ -10,7 +10,7 @@ import {
10
10
  renumberTasks,
11
11
  stripTrailingCommas,
12
12
  updateTaskInPlan
13
- } from "./chunk-JRZPSNRO.mjs";
13
+ } from "./chunk-YU4UKKKI.mjs";
14
14
 
15
15
  // src/models/Usage.ts
16
16
  function partedPromptUsage(parts) {
@@ -77,6 +77,10 @@ var KNOWN_TOOLS = {
77
77
  list: "list_dir",
78
78
  fetch: "fetch"
79
79
  };
80
+ var FILE_EDIT_TOOLS = /* @__PURE__ */ new Set(["edit", "write", "multiedit", "notebookedit", "applypatch", "patch", "add", "update", "delete", "filechange"]);
81
+ function isFileEditTool(name) {
82
+ return FILE_EDIT_TOOLS.has(name.trim().toLowerCase().replace(/[_-]/g, ""));
83
+ }
80
84
  function mapAgentTool(name) {
81
85
  const normalized = name.trim().toLowerCase().replace(/[_-]/g, "");
82
86
  const direct = KNOWN_TOOLS[normalized] ?? KNOWN_TOOLS[name.trim().toLowerCase()];
@@ -272,13 +276,13 @@ function renderTerminalOutput(raw) {
272
276
  function renderCleanCapture(raw, doneToken) {
273
277
  const rendered = renderTerminalOutput(raw).replace(/[\s─-▟]+$/gm, "");
274
278
  if (!doneToken) return rendered.trim();
275
- const lines = rendered.split("\n");
279
+ const lines2 = rendered.split("\n");
276
280
  const flat = (s) => flattenTerminalOutput(s);
277
- for (let i = 0; i < lines.length; i++) {
278
- const own = flat(lines[i]).includes(doneToken);
279
- if (own) return lines.slice(0, i).join("\n").trim();
280
- const window = flat(lines[i]) + (i + 1 < lines.length ? flat(lines[i + 1]) : "");
281
- if (window.includes(doneToken)) return lines.slice(0, i + 1).join("\n").trim();
281
+ for (let i = 0; i < lines2.length; i++) {
282
+ const own = flat(lines2[i]).includes(doneToken);
283
+ if (own) return lines2.slice(0, i).join("\n").trim();
284
+ const window = flat(lines2[i]) + (i + 1 < lines2.length ? flat(lines2[i + 1]) : "");
285
+ if (window.includes(doneToken)) return lines2.slice(0, i + 1).join("\n").trim();
282
286
  }
283
287
  return rendered.trim();
284
288
  }
@@ -309,9 +313,9 @@ function oneLine(text2) {
309
313
  return text2.replace(/\s+/g, " ").trim();
310
314
  }
311
315
  function firstLineOf(command) {
312
- const lines = command.trim().split(/\r?\n/);
313
- const more = lines.length - 1;
314
- return more > 0 ? `${lines[0]} \u2026 +${more} line${more === 1 ? "" : "s"}` : lines[0];
316
+ const lines2 = command.trim().split(/\r?\n/);
317
+ const more = lines2.length - 1;
318
+ return more > 0 ? `${lines2[0]} \u2026 +${more} line${more === 1 ? "" : "s"}` : lines2[0];
315
319
  }
316
320
  function text(value) {
317
321
  return typeof value === "string" ? value : "";
@@ -358,14 +362,56 @@ function toolHeadline(tool, args, toolLabel) {
358
362
  return { name, keyArg: parsed ? keyArgOf(tool, parsed) : oneLine(args) };
359
363
  }
360
364
  function outputLines(output) {
361
- const lines = output.replace(/\r\n?/g, "\n").replace(ANSI_OR_CTRL_RE, "").split("\n");
362
- while (lines.length > 0 && lines[lines.length - 1].trim() === "") lines.pop();
363
- return lines;
365
+ const lines2 = output.replace(/\r\n?/g, "\n").replace(ANSI_OR_CTRL_RE, "").split("\n");
366
+ while (lines2.length > 0 && lines2[lines2.length - 1].trim() === "") lines2.pop();
367
+ return lines2;
364
368
  }
365
369
  function outputPreview(output, maxLines) {
366
- const lines = outputLines(output);
367
- const shown = lines.slice(0, Math.max(0, maxLines));
368
- return { lines: shown, hiddenLineCount: lines.length - shown.length };
370
+ const lines2 = outputLines(output);
371
+ const shown = lines2.slice(0, Math.max(0, maxLines));
372
+ return { lines: shown, hiddenLineCount: lines2.length - shown.length };
373
+ }
374
+ function diffStat(output) {
375
+ const lines2 = outputLines(output);
376
+ let added = 0;
377
+ let removed = 0;
378
+ for (const line of lines2) {
379
+ if (line.startsWith("+")) added += 1;
380
+ else if (line.startsWith("-")) removed += 1;
381
+ else if (!(line.startsWith("@@") || line.startsWith(" ") || line === "" || line.startsWith("\\"))) return null;
382
+ }
383
+ return added + removed > 0 ? { added, removed } : null;
384
+ }
385
+ var HUNK_RANGE = /^@@ -(\d+)(?:,\d+)? \+(\d+)(?:,\d+)? @@/;
386
+ function diffRows(output) {
387
+ const rows = [];
388
+ let oldLine = 1;
389
+ let newLine = 1;
390
+ for (const line of outputLines(output)) {
391
+ const range = HUNK_RANGE.exec(line);
392
+ if (range) {
393
+ if (rows.length > 0) rows.push({ kind: "gap", text: "" });
394
+ oldLine = Number(range[1]);
395
+ newLine = Number(range[2]);
396
+ } else if (line.startsWith("+")) {
397
+ rows.push({ kind: "added", line: newLine++, text: line.slice(1) });
398
+ } else if (line.startsWith("-")) {
399
+ rows.push({ kind: "removed", line: oldLine++, text: line.slice(1) });
400
+ } else if (!line.startsWith("\\")) {
401
+ rows.push({ kind: "context", line: newLine, text: line.slice(1) });
402
+ oldLine += 1;
403
+ newLine += 1;
404
+ }
405
+ }
406
+ return rows;
407
+ }
408
+ function lines(count) {
409
+ return `${count} line${count === 1 ? "" : "s"}`;
410
+ }
411
+ function diffSummary({ added, removed }) {
412
+ if (!removed) return `Added ${lines(added)}`;
413
+ if (!added) return `Removed ${lines(removed)}`;
414
+ return `Added ${lines(added)}, removed ${lines(removed)}`;
369
415
  }
370
416
 
371
417
  // src/conversation/records.ts
@@ -394,7 +440,8 @@ var STATUS_OF_OUTCOME = {
394
440
  not_executed: "interrupted"
395
441
  };
396
442
  function finishedTool(call, output, outcome) {
397
- return { ...call, status: STATUS_OF_OUTCOME[outcome], outcome, output, outputLineCount: outputLines(output).length };
443
+ const diff = outcome === "success" && isFileEditTool(call.toolLabel ?? call.tool) ? diffStat(output) : null;
444
+ return { ...call, status: STATUS_OF_OUTCOME[outcome], outcome, output, outputLineCount: outputLines(output).length, ...diff ? { diff } : {} };
398
445
  }
399
446
  function settledTool(call, step) {
400
447
  return finishedTool(call, step.result, step.outcome);
@@ -937,11 +984,11 @@ var UPDATABLE_FIELDS = [
937
984
  "sliceType",
938
985
  "ops"
939
986
  ];
940
- function taskOpsProtocol(executionNote = "") {
987
+ function taskOpsProtocol(executionNote = "", tools = false) {
941
988
  const updateChanges = UPDATABLE_FIELDS.map((f) => f === "dependencies" ? '"dependencies"?:["<id or #order>"]' : `"${f}"?`).join(",");
942
989
  return [
943
- "- To modify specific tasks, reply with ONLY this JSON object:",
944
- ' {"taskOps": [',
990
+ tools ? "- To modify specific tasks, call edit_plan, never a JSON reply. Its argument is:" : "- To modify specific tasks, reply with ONLY this JSON object:",
991
+ tools ? ' {"ops": [' : ' {"taskOps": [',
945
992
  ` {"op":"update","taskId":"<id or #order>","changes":{${updateChanges}}},`,
946
993
  ' {"op":"add","task":{"title","description","prompt","dependencies":["<id or #order>"],"assignedRunner"?,"assignedModel"?,"ops"?},"handle"?:"<name>"},',
947
994
  ' {"op":"remove","taskId":"<id or #order>"},',
@@ -950,11 +997,12 @@ function taskOpsProtocol(executionNote = "") {
950
997
  ' {"op":"split","taskId":"<id or #order>","parts":[{"title","description","prompt"?,"assignedRunner"?,"assignedModel"?,...}, ...],"handle"?:"<name>"},',
951
998
  ` {"op":"rearm","taskId":"<id or #order>","changes"?:{${updateChanges}}}`,
952
999
  " ]}",
953
- '- For sweeping changes, you may instead emit a full {"tasks":[...]} plan JSON.',
1000
+ tools ? "- For sweeping changes, you may instead call submit_plan with the full plan." : '- For sweeping changes, you may instead emit a full {"tasks":[...]} plan JSON.',
954
1001
  'Every "<id or #order>" ref in a batch resolves against the plan shown above, before any op in the batch runs \u2014 an earlier remove/merge/split never shifts what a later "#N" means.',
955
1002
  'Give "add", "merge", or "split" a "handle" (any name you choose, unused elsewhere in this batch) to let a LATER op in the same batch reference the task it produces \u2014 for "split", the handle names its last part. A handle used before its defining op is rejected.',
956
- 'When creating or changing tasks, set "assignedRunner" and "assignedModel" ({"modelId","modelLabel","thinkingEffort"?}) using only the runners and models listed in <available_models>.',
1003
+ `When creating or changing tasks, set "assignedRunner" and "assignedModel" ({"modelId","modelLabel","thinkingEffort"?}) using only the runners and models ${tools ? "list_runners and list_models return" : "listed in <available_models>"}.`,
957
1004
  'Keep dependencies consistent: no cycles, no references to removed tasks, and never touch running or completed tasks \u2014 "rearm" is the one exception, below.',
1005
+ ...tools ? ["edit_plan checks the batch when you call it and answers with what it will change, or with the error to fix \u2014 call it again in the same reply. The edit is applied when your reply ends; edits you make in one reply join one batch."] : [],
958
1006
  'Just declare the dependencies you want \u2014 display order is repaired for you afterwards, so a rewire or a newly added prerequisite never needs a "reorder" op. Only a task that is running or completed cannot be shifted, so an edit that would need one to move is rejected.' + executionNote,
959
1007
  'Flipping "type" between "ai" and "user" is a content change, not just a label: an update to "user" needs "userSteps" in the SAME op, and an update to "ai" needs "prompt" in the SAME op \u2014 the model/mode/effort/autonomy fields (flipping to "user") or the userSteps (flipping to "ai") are cleared automatically.',
960
1008
  '"rearm" puts a failed OR completed task back to pending \u2014 verdict and output summary are cleared, any dependents it had blocked are released, and it may carry field changes (e.g. a corrected "prompt") applied in the same op. A running task cannot be re-armed. Never rearm a task just to relabel it \u2014 only when it should actually run again.'
@@ -2090,6 +2138,9 @@ export {
2090
2138
  toolHeadline,
2091
2139
  outputLines,
2092
2140
  outputPreview,
2141
+ diffStat,
2142
+ diffRows,
2143
+ diffSummary,
2093
2144
  EMPTY_TASK_LOG,
2094
2145
  runnerToolSubject,
2095
2146
  reduceTaskLog,
@@ -2136,4 +2187,4 @@ export {
2136
2187
  hasHiddenDetail,
2137
2188
  taskStartedNotice
2138
2189
  };
2139
- //# sourceMappingURL=chunk-I6U3PVHL.mjs.map
2190
+ //# sourceMappingURL=chunk-LSGY7AIZ.mjs.map