@ordewell/core 0.7.1 → 0.8.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 (52) hide show
  1. package/README.md +5 -2
  2. package/dist/{IFileSystem-BnLh-_SK.d.mts → IFileSystem-D96mT-bm.d.ts} +1 -1
  3. package/dist/{IFileSystem-DofiRcCo.d.ts → IFileSystem-DXJCRw5x.d.mts} +1 -1
  4. package/dist/IRunner-CGCihlGQ.d.ts +1165 -0
  5. package/dist/IRunner-XVUddYVX.d.mts +1165 -0
  6. package/dist/{ModeResolver-DkMYf4uS.d.ts → ModeResolver-DE-o2lRF.d.mts} +2 -2
  7. package/dist/{ModeResolver-DZzJSdIU.d.mts → ModeResolver-EWlpmVAy.d.ts} +2 -2
  8. package/dist/Task-1Q19y7sZ.d.mts +1122 -0
  9. package/dist/Task-1Q19y7sZ.d.ts +1122 -0
  10. package/dist/{chunk-ZV5LDNCO.mjs → chunk-2M4X3VB7.mjs} +18 -6
  11. package/dist/chunk-2M4X3VB7.mjs.map +1 -0
  12. package/dist/{chunk-Y36NIASW.mjs → chunk-BLLIBCCS.mjs} +153 -264
  13. package/dist/chunk-BLLIBCCS.mjs.map +1 -0
  14. package/dist/chunk-H5O74L77.mjs +185 -0
  15. package/dist/chunk-H5O74L77.mjs.map +1 -0
  16. package/dist/{chunk-LGQNXPBX.mjs → chunk-UUU46PVQ.mjs} +72 -192
  17. package/dist/chunk-UUU46PVQ.mjs.map +1 -0
  18. package/dist/index.d.mts +1119 -930
  19. package/dist/index.d.ts +1119 -930
  20. package/dist/index.js +8361 -8849
  21. package/dist/index.js.map +1 -1
  22. package/dist/index.mjs +8197 -8614
  23. package/dist/index.mjs.map +1 -1
  24. package/dist/order-labels.d.mts +1 -4
  25. package/dist/order-labels.d.ts +1 -4
  26. package/dist/{parsing-ddZXZFP4.d.ts → parsing-CZdp2p_n.d.ts} +5 -3
  27. package/dist/{parsing-B6ctfF80.d.mts → parsing-GgUJoYKs.d.mts} +5 -3
  28. package/dist/parsing.d.mts +3 -6
  29. package/dist/parsing.d.ts +3 -6
  30. package/dist/parsing.js +25 -4
  31. package/dist/parsing.js.map +1 -1
  32. package/dist/parsing.mjs +3 -2
  33. package/dist/{plan-utils-CKgNtDwQ.d.mts → plan-utils-BMayhGBj.d.mts} +89 -14
  34. package/dist/{plan-utils--kQRzSE-.d.ts → plan-utils-Cv48fe7r.d.ts} +89 -14
  35. package/dist/plan-utils.d.mts +4 -4
  36. package/dist/plan-utils.d.ts +4 -4
  37. package/dist/plan-utils.js +128 -65
  38. package/dist/plan-utils.js.map +1 -1
  39. package/dist/plan-utils.mjs +10 -2
  40. package/dist/testing.d.mts +12 -24
  41. package/dist/testing.d.ts +12 -24
  42. package/dist/testing.js +29 -29
  43. package/dist/testing.js.map +1 -1
  44. package/dist/testing.mjs +21 -27
  45. package/dist/testing.mjs.map +1 -1
  46. package/package.json +1 -1
  47. package/skills/tdd/SKILL.md +19 -0
  48. package/dist/Task-BnLxkVQF.d.mts +0 -2594
  49. package/dist/Task-BnLxkVQF.d.ts +0 -2594
  50. package/dist/chunk-LGQNXPBX.mjs.map +0 -1
  51. package/dist/chunk-Y36NIASW.mjs.map +0 -1
  52. package/dist/chunk-ZV5LDNCO.mjs.map +0 -1
@@ -21,6 +21,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
21
21
  var plan_utils_exports = {};
22
22
  __export(plan_utils_exports, {
23
23
  CHECKPOINT_TRUNCATE_LENGTH: () => CHECKPOINT_TRUNCATE_LENGTH,
24
+ DEFAULT_RUNNERS: () => DEFAULT_RUNNERS,
24
25
  EMPTY_CONVERSATION: () => EMPTY_CONVERSATION,
25
26
  EMPTY_HOLD: () => EMPTY_HOLD,
26
27
  EMPTY_TASK_LOG: () => EMPTY_TASK_LOG,
@@ -45,6 +46,7 @@ __export(plan_utils_exports, {
45
46
  hasHiddenDetail: () => hasHiddenDetail,
46
47
  holdPrompt: () => holdPrompt,
47
48
  isTaskRunning: () => isTaskRunning,
49
+ loadedSkillTokens: () => loadedSkillTokens,
48
50
  markAction: () => markAction,
49
51
  markRequestFor: () => markRequestFor,
50
52
  namedRepos: () => namedRepos,
@@ -57,6 +59,7 @@ __export(plan_utils_exports, {
57
59
  reduceTaskLog: () => reduceTaskLog,
58
60
  replayTaskLog: () => replayTaskLog,
59
61
  runnerToolSubject: () => runnerToolSubject,
62
+ skillTokens: () => skillTokens,
60
63
  stopTurn: () => stopTurn,
61
64
  summarizeToolCall: () => summarizeToolCall,
62
65
  taskOrderLabel: () => taskOrderLabel,
@@ -75,8 +78,30 @@ __export(plan_utils_exports, {
75
78
  module.exports = __toCommonJS(plan_utils_exports);
76
79
 
77
80
  // src/services/TaskOps.ts
81
+ var import_uuid2 = require("uuid");
82
+
83
+ // src/models/Task.ts
78
84
  var import_uuid = require("uuid");
79
85
 
86
+ // src/conversation/skillTokens.ts
87
+ var SKILL_NAME_PATTERN = "[a-z0-9][a-z0-9_-]*";
88
+ var SKILL_TOKEN = new RegExp(`(^|\\s)\\/(${SKILL_NAME_PATTERN})([,.!?;:]*)(?=\\s|$)`, "gi");
89
+ function skillTokens(text2) {
90
+ const tokens = [];
91
+ const seen = /* @__PURE__ */ new Set();
92
+ for (const match of text2.matchAll(SKILL_TOKEN)) {
93
+ const name = match[2].toLowerCase();
94
+ if (seen.has(name)) continue;
95
+ seen.add(name);
96
+ const start = match.index + match[1].length;
97
+ tokens.push({ name, start, end: start + 1 + match[2].length });
98
+ }
99
+ return tokens;
100
+ }
101
+ function loadedSkillTokens(text2, loaded) {
102
+ return skillTokens(text2).filter((t) => loaded.includes(t.name));
103
+ }
104
+
80
105
  // src/order-labels.ts
81
106
  function taskOrderLabel(task, parent) {
82
107
  return parent ? `${parent.order}.${task.order}` : String(task.order);
@@ -88,6 +113,10 @@ function titledTaskRef(task, parent) {
88
113
  return `${taskRef(task, parent)} ${task.title}`;
89
114
  }
90
115
 
116
+ // src/models/Task.ts
117
+ var SKILL_NAME = new RegExp(`^${SKILL_NAME_PATTERN}$`);
118
+ var DEFAULT_RUNNERS = ["claude-code"];
119
+
91
120
  // src/taskRow/status.ts
92
121
  var isTaskRunning = (task) => task.status === "in_progress" || task.status === "running";
93
122
  var NOT_STARTED = /* @__PURE__ */ new Set(["pending", "approved", "blocked"]);
@@ -251,63 +280,8 @@ function summarizeToolCall(tool, argsJson, toolLabel) {
251
280
  return display;
252
281
  }
253
282
 
254
- // src/services/SessionMessage.ts
255
- var CHECKPOINT_TRUNCATE_LENGTH = 120;
256
- function truncateCheckpointSummary(summary) {
257
- const firstLine = summary.split("\n")[0].trim();
258
- if (firstLine.length <= CHECKPOINT_TRUNCATE_LENGTH) return firstLine;
259
- return firstLine.slice(0, CHECKPOINT_TRUNCATE_LENGTH - 1) + "\u2026";
260
- }
261
-
262
- // src/services/conflictFiles.ts
263
- function capConflictFiles(files, max = 5) {
264
- return files.length <= max ? files.join(", ") : `${files.slice(0, max).join(", ")}, +${files.length - max} more`;
265
- }
266
-
267
- // src/models/Usage.ts
268
- var TOKEN_FIELDS = ["inputTokens", "outputTokens", "cachedInputTokens"];
269
- function addUsage(totals, record) {
270
- const next = { ...totals };
271
- for (const field of TOKEN_FIELDS) {
272
- const reported = record[field];
273
- if (reported !== void 0) next[field] = (totals[field] ?? 0) + reported;
274
- }
275
- if (record.reportedCost) {
276
- const { amount, currency } = record.reportedCost;
277
- next.reportedCost = { ...totals.reportedCost, [currency]: (totals.reportedCost?.[currency] ?? 0) + amount };
278
- }
279
- return next;
280
- }
281
- function addPlannerUsage(usage, record) {
282
- const next = { ...usage, totals: addUsage(usage.totals, record) };
283
- if (record.subagentId) {
284
- next.bySubagent = { ...usage.bySubagent, [record.subagentId]: addUsage(usage.bySubagent?.[record.subagentId] ?? {}, record) };
285
- return next;
286
- }
287
- if (record.inputTokens !== void 0) next.lastPromptTokens = record.inputTokens;
288
- if (record.contextWindow !== void 0 && record.contextWindow > 0) next.contextWindow = record.contextWindow;
289
- return next;
290
- }
291
- function isMeasured(totals) {
292
- return totals.inputTokens !== void 0 || totals.outputTokens !== void 0 || totals.cachedInputTokens !== void 0 || Object.keys(totals.reportedCost ?? {}).length > 0;
293
- }
294
- function usageLine(usage) {
295
- const contextFill = plannerContextFill(usage);
296
- return {
297
- totals: usage.totals,
298
- ...usage.bySubagent ? { bySubagent: usage.bySubagent } : {},
299
- ...contextFill ? { contextFill } : {}
300
- };
301
- }
302
- function plannerContextFill(usage) {
303
- if (usage.lastPromptTokens === void 0 || usage.contextWindow === void 0 || usage.contextWindow <= 0) return void 0;
304
- return { usedTokens: usage.lastPromptTokens, windowTokens: usage.contextWindow };
305
- }
306
-
307
- // src/services/terminalRender.ts
308
- var ANSI_OR_CTRL_RE = /\x1b\[[0-9;?]*[A-Za-z]|\x1b\][^\x07\x1b]*(?:\x07|\x1b\\)?|\x1b[()][AB012]|\x1b[=>]|[\x00-\x08\x0b-\x1f\x7f]/g;
309
-
310
283
  // src/conversation/format.ts
284
+ var ANSI_OR_CTRL_RE = /\x1b\[[0-9;?]*[A-Za-z]|\x1b\][^\x07\x1b]*(?:\x07|\x1b\\)?|\x1b[()][AB012]|\x1b[=>]|[\x00-\x08\x0b-\x1f\x7f]/g;
311
285
  var DISPLAY_NAMES = {
312
286
  read_file: "Read",
313
287
  read_files: "Read",
@@ -490,6 +464,16 @@ function normalizeAgentArgs(tool, args) {
490
464
  function settledMessage(id, role, text2, turnId) {
491
465
  return { type: "message", id, role, text: text2, streaming: false, ...turnId ? { turnId } : {} };
492
466
  }
467
+ function userMessage(id, text2, skills, turnId) {
468
+ const block = settledMessage(id, "user", text2, turnId);
469
+ return skills.length > 0 ? { ...block, skills: skills.map((s) => s.name) } : block;
470
+ }
471
+ function skillLoadNotice({ invokedBy, name, source, path, attaches }) {
472
+ return { invokedBy, name, source, path, ...attaches ? { attaches } : {} };
473
+ }
474
+ function skillLoadBlock(id, { invokedBy, name, source, path, attaches }, turnId) {
475
+ return { type: "skill_load", id, invokedBy, name, source, path, ...attaches ? { attaches } : {}, ...turnId ? { turnId } : {} };
476
+ }
493
477
  function subagentBlock(id, { toolCallId, model, usage, turnId, ...fields }) {
494
478
  return {
495
479
  type: "subagent",
@@ -541,6 +525,59 @@ function planMarker(content) {
541
525
  return { status: content.startsWith("Plan updated") ? "updated" : "generated", ...count ? { taskCount: Number(count[1]) } : {} };
542
526
  }
543
527
 
528
+ // src/services/SessionMessage.ts
529
+ var CHECKPOINT_TRUNCATE_LENGTH = 120;
530
+ function truncateCheckpointSummary(summary) {
531
+ const firstLine = summary.split("\n")[0].trim();
532
+ if (firstLine.length <= CHECKPOINT_TRUNCATE_LENGTH) return firstLine;
533
+ return firstLine.slice(0, CHECKPOINT_TRUNCATE_LENGTH - 1) + "\u2026";
534
+ }
535
+
536
+ // src/services/conflictFiles.ts
537
+ function capConflictFiles(files, max = 5) {
538
+ return files.length <= max ? files.join(", ") : `${files.slice(0, max).join(", ")}, +${files.length - max} more`;
539
+ }
540
+
541
+ // src/models/Usage.ts
542
+ var TOKEN_FIELDS = ["inputTokens", "outputTokens", "cachedInputTokens"];
543
+ function addUsage(totals, record) {
544
+ const next = { ...totals };
545
+ for (const field of TOKEN_FIELDS) {
546
+ const reported = record[field];
547
+ if (reported !== void 0) next[field] = (totals[field] ?? 0) + reported;
548
+ }
549
+ if (record.reportedCost) {
550
+ const { amount, currency } = record.reportedCost;
551
+ next.reportedCost = { ...totals.reportedCost, [currency]: (totals.reportedCost?.[currency] ?? 0) + amount };
552
+ }
553
+ return next;
554
+ }
555
+ function addPlannerUsage(usage, record) {
556
+ const next = { ...usage, totals: addUsage(usage.totals, record) };
557
+ if (record.subagentId) {
558
+ next.bySubagent = { ...usage.bySubagent, [record.subagentId]: addUsage(usage.bySubagent?.[record.subagentId] ?? {}, record) };
559
+ return next;
560
+ }
561
+ if (record.inputTokens !== void 0) next.lastPromptTokens = record.inputTokens;
562
+ if (record.contextWindow !== void 0 && record.contextWindow > 0) next.contextWindow = record.contextWindow;
563
+ return next;
564
+ }
565
+ function isMeasured(totals) {
566
+ return totals.inputTokens !== void 0 || totals.outputTokens !== void 0 || totals.cachedInputTokens !== void 0 || Object.keys(totals.reportedCost ?? {}).length > 0;
567
+ }
568
+ function usageLine(usage) {
569
+ const contextFill = plannerContextFill(usage);
570
+ return {
571
+ totals: usage.totals,
572
+ ...usage.bySubagent ? { bySubagent: usage.bySubagent } : {},
573
+ ...contextFill ? { contextFill } : {}
574
+ };
575
+ }
576
+ function plannerContextFill(usage) {
577
+ if (usage.lastPromptTokens === void 0 || usage.contextWindow === void 0 || usage.contextWindow <= 0) return void 0;
578
+ return { usedTokens: usage.lastPromptTokens, windowTokens: usage.contextWindow };
579
+ }
580
+
544
581
  // src/conversation/lanes.ts
545
582
  function findLastIndex(items, match) {
546
583
  for (let i = items.length - 1; i >= 0; i--) if (match(items[i])) return i;
@@ -675,13 +712,15 @@ function finalSegmentIndex(blocks, turnId, pastPlan = false) {
675
712
  }
676
713
  return -1;
677
714
  }
678
- function openTurn(view, turnId, prompt) {
715
+ function openTurn(view, { turnId, prompt = "", skills = [] }) {
679
716
  const i = findLastIndex(view.blocks, (b) => b.type === "message" && b.role === "user");
680
717
  const sent = view.blocks[i];
681
- if (sent?.type === "message" && sent.turnId === void 0 && sent.text === prompt) {
682
- return { ...view, blocks: replaceAt(view.blocks, i, { ...sent, turnId }) };
683
- }
684
- return append(view, (id) => settledMessage(id, "user", prompt, turnId));
718
+ const adopted = sent?.type === "message" && sent.turnId === void 0 && sent.text === prompt;
719
+ const said = adopted ? { ...view, blocks: replaceAt(view.blocks, i, userMessage(sent.id, prompt, skills, turnId)) } : append(view, (id) => userMessage(id, prompt, skills, turnId));
720
+ if (skills.length === 0) return said;
721
+ const at = adopted ? i + 1 : findLastIndex(said.blocks, (b) => b.type === "message" && b.role === "user") + 1;
722
+ const loads = skills.map((skill, n) => skillLoadBlock(`b${said.nextId + n}`, skill, turnId));
723
+ return { ...said, blocks: [...said.blocks.slice(0, at), ...loads, ...said.blocks.slice(at)], nextId: said.nextId + loads.length };
685
724
  }
686
725
  function streamText(view, { turnId, segmentId, text: text2 }) {
687
726
  const i = findLastIndex(view.blocks, (b) => isUnsettledSegment(b, turnId) && b.segmentId === segmentId);
@@ -828,7 +867,9 @@ function reduceConversation(view, input) {
828
867
  case "local_entry":
829
868
  return append(view, (id) => settledMessage(id, input.role, input.text));
830
869
  case "planner_turn_started":
831
- return input.prompt === void 0 ? view : openTurn(view, input.turnId, input.prompt);
870
+ return input.prompt === void 0 ? view : openTurn(view, input);
871
+ case "planner_skill_loaded":
872
+ return append(sealLane(view, null, -1), (id) => skillLoadBlock(id, input.skill, input.turnId));
832
873
  case "planner_text_delta":
833
874
  return streamText(view, input);
834
875
  case "planner_message":
@@ -868,11 +909,27 @@ function reduceConversation(view, input) {
868
909
  var USER = 0;
869
910
  var RESEARCH = 1;
870
911
  var SETTLED = 2;
871
- function fromEntry(entry) {
912
+ function fromEntry(entry, loaded = []) {
872
913
  if (entry.kind === "plan_generated") return (id) => ({ type: "plan", id: id(), text: "", ...planMarker(entry.content) });
914
+ if (entry.kind === "skill_load" && entry.skill) {
915
+ const { skill } = entry;
916
+ return (id) => skillLoadBlock(id(), skillLoadNotice(skill));
917
+ }
918
+ if (entry.role === "user" && !entry.kind) return (id) => userMessage(id(), entry.content, loaded.map(skillLoadNotice));
873
919
  const role = entry.kind === "system" || entry.kind === "compaction" ? "system" : entry.role === "user" ? "user" : "planner";
874
920
  return (id) => settledMessage(id(), role, entry.content);
875
921
  }
922
+ function loadsAfter(entries, index) {
923
+ const loads = [];
924
+ for (let i = index + 1; i < entries.length && entries[i].kind === "skill_load"; i++) {
925
+ const { skill } = entries[i];
926
+ if (skill?.invokedBy === "user") loads.push(skill);
927
+ }
928
+ return loads;
929
+ }
930
+ function rankOf(entry) {
931
+ return entry.role === "user" && (!entry.kind || entry.kind === "skill_load") ? USER : SETTLED;
932
+ }
876
933
  function spawnBrief(step) {
877
934
  try {
878
935
  const args = JSON.parse(step.args);
@@ -935,7 +992,7 @@ function fromTranscript(conversationHistory, researchLog, plannerUsage) {
935
992
  const kept = compacted ? history.slice(1) : history;
936
993
  const cutoff = compacted ? kept[0]?.timestamp ?? compacted.timestamp : "";
937
994
  const placed = [
938
- ...kept.map((entry) => ({ at: entry.timestamp, rank: entry.role === "user" && !entry.kind ? USER : SETTLED, build: fromEntry(entry) })),
995
+ ...kept.map((entry, i) => ({ at: entry.timestamp, rank: rankOf(entry), build: fromEntry(entry, loadsAfter(kept, i)) })),
939
996
  ...research(researchLog ?? []).filter((item) => item.at >= cutoff)
940
997
  ];
941
998
  placed.sort((a, b) => a.at < b.at ? -1 : a.at > b.at ? 1 : a.rank - b.rank);
@@ -1119,6 +1176,8 @@ function unqueueMessage(view, { messageId }) {
1119
1176
  }
1120
1177
  function reduceTaskLog(view, event) {
1121
1178
  switch (event.type) {
1179
+ case "task_skills":
1180
+ return append(view, (id) => settledMessage(id, "system", `Skills: ${event.skills.map((s) => `${s.name} (${s.path})`).join(", ")}`));
1122
1181
  case "turn_start":
1123
1182
  return startTurn(view, event);
1124
1183
  case "turn_end":
@@ -1201,7 +1260,8 @@ var TURN_STREAM = /* @__PURE__ */ new Set([
1201
1260
  "research_step_done",
1202
1261
  "subagent_started",
1203
1262
  "subagent_finished",
1204
- "planner_turn_ended"
1263
+ "planner_turn_ended",
1264
+ "planner_skill_loaded"
1205
1265
  ]);
1206
1266
  function cutOff(gate, input) {
1207
1267
  if (gate.stopped === null || !TURN_STREAM.has(input.type)) return false;
@@ -1339,6 +1399,7 @@ function newTaskFields(title, prompt) {
1339
1399
  // Annotate the CommonJS export names for ESM import in node:
1340
1400
  0 && (module.exports = {
1341
1401
  CHECKPOINT_TRUNCATE_LENGTH,
1402
+ DEFAULT_RUNNERS,
1342
1403
  EMPTY_CONVERSATION,
1343
1404
  EMPTY_HOLD,
1344
1405
  EMPTY_TASK_LOG,
@@ -1363,6 +1424,7 @@ function newTaskFields(title, prompt) {
1363
1424
  hasHiddenDetail,
1364
1425
  holdPrompt,
1365
1426
  isTaskRunning,
1427
+ loadedSkillTokens,
1366
1428
  markAction,
1367
1429
  markRequestFor,
1368
1430
  namedRepos,
@@ -1375,6 +1437,7 @@ function newTaskFields(title, prompt) {
1375
1437
  reduceTaskLog,
1376
1438
  replayTaskLog,
1377
1439
  runnerToolSubject,
1440
+ skillTokens,
1378
1441
  stopTurn,
1379
1442
  summarizeToolCall,
1380
1443
  taskOrderLabel,