@ordewell/core 0.6.4 → 0.7.1

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 (54) hide show
  1. package/README.md +1 -1
  2. package/dist/{IFileSystem-Qj2MWHn_.d.mts → IFileSystem-BnLh-_SK.d.mts} +1 -1
  3. package/dist/{IFileSystem-DQEKyC6H.d.ts → IFileSystem-DofiRcCo.d.ts} +1 -1
  4. package/dist/{ModeResolver-rqaY_4Ex.d.mts → ModeResolver-DZzJSdIU.d.mts} +3 -3
  5. package/dist/{ModeResolver-ByNpC0EP.d.ts → ModeResolver-DkMYf4uS.d.ts} +3 -3
  6. package/dist/{Task-xqdxugt2.d.mts → Task-BnLxkVQF.d.mts} +414 -22
  7. package/dist/{Task-xqdxugt2.d.ts → Task-BnLxkVQF.d.ts} +414 -22
  8. package/dist/{chunk-JRZPSNRO.mjs → chunk-LGQNXPBX.mjs} +10 -2
  9. package/dist/chunk-LGQNXPBX.mjs.map +1 -0
  10. package/dist/{chunk-N66ZHFGN.mjs → chunk-OYUSADFM.mjs} +11 -1
  11. package/dist/chunk-OYUSADFM.mjs.map +1 -0
  12. package/dist/{chunk-HPNUFBIT.mjs → chunk-V3JHS7AX.mjs} +9 -1
  13. package/dist/chunk-V3JHS7AX.mjs.map +1 -0
  14. package/dist/{chunk-I6U3PVHL.mjs → chunk-Y36NIASW.mjs} +255 -32
  15. package/dist/chunk-Y36NIASW.mjs.map +1 -0
  16. package/dist/{chunk-M4KXBEFJ.mjs → chunk-ZV5LDNCO.mjs} +44 -43
  17. package/dist/chunk-ZV5LDNCO.mjs.map +1 -0
  18. package/dist/index.d.mts +518 -238
  19. package/dist/index.d.ts +518 -238
  20. package/dist/index.js +3925 -1568
  21. package/dist/index.js.map +1 -1
  22. package/dist/index.mjs +3525 -1393
  23. package/dist/index.mjs.map +1 -1
  24. package/dist/order-labels.d.mts +16 -2
  25. package/dist/order-labels.d.ts +16 -2
  26. package/dist/order-labels.js +12 -2
  27. package/dist/order-labels.js.map +1 -1
  28. package/dist/order-labels.mjs +7 -3
  29. package/dist/{parsing-DDZ1rUYa.d.mts → parsing-B6ctfF80.d.mts} +24 -3
  30. package/dist/{parsing-COPG8-Ep.d.ts → parsing-ddZXZFP4.d.ts} +24 -3
  31. package/dist/parsing.d.mts +4 -3
  32. package/dist/parsing.d.ts +4 -3
  33. package/dist/parsing.js +42 -41
  34. package/dist/parsing.js.map +1 -1
  35. package/dist/parsing.mjs +3 -3
  36. package/dist/{plan-utils-Br8UAoiu.d.ts → plan-utils--kQRzSE-.d.ts} +251 -7
  37. package/dist/{plan-utils-DMgajMvd.d.mts → plan-utils-CKgNtDwQ.d.mts} +251 -7
  38. package/dist/plan-utils.d.mts +5 -3
  39. package/dist/plan-utils.d.ts +5 -3
  40. package/dist/plan-utils.js +313 -61
  41. package/dist/plan-utils.js.map +1 -1
  42. package/dist/plan-utils.mjs +46 -3
  43. package/dist/testing.d.mts +26 -5
  44. package/dist/testing.d.ts +26 -5
  45. package/dist/testing.js +62 -2
  46. package/dist/testing.js.map +1 -1
  47. package/dist/testing.mjs +62 -4
  48. package/dist/testing.mjs.map +1 -1
  49. package/package.json +4 -2
  50. package/dist/chunk-HPNUFBIT.mjs.map +0 -1
  51. package/dist/chunk-I6U3PVHL.mjs.map +0 -1
  52. package/dist/chunk-JRZPSNRO.mjs.map +0 -1
  53. package/dist/chunk-M4KXBEFJ.mjs.map +0 -1
  54. package/dist/chunk-N66ZHFGN.mjs.map +0 -1
@@ -1,5 +1,7 @@
1
- export { a as ApprovalBlock, b as ApprovalStatus, C as CHECKPOINT_TRUNCATE_LENGTH, c as ConversationInput, d as ConversationView, D as DisplayBlock, E as EMPTY_CONVERSATION, e as EMPTY_HOLD, f as EMPTY_TASK_LOG, G as GatedConversation, L as LocalEntry, g as MessageBlock, h as MessageRole, N as NO_TURN, O as OutputPreview, P as PlanBlock, i as PlanMarkerStatus, j as PromptHold, p as SubagentBlock, q as SubagentChild, r as SubagentStatus, T as TakenPrompt, t as TaskLogView, v as TaskRef, w as ThinkingDisplayBlock, x as ToolBlock, y as ToolHeadline, z as ToolStatus, B as TurnGate, U as UsageBlock, F as aheadOfDraft, I as canMergeTasks, J as canSetDependencies, K as canSplitTask, Q as capConflictFiles, W as dependencyCandidates, X as dependentsOf, Z as drainNext, $ as followTurn, a0 as fromTranscript, a1 as hasHiddenDetail, a2 as holdPrompt, a3 as outputLines, a4 as outputPreview, a6 as reduceConversation, a7 as reduceTaskLog, a8 as replayTaskLog, a9 as runnerToolSubject, ad as stopTurn, ae as summarizeToolCall, af as taskStartedNotice, ai as toolHeadline, ak as truncateCheckpointSummary, al as unsendAll, am as unsendLatest } from './plan-utils-DMgajMvd.mjs';
2
- import './Task-xqdxugt2.mjs';
1
+ export { a as ApprovalBlock, b as ApprovalStatus, C as CHECKPOINT_TRUNCATE_LENGTH, c as ConversationInput, d as ConversationView, D as DiffRow, e as DiffRowKind, f as DiffStat, g as DisplayBlock, E as EMPTY_CONVERSATION, h as EMPTY_HOLD, i as EMPTY_TASK_LOG, G as GatedConversation, L as LocalEntry, j as MessageBlock, k as MessageRole, N as NOT_STARTED, l as NO_TURN, m as NewTaskFields, O as OutputPreview, P as PlanBlock, n as PlanMarkerStatus, o as PromptHold, u as SubagentBlock, v as SubagentChild, w as SubagentStatus, T as TakenPrompt, y as TaskLogView, B as TaskRef, F as TaskRowAction, H as TaskRowContext, I as TaskRowIsolation, J as TaskRowKind, K as TaskRowPlacement, Q as TaskRowSubject, R as TaskRowView, U as TaskStatusKind, V as ThinkingDisplayBlock, W as ToolBlock, X as ToolHeadline, Y as ToolStatus, Z as TurnGate, _ as UsageBlock, $ as aheadOfDraft, a1 as approvalLabel, a2 as awaitingLabel, a3 as canMergeTasks, a4 as canSetDependencies, a5 as canSplitTask, a6 as capConflictFiles, a9 as dependencyCandidates, aa as dependentsNotice, ab as dependentsOf, ac as diffRows, ad as diffStat, ae as diffSummary, ag as drainNext, ai as followTurn, aj as fromTranscript, ak as hasHiddenDetail, al as holdPrompt, am as isTaskRunning, an as markAction, ao as markRequestFor, ap as namedRepos, aq as newTaskFields, ar as opsEditable, as as outputLines, at as outputPreview, av as pastGateConfirmation, aw as reduceConversation, ax as reduceTaskLog, ay as replayTaskLog, az as runnerToolSubject, aD as stopTurn, aE as summarizeToolCall, aF as taskRowActions, aG as taskRowView, aH as taskStartedNotice, aI as taskStatusKind, aK as titledRefs, aM as toolHeadline, aO as truncateCheckpointSummary, aP as unsendAll, aQ as unsendLatest } from './plan-utils-CKgNtDwQ.mjs';
2
+ export { taskOrderLabel, taskRef, titledTaskRef } from './order-labels.mjs';
3
+ import './Task-BnLxkVQF.mjs';
3
4
  import 'child_process';
4
5
  import 'events';
5
- import './ModeResolver-rqaY_4Ex.mjs';
6
+ import 'zod/v4';
7
+ import './ModeResolver-DZzJSdIU.mjs';
@@ -1,5 +1,7 @@
1
- export { a as ApprovalBlock, b as ApprovalStatus, C as CHECKPOINT_TRUNCATE_LENGTH, c as ConversationInput, d as ConversationView, D as DisplayBlock, E as EMPTY_CONVERSATION, e as EMPTY_HOLD, f as EMPTY_TASK_LOG, G as GatedConversation, L as LocalEntry, g as MessageBlock, h as MessageRole, N as NO_TURN, O as OutputPreview, P as PlanBlock, i as PlanMarkerStatus, j as PromptHold, p as SubagentBlock, q as SubagentChild, r as SubagentStatus, T as TakenPrompt, t as TaskLogView, v as TaskRef, w as ThinkingDisplayBlock, x as ToolBlock, y as ToolHeadline, z as ToolStatus, B as TurnGate, U as UsageBlock, F as aheadOfDraft, I as canMergeTasks, J as canSetDependencies, K as canSplitTask, Q as capConflictFiles, W as dependencyCandidates, X as dependentsOf, Z as drainNext, $ as followTurn, a0 as fromTranscript, a1 as hasHiddenDetail, a2 as holdPrompt, a3 as outputLines, a4 as outputPreview, a6 as reduceConversation, a7 as reduceTaskLog, a8 as replayTaskLog, a9 as runnerToolSubject, ad as stopTurn, ae as summarizeToolCall, af as taskStartedNotice, ai as toolHeadline, ak as truncateCheckpointSummary, al as unsendAll, am as unsendLatest } from './plan-utils-Br8UAoiu.js';
2
- import './Task-xqdxugt2.js';
1
+ export { a as ApprovalBlock, b as ApprovalStatus, C as CHECKPOINT_TRUNCATE_LENGTH, c as ConversationInput, d as ConversationView, D as DiffRow, e as DiffRowKind, f as DiffStat, g as DisplayBlock, E as EMPTY_CONVERSATION, h as EMPTY_HOLD, i as EMPTY_TASK_LOG, G as GatedConversation, L as LocalEntry, j as MessageBlock, k as MessageRole, N as NOT_STARTED, l as NO_TURN, m as NewTaskFields, O as OutputPreview, P as PlanBlock, n as PlanMarkerStatus, o as PromptHold, u as SubagentBlock, v as SubagentChild, w as SubagentStatus, T as TakenPrompt, y as TaskLogView, B as TaskRef, F as TaskRowAction, H as TaskRowContext, I as TaskRowIsolation, J as TaskRowKind, K as TaskRowPlacement, Q as TaskRowSubject, R as TaskRowView, U as TaskStatusKind, V as ThinkingDisplayBlock, W as ToolBlock, X as ToolHeadline, Y as ToolStatus, Z as TurnGate, _ as UsageBlock, $ as aheadOfDraft, a1 as approvalLabel, a2 as awaitingLabel, a3 as canMergeTasks, a4 as canSetDependencies, a5 as canSplitTask, a6 as capConflictFiles, a9 as dependencyCandidates, aa as dependentsNotice, ab as dependentsOf, ac as diffRows, ad as diffStat, ae as diffSummary, ag as drainNext, ai as followTurn, aj as fromTranscript, ak as hasHiddenDetail, al as holdPrompt, am as isTaskRunning, an as markAction, ao as markRequestFor, ap as namedRepos, aq as newTaskFields, ar as opsEditable, as as outputLines, at as outputPreview, av as pastGateConfirmation, aw as reduceConversation, ax as reduceTaskLog, ay as replayTaskLog, az as runnerToolSubject, aD as stopTurn, aE as summarizeToolCall, aF as taskRowActions, aG as taskRowView, aH as taskStartedNotice, aI as taskStatusKind, aK as titledRefs, aM as toolHeadline, aO as truncateCheckpointSummary, aP as unsendAll, aQ as unsendLatest } from './plan-utils--kQRzSE-.js';
2
+ export { taskOrderLabel, taskRef, titledTaskRef } from './order-labels.js';
3
+ import './Task-BnLxkVQF.js';
3
4
  import 'child_process';
4
5
  import 'events';
5
- import './ModeResolver-ByNpC0EP.js';
6
+ import 'zod/v4';
7
+ import './ModeResolver-DkMYf4uS.js';
@@ -24,28 +24,49 @@ __export(plan_utils_exports, {
24
24
  EMPTY_CONVERSATION: () => EMPTY_CONVERSATION,
25
25
  EMPTY_HOLD: () => EMPTY_HOLD,
26
26
  EMPTY_TASK_LOG: () => EMPTY_TASK_LOG,
27
+ NOT_STARTED: () => NOT_STARTED,
27
28
  NO_TURN: () => NO_TURN,
28
29
  aheadOfDraft: () => aheadOfDraft,
30
+ approvalLabel: () => approvalLabel,
31
+ awaitingLabel: () => awaitingLabel,
29
32
  canMergeTasks: () => canMergeTasks,
30
33
  canSetDependencies: () => canSetDependencies,
31
34
  canSplitTask: () => canSplitTask,
32
35
  capConflictFiles: () => capConflictFiles,
33
36
  dependencyCandidates: () => dependencyCandidates,
37
+ dependentsNotice: () => dependentsNotice,
34
38
  dependentsOf: () => dependentsOf,
39
+ diffRows: () => diffRows,
40
+ diffStat: () => diffStat,
41
+ diffSummary: () => diffSummary,
35
42
  drainNext: () => drainNext,
36
43
  followTurn: () => followTurn,
37
44
  fromTranscript: () => fromTranscript,
38
45
  hasHiddenDetail: () => hasHiddenDetail,
39
46
  holdPrompt: () => holdPrompt,
47
+ isTaskRunning: () => isTaskRunning,
48
+ markAction: () => markAction,
49
+ markRequestFor: () => markRequestFor,
50
+ namedRepos: () => namedRepos,
51
+ newTaskFields: () => newTaskFields,
52
+ opsEditable: () => opsEditable,
40
53
  outputLines: () => outputLines,
41
54
  outputPreview: () => outputPreview,
55
+ pastGateConfirmation: () => pastGateConfirmation,
42
56
  reduceConversation: () => reduceConversation,
43
57
  reduceTaskLog: () => reduceTaskLog,
44
58
  replayTaskLog: () => replayTaskLog,
45
59
  runnerToolSubject: () => runnerToolSubject,
46
60
  stopTurn: () => stopTurn,
47
61
  summarizeToolCall: () => summarizeToolCall,
62
+ taskOrderLabel: () => taskOrderLabel,
63
+ taskRef: () => taskRef,
64
+ taskRowActions: () => taskRowActions,
65
+ taskRowView: () => taskRowView,
48
66
  taskStartedNotice: () => taskStartedNotice,
67
+ taskStatusKind: () => taskStatusKind,
68
+ titledRefs: () => titledRefs,
69
+ titledTaskRef: () => titledTaskRef,
49
70
  toolHeadline: () => toolHeadline,
50
71
  truncateCheckpointSummary: () => truncateCheckpointSummary,
51
72
  unsendAll: () => unsendAll,
@@ -55,6 +76,50 @@ module.exports = __toCommonJS(plan_utils_exports);
55
76
 
56
77
  // src/services/TaskOps.ts
57
78
  var import_uuid = require("uuid");
79
+
80
+ // src/order-labels.ts
81
+ function taskOrderLabel(task, parent) {
82
+ return parent ? `${parent.order}.${task.order}` : String(task.order);
83
+ }
84
+ function taskRef(task, parent) {
85
+ return `#${taskOrderLabel(task, parent)}`;
86
+ }
87
+ function titledTaskRef(task, parent) {
88
+ return `${taskRef(task, parent)} ${task.title}`;
89
+ }
90
+
91
+ // src/taskRow/status.ts
92
+ var isTaskRunning = (task) => task.status === "in_progress" || task.status === "running";
93
+ var NOT_STARTED = /* @__PURE__ */ new Set(["pending", "approved", "blocked"]);
94
+ function taskStatusKind(task) {
95
+ switch (task.status) {
96
+ case "completed":
97
+ return "done";
98
+ case "failed":
99
+ return "failed";
100
+ case "blocked":
101
+ return "blocked";
102
+ case "awaiting_user":
103
+ return "awaiting";
104
+ }
105
+ if (!isTaskRunning(task)) return "todo";
106
+ return task.status === "in_progress" && task.idleSince ? "quiet" : "running";
107
+ }
108
+ var AWAITING_LABELS = {
109
+ input: "Waiting for your input",
110
+ checkpoint: "Checkpoint",
111
+ conflict: "Merge conflict",
112
+ "files-changed": "Changed tracked files"
113
+ };
114
+ function awaitingLabel(task) {
115
+ return task.status === "awaiting_user" && task.awaitingReason ? AWAITING_LABELS[task.awaitingReason] : null;
116
+ }
117
+ function approvalLabel(count) {
118
+ if (!count) return null;
119
+ return count > 1 ? `Waiting for approval (${count})` : "Waiting for approval";
120
+ }
121
+
122
+ // src/services/TaskOps.ts
58
123
  function detectCycle(tasks) {
59
124
  const byId = new Map(tasks.map((t) => [t.id, t]));
60
125
  const visiting = /* @__PURE__ */ new Set();
@@ -268,9 +333,9 @@ function oneLine(text2) {
268
333
  return text2.replace(/\s+/g, " ").trim();
269
334
  }
270
335
  function firstLineOf(command) {
271
- const lines = command.trim().split(/\r?\n/);
272
- const more = lines.length - 1;
273
- return more > 0 ? `${lines[0]} \u2026 +${more} line${more === 1 ? "" : "s"}` : lines[0];
336
+ const lines2 = command.trim().split(/\r?\n/);
337
+ const more = lines2.length - 1;
338
+ return more > 0 ? `${lines2[0]} \u2026 +${more} line${more === 1 ? "" : "s"}` : lines2[0];
274
339
  }
275
340
  function text(value) {
276
341
  return typeof value === "string" ? value : "";
@@ -317,14 +382,108 @@ function toolHeadline(tool, args, toolLabel) {
317
382
  return { name, keyArg: parsed ? keyArgOf(tool, parsed) : oneLine(args) };
318
383
  }
319
384
  function outputLines(output) {
320
- const lines = output.replace(/\r\n?/g, "\n").replace(ANSI_OR_CTRL_RE, "").split("\n");
321
- while (lines.length > 0 && lines[lines.length - 1].trim() === "") lines.pop();
322
- return lines;
385
+ const lines2 = output.replace(/\r\n?/g, "\n").replace(ANSI_OR_CTRL_RE, "").split("\n");
386
+ while (lines2.length > 0 && lines2[lines2.length - 1].trim() === "") lines2.pop();
387
+ return lines2;
323
388
  }
324
389
  function outputPreview(output, maxLines) {
325
- const lines = outputLines(output);
326
- const shown = lines.slice(0, Math.max(0, maxLines));
327
- return { lines: shown, hiddenLineCount: lines.length - shown.length };
390
+ const lines2 = outputLines(output);
391
+ const shown = lines2.slice(0, Math.max(0, maxLines));
392
+ return { lines: shown, hiddenLineCount: lines2.length - shown.length };
393
+ }
394
+ function diffStat(output) {
395
+ const lines2 = outputLines(output);
396
+ let added = 0;
397
+ let removed = 0;
398
+ for (const line of lines2) {
399
+ if (line.startsWith("+")) added += 1;
400
+ else if (line.startsWith("-")) removed += 1;
401
+ else if (!(line.startsWith("@@") || line.startsWith(" ") || line === "" || line.startsWith("\\"))) return null;
402
+ }
403
+ return added + removed > 0 ? { added, removed } : null;
404
+ }
405
+ var HUNK_RANGE = /^@@ -(\d+)(?:,\d+)? \+(\d+)(?:,\d+)? @@/;
406
+ function diffRows(output) {
407
+ const rows = [];
408
+ let oldLine = 1;
409
+ let newLine = 1;
410
+ for (const line of outputLines(output)) {
411
+ const range = HUNK_RANGE.exec(line);
412
+ if (range) {
413
+ if (rows.length > 0) rows.push({ kind: "gap", text: "" });
414
+ oldLine = Number(range[1]);
415
+ newLine = Number(range[2]);
416
+ } else if (line.startsWith("+")) {
417
+ rows.push({ kind: "added", line: newLine++, text: line.slice(1) });
418
+ } else if (line.startsWith("-")) {
419
+ rows.push({ kind: "removed", line: oldLine++, text: line.slice(1) });
420
+ } else if (!line.startsWith("\\")) {
421
+ rows.push({ kind: "context", line: newLine, text: line.slice(1) });
422
+ oldLine += 1;
423
+ newLine += 1;
424
+ }
425
+ }
426
+ return rows;
427
+ }
428
+ function lines(count) {
429
+ return `${count} line${count === 1 ? "" : "s"}`;
430
+ }
431
+ function diffSummary({ added, removed }) {
432
+ if (!removed) return `Added ${lines(added)}`;
433
+ if (!added) return `Removed ${lines(removed)}`;
434
+ return `Added ${lines(added)}, removed ${lines(removed)}`;
435
+ }
436
+
437
+ // src/services/harness/agentTools.ts
438
+ var KNOWN_TOOLS = {
439
+ // Claude Code
440
+ read: "read_file",
441
+ grep: "grep",
442
+ glob: "glob",
443
+ bash: "bash",
444
+ ls: "list_dir",
445
+ webfetch: "fetch",
446
+ websearch: "web_search",
447
+ // Codex — its sandboxed command tool is a shell by another name
448
+ shell: "bash",
449
+ exec_command: "bash",
450
+ local_shell: "bash",
451
+ // OpenCode
452
+ list: "list_dir",
453
+ fetch: "fetch"
454
+ };
455
+ var FILE_EDIT_TOOLS = /* @__PURE__ */ new Set(["edit", "write", "multiedit", "notebookedit", "applypatch", "patch", "add", "update", "delete", "filechange"]);
456
+ function isFileEditTool(name) {
457
+ return FILE_EDIT_TOOLS.has(name.trim().toLowerCase().replace(/[_-]/g, ""));
458
+ }
459
+ function mapAgentTool(name) {
460
+ const normalized = name.trim().toLowerCase().replace(/[_-]/g, "");
461
+ const direct = KNOWN_TOOLS[normalized] ?? KNOWN_TOOLS[name.trim().toLowerCase()];
462
+ if (direct) {
463
+ return { tool: direct, toolLabel: name };
464
+ }
465
+ return { tool: "agent_tool", toolLabel: name };
466
+ }
467
+ function normalizeAgentArgs(tool, args) {
468
+ const out = { ...args };
469
+ const alias = (from, to) => {
470
+ if (out[to] === void 0 && out[from] !== void 0) out[to] = out[from];
471
+ };
472
+ if (tool === "read_file" || tool === "list_dir") {
473
+ alias("filePath", "path");
474
+ alias("file_path", "path");
475
+ alias("target", "path");
476
+ }
477
+ if (tool === "bash") {
478
+ alias("cmd", "command");
479
+ alias("script", "command");
480
+ if (typeof out.command !== "string" && Array.isArray(out.command)) {
481
+ out.command = out.command.join(" ");
482
+ }
483
+ }
484
+ if (tool === "fetch") alias("uri", "url");
485
+ if (tool === "web_search") alias("q", "query");
486
+ return out;
328
487
  }
329
488
 
330
489
  // src/conversation/records.ts
@@ -353,7 +512,8 @@ var STATUS_OF_OUTCOME = {
353
512
  not_executed: "interrupted"
354
513
  };
355
514
  function finishedTool(call, output, outcome) {
356
- return { ...call, status: STATUS_OF_OUTCOME[outcome], outcome, output, outputLineCount: outputLines(output).length };
515
+ const diff = outcome === "success" && isFileEditTool(call.toolLabel ?? call.tool) ? diffStat(output) : null;
516
+ return { ...call, status: STATUS_OF_OUTCOME[outcome], outcome, output, outputLineCount: outputLines(output).length, ...diff ? { diff } : {} };
357
517
  }
358
518
  function settledTool(call, step) {
359
519
  return finishedTool(call, step.result, step.outcome);
@@ -788,54 +948,6 @@ function fromTranscript(conversationHistory, researchLog, plannerUsage) {
788
948
  return { blocks, nextId, ...transcriptAt ? { transcriptAt } : {} };
789
949
  }
790
950
 
791
- // src/services/harness/agentTools.ts
792
- var KNOWN_TOOLS = {
793
- // Claude Code
794
- read: "read_file",
795
- grep: "grep",
796
- glob: "glob",
797
- bash: "bash",
798
- ls: "list_dir",
799
- webfetch: "fetch",
800
- websearch: "web_search",
801
- // Codex — its sandboxed command tool is a shell by another name
802
- shell: "bash",
803
- exec_command: "bash",
804
- local_shell: "bash",
805
- // OpenCode
806
- list: "list_dir",
807
- fetch: "fetch"
808
- };
809
- function mapAgentTool(name) {
810
- const normalized = name.trim().toLowerCase().replace(/[_-]/g, "");
811
- const direct = KNOWN_TOOLS[normalized] ?? KNOWN_TOOLS[name.trim().toLowerCase()];
812
- if (direct) {
813
- return { tool: direct, toolLabel: name };
814
- }
815
- return { tool: "agent_tool", toolLabel: name };
816
- }
817
- function normalizeAgentArgs(tool, args) {
818
- const out = { ...args };
819
- const alias = (from, to) => {
820
- if (out[to] === void 0 && out[from] !== void 0) out[to] = out[from];
821
- };
822
- if (tool === "read_file" || tool === "list_dir") {
823
- alias("filePath", "path");
824
- alias("file_path", "path");
825
- alias("target", "path");
826
- }
827
- if (tool === "bash") {
828
- alias("cmd", "command");
829
- alias("script", "command");
830
- if (typeof out.command !== "string" && Array.isArray(out.command)) {
831
- out.command = out.command.join(" ");
832
- }
833
- }
834
- if (tool === "fetch") alias("uri", "url");
835
- if (tool === "web_search") alias("q", "query");
836
- return out;
837
- }
838
-
839
951
  // src/conversation/taskLog.ts
840
952
  var EMPTY_TASK_LOG = { blocks: [], nextId: 1, queued: [], working: false, streams: {} };
841
953
  var TEXT_STREAM = "text";
@@ -981,9 +1093,25 @@ function endTurn2(view, { reason }) {
981
1093
  const closed = closeOpenBlocks({ ...view, working: false, lastTurnEnd: reason, streams: {} }, CUT[reason]);
982
1094
  return reason === "interrupted" ? append(closed, (id) => settledMessage(id, "system", "Interrupted.")) : closed;
983
1095
  }
984
- function queueMessage(view, { messageId, text: text2 }) {
985
- if (view.queued.some((m) => m.id === messageId)) return view;
986
- return { ...view, queued: [...view.queued, { id: messageId, text: text2 }] };
1096
+ function queueMessage(view, { messageId, text: text2, forced }) {
1097
+ const listed = view.queued.find((m) => m.id === messageId);
1098
+ if (forced) {
1099
+ const rest = view.queued.filter((m) => m !== listed);
1100
+ const at = rest.findIndex((m) => !m.forced);
1101
+ const placed = at < 0 ? rest.length : at;
1102
+ return { ...view, queued: [...rest.slice(0, placed), { id: messageId, text: text2, forced: true }, ...rest.slice(placed)] };
1103
+ }
1104
+ if (!listed) return { ...view, queued: [...view.queued, { id: messageId, text: text2 }] };
1105
+ if (!listed.handedOver) return view;
1106
+ return { ...view, queued: view.queued.map((m) => m === listed ? { id: m.id, text: m.text } : m) };
1107
+ }
1108
+ function handOver(view, { messageId }) {
1109
+ const listed = view.queued.find((m) => m.id === messageId);
1110
+ if (!listed || listed.handedOver) return view;
1111
+ return { ...view, queued: view.queued.map((m) => m === listed ? { ...m, handedOver: true } : m) };
1112
+ }
1113
+ function deliverMidTurn(view, event) {
1114
+ return appendOutput(unqueueMessage(view, event), null, (id) => settledMessage(id, "user", event.text));
987
1115
  }
988
1116
  function unqueueMessage(view, { messageId }) {
989
1117
  const queued = view.queued.filter((m) => m.id !== messageId);
@@ -1017,6 +1145,12 @@ function reduceTaskLog(view, event) {
1017
1145
  return queueMessage(view, event);
1018
1146
  case "message_removed":
1019
1147
  return unqueueMessage(view, event);
1148
+ case "message_handed_over":
1149
+ return handOver(view, event);
1150
+ case "message_delivered":
1151
+ return deliverMidTurn(view, event);
1152
+ case "message_undelivered":
1153
+ return append(unqueueMessage(view, event), (id) => settledMessage(id, "system", `${event.text} \xB7 not delivered`));
1020
1154
  case "error":
1021
1155
  return appendOutput(view, null, (id) => settledMessage(id, "error", event.message));
1022
1156
  case "approval_requested":
@@ -1105,34 +1239,152 @@ function hasHiddenDetail(blocks) {
1105
1239
  function taskStartedNotice(title, runner) {
1106
1240
  return runner ? `Started "${title}" \xB7 ${runner}` : `Started "${title}"`;
1107
1241
  }
1242
+
1243
+ // src/taskRow/actions.ts
1244
+ var UNSTARTED_AI = (t) => t.type === "ai" && NOT_STARTED.has(t.status);
1245
+ var QUEUED = (t) => t.status === "pending" || t.status === "approved";
1246
+ var TASK_RULES = [
1247
+ ["cancel", (t) => t.status === "in_progress"],
1248
+ ["skip", (t) => t.status === "blocked"],
1249
+ ["force-start", UNSTARTED_AI],
1250
+ // A manual task has no runner to report it done, so it can always be marked.
1251
+ ["complete", (t) => t.status === "awaiting_user" || t.type === "user"],
1252
+ ["uncomplete", (t) => t.status === "completed"]
1253
+ ];
1254
+ var SUBTASK_RULES = [
1255
+ ["cancel", (t) => t.status === "in_progress"],
1256
+ ["complete", (t) => t.status === "in_progress" && t.type === "ai"],
1257
+ ["force-start", (t) => t.type === "ai" && QUEUED(t)],
1258
+ ["skip", QUEUED],
1259
+ ["complete", (t) => t.status === "awaiting_user"],
1260
+ ["uncomplete", (t) => t.status === "completed"]
1261
+ ];
1262
+ function taskRowActions(task, placement = "task") {
1263
+ const rules = placement === "subtask" ? SUBTASK_RULES : TASK_RULES;
1264
+ return rules.filter(([, applies]) => applies(task)).map(([action]) => action);
1265
+ }
1266
+ function markAction(task) {
1267
+ return task.status === "completed" ? "uncomplete" : "complete";
1268
+ }
1269
+ function markRequestFor(action) {
1270
+ if (action === "complete" || action === "skip") return "complete";
1271
+ if (action === "uncomplete") return "uncomplete";
1272
+ return null;
1273
+ }
1274
+ function opsEditable(task) {
1275
+ return UNSTARTED_AI(task);
1276
+ }
1277
+
1278
+ // src/taskRow/view.ts
1279
+ var refsOf = (ids, orderOf) => ids.map((id) => {
1280
+ const order = orderOf?.get(id);
1281
+ return order === void 0 ? id : taskRef({ order });
1282
+ });
1283
+ var namedRepo = (repo) => repo && repo !== "." ? repo : null;
1284
+ var namedRepos = (repos) => (repos ?? []).filter((r) => r !== ".");
1285
+ var filesOf = (files) => files?.length ? capConflictFiles(files) : null;
1286
+ function taskRowView(task, context = {}) {
1287
+ const parent = context.parent ?? void 0;
1288
+ const isolation = task.isolation && task.isolation.state !== "none" ? task.isolation : null;
1289
+ return {
1290
+ orderLabel: taskOrderLabel(task, parent),
1291
+ kind: task.type === "user" ? "user" : task.ops ? "ops" : "ai",
1292
+ status: taskStatusKind(task),
1293
+ running: isTaskRunning(task),
1294
+ awaiting: awaitingLabel(task),
1295
+ approvals: approvalLabel(task.awaitingApproval),
1296
+ autonomous: task.type === "ai" && context.modes?.find((m) => m.id === task.taskMode)?.autonomous === true,
1297
+ repos: namedRepos(isolation?.repos),
1298
+ conflict: isolation?.state === "conflict" ? { repo: namedRepo(isolation.conflictRepo), files: filesOf(isolation.conflictFiles) } : null,
1299
+ repairing: isolation?.state === "repairing" ? { files: filesOf(isolation.conflictFiles), attempt: isolation.repair ?? null } : null,
1300
+ repaired: isolation?.repairedFiles?.length ? { files: capConflictFiles(isolation.repairedFiles), landed: isolation.state === "integrated" } : null,
1301
+ mergeGate: task.mergeGate?.length ? refsOf(task.mergeGate, context.orderOf) : null,
1302
+ opsChangedFiles: task.status === "awaiting_user" && task.awaitingReason === "files-changed",
1303
+ forcedPastGate: task.forcedPastGate?.length ? task.forcedPastGate : null,
1304
+ dependencies: refsOf(task.dependencies, context.orderOf),
1305
+ actions: taskRowActions(task, context.placement ?? (parent ? "subtask" : "task")),
1306
+ mark: markAction(task),
1307
+ opsEditable: opsEditable(task)
1308
+ };
1309
+ }
1310
+
1311
+ // src/taskRow/texts.ts
1312
+ function findNamed(tasks, id) {
1313
+ for (const task of tasks) {
1314
+ if (task.id === id) return task;
1315
+ const nested = findNamed(task.subtasks ?? [], id);
1316
+ if (nested) return nested;
1317
+ }
1318
+ return void 0;
1319
+ }
1320
+ function titledRefs(ids, tasks) {
1321
+ return ids.map((id) => {
1322
+ const task = findNamed(tasks, id);
1323
+ return task ? titledTaskRef(task) : id;
1324
+ });
1325
+ }
1326
+ function dependentsNotice(dependents) {
1327
+ if (dependents.length === 0) return null;
1328
+ const subject = dependents.length === 1 ? "1 task depends" : `${dependents.length} tasks depend`;
1329
+ return `${subject} on it and will lose that dependency: ${dependents.map((t) => titledTaskRef(t)).join(", ")}.`;
1330
+ }
1331
+ function pastGateConfirmation(unmerged, subject = "This task") {
1332
+ return `${subject} waits for Merge all: the work of ${unmerged.join(", ")} is not merged into your branch yet, so it would act without it. Starting it now is kept on the task.`;
1333
+ }
1334
+ function newTaskFields(title, prompt) {
1335
+ const name = title.trim();
1336
+ if (!name) return null;
1337
+ return { title: name, description: name, prompt: prompt?.trim() ? prompt : name, type: "ai" };
1338
+ }
1108
1339
  // Annotate the CommonJS export names for ESM import in node:
1109
1340
  0 && (module.exports = {
1110
1341
  CHECKPOINT_TRUNCATE_LENGTH,
1111
1342
  EMPTY_CONVERSATION,
1112
1343
  EMPTY_HOLD,
1113
1344
  EMPTY_TASK_LOG,
1345
+ NOT_STARTED,
1114
1346
  NO_TURN,
1115
1347
  aheadOfDraft,
1348
+ approvalLabel,
1349
+ awaitingLabel,
1116
1350
  canMergeTasks,
1117
1351
  canSetDependencies,
1118
1352
  canSplitTask,
1119
1353
  capConflictFiles,
1120
1354
  dependencyCandidates,
1355
+ dependentsNotice,
1121
1356
  dependentsOf,
1357
+ diffRows,
1358
+ diffStat,
1359
+ diffSummary,
1122
1360
  drainNext,
1123
1361
  followTurn,
1124
1362
  fromTranscript,
1125
1363
  hasHiddenDetail,
1126
1364
  holdPrompt,
1365
+ isTaskRunning,
1366
+ markAction,
1367
+ markRequestFor,
1368
+ namedRepos,
1369
+ newTaskFields,
1370
+ opsEditable,
1127
1371
  outputLines,
1128
1372
  outputPreview,
1373
+ pastGateConfirmation,
1129
1374
  reduceConversation,
1130
1375
  reduceTaskLog,
1131
1376
  replayTaskLog,
1132
1377
  runnerToolSubject,
1133
1378
  stopTurn,
1134
1379
  summarizeToolCall,
1380
+ taskOrderLabel,
1381
+ taskRef,
1382
+ taskRowActions,
1383
+ taskRowView,
1135
1384
  taskStartedNotice,
1385
+ taskStatusKind,
1386
+ titledRefs,
1387
+ titledTaskRef,
1136
1388
  toolHeadline,
1137
1389
  truncateCheckpointSummary,
1138
1390
  unsendAll,