@ordewell/core 0.10.3 → 0.10.5

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 (46) hide show
  1. package/dist/{IFileSystem-DCd-rkeH.d.ts → IFileSystem-ClBdp59f.d.ts} +1 -1
  2. package/dist/{IFileSystem-B8Nkgg4e.d.mts → IFileSystem-Db34maxC.d.mts} +1 -1
  3. package/dist/{IRunner-CXdYyIZo.d.mts → IRunner-Crkt3tHD.d.ts} +64 -3
  4. package/dist/{IRunner-QBdYcatb.d.ts → IRunner-lMQIa5Wc.d.mts} +64 -3
  5. package/dist/{ModeResolver-geqjKkLY.d.mts → ModeResolver-B4hhABNf.d.mts} +1 -1
  6. package/dist/{ModeResolver-BOU90Nn-.d.ts → ModeResolver-CUR5jCSU.d.ts} +1 -1
  7. package/dist/{Task-CRVIqSfy.d.mts → Task-D4QHjdGv.d.mts} +93 -11
  8. package/dist/{Task-CRVIqSfy.d.ts → Task-D4QHjdGv.d.ts} +93 -11
  9. package/dist/{chunk-A57ITQE7.mjs → chunk-4QLFM73A.mjs} +34 -5
  10. package/dist/chunk-4QLFM73A.mjs.map +1 -0
  11. package/dist/{chunk-FH6M5QZG.mjs → chunk-6LEA6WAM.mjs} +88 -7
  12. package/dist/chunk-6LEA6WAM.mjs.map +1 -0
  13. package/dist/{chunk-645FALZX.mjs → chunk-F3KIX7WR.mjs} +3 -3
  14. package/dist/{chunk-OYUSADFM.mjs → chunk-NJGID6BG.mjs} +3 -1
  15. package/dist/chunk-NJGID6BG.mjs.map +1 -0
  16. package/dist/{chunk-SM6BV6XS.mjs → chunk-RT4NQ2BZ.mjs} +3 -1
  17. package/dist/chunk-RT4NQ2BZ.mjs.map +1 -0
  18. package/dist/index.d.mts +307 -66
  19. package/dist/index.d.ts +307 -66
  20. package/dist/index.js +1688 -402
  21. package/dist/index.js.map +1 -1
  22. package/dist/index.mjs +1567 -388
  23. package/dist/index.mjs.map +1 -1
  24. package/dist/parsing.d.mts +2 -2
  25. package/dist/parsing.d.ts +2 -2
  26. package/dist/parsing.js.map +1 -1
  27. package/dist/parsing.mjs +3 -3
  28. package/dist/{plan-utils-oC8bO4pN.d.ts → plan-utils-BVJCzNvm.d.ts} +204 -19
  29. package/dist/{plan-utils-KU1Rse82.d.mts → plan-utils-wI8MuDBC.d.mts} +204 -19
  30. package/dist/plan-utils.d.mts +4 -4
  31. package/dist/plan-utils.d.ts +4 -4
  32. package/dist/plan-utils.js +94 -5
  33. package/dist/plan-utils.js.map +1 -1
  34. package/dist/plan-utils.mjs +13 -3
  35. package/dist/testing.d.mts +6 -3
  36. package/dist/testing.d.ts +6 -3
  37. package/dist/testing.js +7 -0
  38. package/dist/testing.js.map +1 -1
  39. package/dist/testing.mjs +7 -2
  40. package/dist/testing.mjs.map +1 -1
  41. package/package.json +1 -1
  42. package/dist/chunk-A57ITQE7.mjs.map +0 -1
  43. package/dist/chunk-FH6M5QZG.mjs.map +0 -1
  44. package/dist/chunk-OYUSADFM.mjs.map +0 -1
  45. package/dist/chunk-SM6BV6XS.mjs.map +0 -1
  46. /package/dist/{chunk-645FALZX.mjs.map → chunk-F3KIX7WR.mjs.map} +0 -0
@@ -47,6 +47,8 @@ __export(plan_utils_exports, {
47
47
  addUsageTotals: () => addUsageTotals,
48
48
  aheadOfDraft: () => aheadOfDraft,
49
49
  approvalLabel: () => approvalLabel,
50
+ assignmentIssue: () => assignmentIssue,
51
+ assignmentIssueText: () => assignmentIssueText,
50
52
  awaitingLabel: () => awaitingLabel,
51
53
  blockedByLabel: () => blockedByLabel,
52
54
  blockingFailures: () => blockingFailures,
@@ -54,6 +56,7 @@ __export(plan_utils_exports, {
54
56
  canSetDependencies: () => canSetDependencies,
55
57
  canSplitTask: () => canSplitTask,
56
58
  capConflictFiles: () => capConflictFiles,
59
+ countedSessionCost: () => countedSessionCost,
57
60
  dependencyCandidates: () => dependencyCandidates,
58
61
  dependentsNotice: () => dependentsNotice,
59
62
  dependentsOf: () => dependentsOf,
@@ -91,6 +94,7 @@ __export(plan_utils_exports, {
91
94
  resolveTaskRef: () => resolveTaskRef,
92
95
  resumeLabel: () => resumeLabel,
93
96
  resumeTime: () => resumeTime,
97
+ resumedSessionWindow: () => resumedSessionWindow,
94
98
  runnerToolSubject: () => runnerToolSubject,
95
99
  skillTokens: () => skillTokens,
96
100
  skippedLabel: () => skippedLabel,
@@ -105,6 +109,7 @@ __export(plan_utils_exports, {
105
109
  taskRowView: () => taskRowView,
106
110
  taskStartedNotice: () => taskStartedNotice,
107
111
  taskStatusKind: () => taskStatusKind,
112
+ taskUsageSummary: () => taskUsageSummary,
108
113
  titledRefs: () => titledRefs,
109
114
  titledTaskRef: () => titledTaskRef,
110
115
  titledTaskRefOf: () => titledTaskRefOf,
@@ -195,6 +200,20 @@ function pausedOnLimit(task) {
195
200
  // src/services/TaskOps.ts
196
201
  var import_uuid3 = require("uuid");
197
202
 
203
+ // src/services/ModelAllowlistResolver.ts
204
+ function effectiveAllowlist(allowlist, runner, modelsByRunner) {
205
+ if (!allowlist || allowlist.length === 0) return void 0;
206
+ if (!modelsByRunner) return allowlist;
207
+ const own = new Set((modelsByRunner[runner] ?? []).map((m) => m.modelId));
208
+ const elsewhere = /* @__PURE__ */ new Set();
209
+ for (const [other, models] of Object.entries(modelsByRunner)) {
210
+ if (other === runner) continue;
211
+ for (const m of models ?? []) elsewhere.add(m.modelId);
212
+ }
213
+ const kept = allowlist.filter((id) => own.has(id) || !elsewhere.has(id));
214
+ return kept.length > 0 ? kept : void 0;
215
+ }
216
+
198
217
  // src/taskRow/status.ts
199
218
  var isTaskRunning = (task) => task.status === "in_progress" || task.status === "running";
200
219
  var NOT_STARTED = /* @__PURE__ */ new Set(["pending", "approved", "blocked"]);
@@ -230,7 +249,7 @@ function blockedByLabel(refs) {
230
249
  function skippedLabel(reason) {
231
250
  return reason ? `Skipped: ${reason}` : "Skipped";
232
251
  }
233
- var WAITS_FOR_APPROVAL_LABEL = "Waiting for your approval to start";
252
+ var WAITS_FOR_APPROVAL_LABEL = "Waits for your approval";
234
253
  function approvalLabel(count) {
235
254
  if (!count) return null;
236
255
  return count > 1 ? `Waiting for approval (${count})` : "Waiting for approval";
@@ -764,8 +783,21 @@ function addAttemptUsage(usage, record, now) {
764
783
  const folded = addPlannerUsage(usage, record);
765
784
  return { ...usage, ...folded, lastPromptTokens: folded.lastPromptTokens, contextWindow: folded.contextWindow, wallTimeMs: Math.max(0, Date.parse(now) - Date.parse(usage.startedAt)) };
766
785
  }
767
- function endAttemptUsage(usage, now) {
768
- return { ...usage, endedAt: now, wallTimeMs: Math.max(0, Date.parse(now) - Date.parse(usage.startedAt)) };
786
+ function endAttemptUsage(usage, now, runnerSessionCost, sessionId) {
787
+ return {
788
+ ...usage,
789
+ endedAt: now,
790
+ wallTimeMs: Math.max(0, Date.parse(now) - Date.parse(usage.startedAt)),
791
+ ...sessionId ? { sessionId } : {},
792
+ ...runnerSessionCost ? { runnerSessionCost } : {}
793
+ };
794
+ }
795
+ function countedSessionCost(attempts, sessionId) {
796
+ return [...attempts ?? []].reverse().find((usage) => usage.runnerSessionCost?.sessionId === sessionId)?.runnerSessionCost;
797
+ }
798
+ function resumedSessionWindow(attempts, runner, attempt, sessionId) {
799
+ const last = [...attempts ?? []].reverse().find((usage) => usage.attempt !== attempt && usage.runner === runner && usage.sessionId === sessionId && usage.contextWindow !== void 0);
800
+ return last ? { source: last.source, model: last.model, contextWindow: last.contextWindow } : void 0;
769
801
  }
770
802
  function addUsageTotals(totals, addition) {
771
803
  let next = addUsage(totals, { source: "", inputTokens: addition.inputTokens, outputTokens: addition.outputTokens, cachedInputTokens: addition.cachedInputTokens });
@@ -794,6 +826,16 @@ function planUsage(tasks) {
794
826
  }
795
827
  return result;
796
828
  }
829
+ function taskUsageSummary(task) {
830
+ const attempts = task.attemptUsage ?? [];
831
+ const latest = attempts.at(-1);
832
+ const contextFill = latest ? plannerContextFill(latest) : void 0;
833
+ return {
834
+ totals: attempts.reduce((sum, attempt) => addUsageTotals(sum, attempt.totals), {}),
835
+ attempts: attempts.length,
836
+ ...contextFill ? { contextFill } : {}
837
+ };
838
+ }
797
839
 
798
840
  // src/conversation/lanes.ts
799
841
  function findLastIndex(items, match) {
@@ -1116,6 +1158,7 @@ function syncTranscript(view, { plan, turnId }) {
1116
1158
  if (isNew && entry.kind === "wake_up") next = takePendingInputs(next, void 0, [entry.content]).view;
1117
1159
  if (isNew && entry.kind === "plan_generated") next = markPlan(next, entry.content, i === committed ? turnId : void 0);
1118
1160
  if (isNew && entry.kind === "system") next = append(next, (id) => settledMessage(id, "system", entry.content));
1161
+ if (isNew && entry.kind === "error") next = append(next, (id) => settledMessage(id, "error", entry.content));
1119
1162
  if (isNew && entry.kind === "compaction") next = markCompaction(next, entry.content);
1120
1163
  if (latest === void 0 || entry.timestamp > latest) latest = entry.timestamp;
1121
1164
  }
@@ -1196,6 +1239,8 @@ function roleOf(entry) {
1196
1239
  return "wake_up";
1197
1240
  case "supervisor":
1198
1241
  return "supervisor";
1242
+ case "error":
1243
+ return "error";
1199
1244
  default:
1200
1245
  return entry.role === "user" ? "user" : "planner";
1201
1246
  }
@@ -1481,6 +1526,12 @@ function commandOutput(view, { text: text2 }) {
1481
1526
  return { ...view, blocks: replaceAt(view.blocks, i, { ...block, output: block.output ? `${block.output}
1482
1527
  ${text2}` : text2 }) };
1483
1528
  }
1529
+ function modelSwitchNotice({ from, to, plan, kept }) {
1530
+ if (!plan) return `Model changed in the runner: ${from.label ?? from.model} \u2192 ${to.label ?? to.model}${kept ? ` (${kept})` : ""}`;
1531
+ const planned = plan.model ? `${plan.model.label ?? plan.model.model}${plan.effort ? `, ${plan.effort}` : ""}` : void 0;
1532
+ if (!kept) return `Model changed in the runner: ${from.label ?? from.model} \u2192 ${to.label ?? to.model}; the plan now says ${planned ?? to.label ?? to.model}`;
1533
+ return `The runner now answers on ${to.label ?? to.model}; ${planned ? `the plan still says ${planned}` : "the plan names no model"} (${kept})`;
1534
+ }
1484
1535
  function appendStep(view, make) {
1485
1536
  const next = append(view, make);
1486
1537
  return sealLane(next, null, findLastIndex(next.blocks, (b) => b.type !== "usage"));
@@ -1542,6 +1593,8 @@ function reduceTaskLog(view, event) {
1542
1593
  return startCommand(view, event);
1543
1594
  case "command_output":
1544
1595
  return commandOutput(view, event);
1596
+ case "model_switched":
1597
+ return append(view, (id) => settledMessage(id, "system", modelSwitchNotice(event)));
1545
1598
  case "compaction":
1546
1599
  return appendStep(view, (id) => ({
1547
1600
  type: "compaction",
@@ -1752,6 +1805,31 @@ function opsEditable(task) {
1752
1805
  return UNSTARTED_AI(task);
1753
1806
  }
1754
1807
 
1808
+ // src/services/AssignmentScope.ts
1809
+ var OVER = /* @__PURE__ */ new Set(["completed", "skipped"]);
1810
+ function assignmentIssue(task, scope) {
1811
+ if (task.type !== "ai" || OVER.has(task.status)) return null;
1812
+ if (!scope.enabledRunners.includes(task.assignedRunner)) return { kind: "runner-off", runner: task.assignedRunner };
1813
+ const model = task.assignedModel;
1814
+ const allowed = effectiveAllowlist(scope.allowlist[task.assignedRunner], task.assignedRunner, scope.models);
1815
+ if (model && allowed && !allowed.includes(model.modelId)) {
1816
+ return { kind: "model-off-list", runner: task.assignedRunner, modelId: model.modelId, modelLabel: model.modelLabel || model.modelId };
1817
+ }
1818
+ return null;
1819
+ }
1820
+ function assignmentIssueText(issue) {
1821
+ return issue.kind === "runner-off" ? `${issue.runner} is switched off` : `${issue.modelLabel} is not in the allowlist`;
1822
+ }
1823
+ function assignmentConsequence({ status, awaitingReason, resumeAt }) {
1824
+ if (status === "failed") return "failed; a retry would run it there unless moved";
1825
+ if (status === "awaiting_user" && awaitingReason === "usage-limit") {
1826
+ return resumeAt ? "paused on a usage limit; resumes there at the reset unless moved" : "paused on a usage limit; a retry would run it there unless moved";
1827
+ }
1828
+ if (status === "awaiting_user" && (awaitingReason === "conflict" || awaitingReason === "files-changed")) return "waiting for the user; what runs next runs there unless moved";
1829
+ if (status === "in_progress" || status === "awaiting_user") return "already running as assigned";
1830
+ return "runs as assigned unless moved";
1831
+ }
1832
+
1755
1833
  // src/taskRow/view.ts
1756
1834
  var refsOf = (ids, tasks) => ids.map((id) => tasks?.length ? taskRefOf(tasks, id) ?? id : id);
1757
1835
  var namedRepo = (repo) => repo && repo !== "." ? repo : null;
@@ -1762,13 +1840,18 @@ function blockedBy(task, tasks) {
1762
1840
  if (!tasks?.length || !NOT_STARTED.has(task.status)) return [];
1763
1841
  return blockingFailures(asBlocking(tasks)).get(task.id) ?? [];
1764
1842
  }
1843
+ function flagOf(task, scope) {
1844
+ const issue = scope && task.assignedRunner !== void 0 ? assignmentIssue({ ...task, assignedRunner: task.assignedRunner }, scope) : null;
1845
+ return issue ? { assignmentFlag: assignmentIssueText(issue), assignmentConsequence: assignmentConsequence(task) } : { assignmentFlag: null, assignmentConsequence: null };
1846
+ }
1765
1847
  function taskRowView(task, context = {}) {
1766
1848
  const parent = context.parent ?? void 0;
1767
1849
  const isolation = task.isolation && task.isolation.state !== "none" ? task.isolation : null;
1768
- const latestUsage = task.attemptUsage?.at(-1);
1850
+ const spend = taskUsageSummary(task);
1851
+ const latestAttempt = task.attemptUsage?.at(-1);
1769
1852
  const blocked = blockedBy(task, context.tasks);
1770
1853
  return {
1771
- usage: latestUsage ? { ...usageLine(latestUsage), attempt: latestUsage.attempt, wallTimeMs: latestUsage.wallTimeMs, byModel: latestUsage.byModel } : task.type === "ai" && ["completed", "failed", "in_progress", "awaiting_user"].includes(task.status) ? { totals: {}, attempt: 0, byModel: [] } : null,
1854
+ usage: latestAttempt ? { totals: spend.totals, ...spend.contextFill ? { contextFill: spend.contextFill } : {}, attempt: latestAttempt.attempt } : task.type === "ai" && ["completed", "failed", "in_progress", "awaiting_user"].includes(task.status) ? { totals: {}, attempt: 0 } : null,
1772
1855
  orderLabel: taskOrderLabel(task, parent),
1773
1856
  kind: task.type === "user" ? "user" : task.ops ? "ops" : "ai",
1774
1857
  status: blocked.length > 0 ? "blocked" : taskStatusKind(task),
@@ -1777,6 +1860,7 @@ function taskRowView(task, context = {}) {
1777
1860
  resumes: resumeLabel(task, context.now),
1778
1861
  approvals: approvalLabel(task.awaitingApproval),
1779
1862
  waitsForApproval: task.waitsForApproval && NOT_STARTED.has(task.status) ? WAITS_FOR_APPROVAL_LABEL : null,
1863
+ ...flagOf(task, context.runnerScope),
1780
1864
  autonomous: task.type === "ai" && context.modes?.find((m) => m.id === task.taskMode)?.autonomous === true,
1781
1865
  repos: namedRepos(isolation?.repos),
1782
1866
  conflict: isolation?.state === "conflict" ? { repo: namedRepo(isolation.conflictRepo), files: filesOf(isolation.conflictFiles) } : null,
@@ -1834,6 +1918,8 @@ var EMPTY_RUN = { tasks: [], runMerge: null, handoff: null, mergeResult: null };
1834
1918
  addUsageTotals,
1835
1919
  aheadOfDraft,
1836
1920
  approvalLabel,
1921
+ assignmentIssue,
1922
+ assignmentIssueText,
1837
1923
  awaitingLabel,
1838
1924
  blockedByLabel,
1839
1925
  blockingFailures,
@@ -1841,6 +1927,7 @@ var EMPTY_RUN = { tasks: [], runMerge: null, handoff: null, mergeResult: null };
1841
1927
  canSetDependencies,
1842
1928
  canSplitTask,
1843
1929
  capConflictFiles,
1930
+ countedSessionCost,
1844
1931
  dependencyCandidates,
1845
1932
  dependentsNotice,
1846
1933
  dependentsOf,
@@ -1878,6 +1965,7 @@ var EMPTY_RUN = { tasks: [], runMerge: null, handoff: null, mergeResult: null };
1878
1965
  resolveTaskRef,
1879
1966
  resumeLabel,
1880
1967
  resumeTime,
1968
+ resumedSessionWindow,
1881
1969
  runnerToolSubject,
1882
1970
  skillTokens,
1883
1971
  skippedLabel,
@@ -1892,6 +1980,7 @@ var EMPTY_RUN = { tasks: [], runMerge: null, handoff: null, mergeResult: null };
1892
1980
  taskRowView,
1893
1981
  taskStartedNotice,
1894
1982
  taskStatusKind,
1983
+ taskUsageSummary,
1895
1984
  titledRefs,
1896
1985
  titledTaskRef,
1897
1986
  titledTaskRefOf,