@ordewell/core 0.7.2 → 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 (50) hide show
  1. package/README.md +5 -2
  2. package/dist/{IFileSystem-B5asBRDa.d.mts → IFileSystem-D96mT-bm.d.ts} +1 -1
  3. package/dist/{IFileSystem-CbCmUDBn.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-DtfhWeVL.d.ts → ModeResolver-DE-o2lRF.d.mts} +2 -2
  7. package/dist/{ModeResolver-DcqAho4y.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-OUIQWNS3.mjs → chunk-2M4X3VB7.mjs} +15 -5
  11. package/dist/chunk-2M4X3VB7.mjs.map +1 -0
  12. package/dist/{chunk-AJ5KDO6V.mjs → chunk-BLLIBCCS.mjs} +117 -198
  13. package/dist/chunk-BLLIBCCS.mjs.map +1 -0
  14. package/dist/{chunk-MZYZS7B3.mjs → chunk-UUU46PVQ.mjs} +68 -8
  15. package/dist/chunk-UUU46PVQ.mjs.map +1 -0
  16. package/dist/index.d.mts +516 -713
  17. package/dist/index.d.ts +516 -713
  18. package/dist/index.js +5012 -6370
  19. package/dist/index.js.map +1 -1
  20. package/dist/index.mjs +3275 -4589
  21. package/dist/index.mjs.map +1 -1
  22. package/dist/order-labels.d.mts +1 -4
  23. package/dist/order-labels.d.ts +1 -4
  24. package/dist/{parsing-COFGUEWx.d.ts → parsing-CZdp2p_n.d.ts} +5 -3
  25. package/dist/{parsing-D0uo-Icd.d.mts → parsing-GgUJoYKs.d.mts} +5 -3
  26. package/dist/parsing.d.mts +3 -6
  27. package/dist/parsing.d.ts +3 -6
  28. package/dist/parsing.js +25 -4
  29. package/dist/parsing.js.map +1 -1
  30. package/dist/parsing.mjs +2 -2
  31. package/dist/{plan-utils-CdW3mxt5.d.mts → plan-utils-BMayhGBj.d.mts} +89 -12
  32. package/dist/{plan-utils-D4Z8UyLL.d.ts → plan-utils-Cv48fe7r.d.ts} +89 -12
  33. package/dist/plan-utils.d.mts +4 -4
  34. package/dist/plan-utils.d.ts +4 -4
  35. package/dist/plan-utils.js +120 -65
  36. package/dist/plan-utils.js.map +1 -1
  37. package/dist/plan-utils.mjs +7 -3
  38. package/dist/testing.d.mts +12 -24
  39. package/dist/testing.d.ts +12 -24
  40. package/dist/testing.js +24 -28
  41. package/dist/testing.js.map +1 -1
  42. package/dist/testing.mjs +17 -27
  43. package/dist/testing.mjs.map +1 -1
  44. package/package.json +1 -1
  45. package/skills/tdd/SKILL.md +19 -0
  46. package/dist/Task-BpzIbunq.d.mts +0 -2599
  47. package/dist/Task-BpzIbunq.d.ts +0 -2599
  48. package/dist/chunk-AJ5KDO6V.mjs.map +0 -1
  49. package/dist/chunk-MZYZS7B3.mjs.map +0 -1
  50. package/dist/chunk-OUIQWNS3.mjs.map +0 -1
@@ -46,6 +46,7 @@ __export(plan_utils_exports, {
46
46
  hasHiddenDetail: () => hasHiddenDetail,
47
47
  holdPrompt: () => holdPrompt,
48
48
  isTaskRunning: () => isTaskRunning,
49
+ loadedSkillTokens: () => loadedSkillTokens,
49
50
  markAction: () => markAction,
50
51
  markRequestFor: () => markRequestFor,
51
52
  namedRepos: () => namedRepos,
@@ -58,6 +59,7 @@ __export(plan_utils_exports, {
58
59
  reduceTaskLog: () => reduceTaskLog,
59
60
  replayTaskLog: () => replayTaskLog,
60
61
  runnerToolSubject: () => runnerToolSubject,
62
+ skillTokens: () => skillTokens,
61
63
  stopTurn: () => stopTurn,
62
64
  summarizeToolCall: () => summarizeToolCall,
63
65
  taskOrderLabel: () => taskOrderLabel,
@@ -81,6 +83,25 @@ var import_uuid2 = require("uuid");
81
83
  // src/models/Task.ts
82
84
  var import_uuid = require("uuid");
83
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
+
84
105
  // src/order-labels.ts
85
106
  function taskOrderLabel(task, parent) {
86
107
  return parent ? `${parent.order}.${task.order}` : String(task.order);
@@ -93,6 +114,7 @@ function titledTaskRef(task, parent) {
93
114
  }
94
115
 
95
116
  // src/models/Task.ts
117
+ var SKILL_NAME = new RegExp(`^${SKILL_NAME_PATTERN}$`);
96
118
  var DEFAULT_RUNNERS = ["claude-code"];
97
119
 
98
120
  // src/taskRow/status.ts
@@ -258,63 +280,8 @@ function summarizeToolCall(tool, argsJson, toolLabel) {
258
280
  return display;
259
281
  }
260
282
 
261
- // src/services/SessionMessage.ts
262
- var CHECKPOINT_TRUNCATE_LENGTH = 120;
263
- function truncateCheckpointSummary(summary) {
264
- const firstLine = summary.split("\n")[0].trim();
265
- if (firstLine.length <= CHECKPOINT_TRUNCATE_LENGTH) return firstLine;
266
- return firstLine.slice(0, CHECKPOINT_TRUNCATE_LENGTH - 1) + "\u2026";
267
- }
268
-
269
- // src/services/conflictFiles.ts
270
- function capConflictFiles(files, max = 5) {
271
- return files.length <= max ? files.join(", ") : `${files.slice(0, max).join(", ")}, +${files.length - max} more`;
272
- }
273
-
274
- // src/models/Usage.ts
275
- var TOKEN_FIELDS = ["inputTokens", "outputTokens", "cachedInputTokens"];
276
- function addUsage(totals, record) {
277
- const next = { ...totals };
278
- for (const field of TOKEN_FIELDS) {
279
- const reported = record[field];
280
- if (reported !== void 0) next[field] = (totals[field] ?? 0) + reported;
281
- }
282
- if (record.reportedCost) {
283
- const { amount, currency } = record.reportedCost;
284
- next.reportedCost = { ...totals.reportedCost, [currency]: (totals.reportedCost?.[currency] ?? 0) + amount };
285
- }
286
- return next;
287
- }
288
- function addPlannerUsage(usage, record) {
289
- const next = { ...usage, totals: addUsage(usage.totals, record) };
290
- if (record.subagentId) {
291
- next.bySubagent = { ...usage.bySubagent, [record.subagentId]: addUsage(usage.bySubagent?.[record.subagentId] ?? {}, record) };
292
- return next;
293
- }
294
- if (record.inputTokens !== void 0) next.lastPromptTokens = record.inputTokens;
295
- if (record.contextWindow !== void 0 && record.contextWindow > 0) next.contextWindow = record.contextWindow;
296
- return next;
297
- }
298
- function isMeasured(totals) {
299
- return totals.inputTokens !== void 0 || totals.outputTokens !== void 0 || totals.cachedInputTokens !== void 0 || Object.keys(totals.reportedCost ?? {}).length > 0;
300
- }
301
- function usageLine(usage) {
302
- const contextFill = plannerContextFill(usage);
303
- return {
304
- totals: usage.totals,
305
- ...usage.bySubagent ? { bySubagent: usage.bySubagent } : {},
306
- ...contextFill ? { contextFill } : {}
307
- };
308
- }
309
- function plannerContextFill(usage) {
310
- if (usage.lastPromptTokens === void 0 || usage.contextWindow === void 0 || usage.contextWindow <= 0) return void 0;
311
- return { usedTokens: usage.lastPromptTokens, windowTokens: usage.contextWindow };
312
- }
313
-
314
- // src/services/terminalRender.ts
315
- 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;
316
-
317
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;
318
285
  var DISPLAY_NAMES = {
319
286
  read_file: "Read",
320
287
  read_files: "Read",
@@ -497,6 +464,16 @@ function normalizeAgentArgs(tool, args) {
497
464
  function settledMessage(id, role, text2, turnId) {
498
465
  return { type: "message", id, role, text: text2, streaming: false, ...turnId ? { turnId } : {} };
499
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
+ }
500
477
  function subagentBlock(id, { toolCallId, model, usage, turnId, ...fields }) {
501
478
  return {
502
479
  type: "subagent",
@@ -548,6 +525,59 @@ function planMarker(content) {
548
525
  return { status: content.startsWith("Plan updated") ? "updated" : "generated", ...count ? { taskCount: Number(count[1]) } : {} };
549
526
  }
550
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
+
551
581
  // src/conversation/lanes.ts
552
582
  function findLastIndex(items, match) {
553
583
  for (let i = items.length - 1; i >= 0; i--) if (match(items[i])) return i;
@@ -682,13 +712,15 @@ function finalSegmentIndex(blocks, turnId, pastPlan = false) {
682
712
  }
683
713
  return -1;
684
714
  }
685
- function openTurn(view, turnId, prompt) {
715
+ function openTurn(view, { turnId, prompt = "", skills = [] }) {
686
716
  const i = findLastIndex(view.blocks, (b) => b.type === "message" && b.role === "user");
687
717
  const sent = view.blocks[i];
688
- if (sent?.type === "message" && sent.turnId === void 0 && sent.text === prompt) {
689
- return { ...view, blocks: replaceAt(view.blocks, i, { ...sent, turnId }) };
690
- }
691
- 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 };
692
724
  }
693
725
  function streamText(view, { turnId, segmentId, text: text2 }) {
694
726
  const i = findLastIndex(view.blocks, (b) => isUnsettledSegment(b, turnId) && b.segmentId === segmentId);
@@ -835,7 +867,9 @@ function reduceConversation(view, input) {
835
867
  case "local_entry":
836
868
  return append(view, (id) => settledMessage(id, input.role, input.text));
837
869
  case "planner_turn_started":
838
- 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));
839
873
  case "planner_text_delta":
840
874
  return streamText(view, input);
841
875
  case "planner_message":
@@ -875,11 +909,27 @@ function reduceConversation(view, input) {
875
909
  var USER = 0;
876
910
  var RESEARCH = 1;
877
911
  var SETTLED = 2;
878
- function fromEntry(entry) {
912
+ function fromEntry(entry, loaded = []) {
879
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));
880
919
  const role = entry.kind === "system" || entry.kind === "compaction" ? "system" : entry.role === "user" ? "user" : "planner";
881
920
  return (id) => settledMessage(id(), role, entry.content);
882
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
+ }
883
933
  function spawnBrief(step) {
884
934
  try {
885
935
  const args = JSON.parse(step.args);
@@ -942,7 +992,7 @@ function fromTranscript(conversationHistory, researchLog, plannerUsage) {
942
992
  const kept = compacted ? history.slice(1) : history;
943
993
  const cutoff = compacted ? kept[0]?.timestamp ?? compacted.timestamp : "";
944
994
  const placed = [
945
- ...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)) })),
946
996
  ...research(researchLog ?? []).filter((item) => item.at >= cutoff)
947
997
  ];
948
998
  placed.sort((a, b) => a.at < b.at ? -1 : a.at > b.at ? 1 : a.rank - b.rank);
@@ -1126,6 +1176,8 @@ function unqueueMessage(view, { messageId }) {
1126
1176
  }
1127
1177
  function reduceTaskLog(view, event) {
1128
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(", ")}`));
1129
1181
  case "turn_start":
1130
1182
  return startTurn(view, event);
1131
1183
  case "turn_end":
@@ -1208,7 +1260,8 @@ var TURN_STREAM = /* @__PURE__ */ new Set([
1208
1260
  "research_step_done",
1209
1261
  "subagent_started",
1210
1262
  "subagent_finished",
1211
- "planner_turn_ended"
1263
+ "planner_turn_ended",
1264
+ "planner_skill_loaded"
1212
1265
  ]);
1213
1266
  function cutOff(gate, input) {
1214
1267
  if (gate.stopped === null || !TURN_STREAM.has(input.type)) return false;
@@ -1371,6 +1424,7 @@ function newTaskFields(title, prompt) {
1371
1424
  hasHiddenDetail,
1372
1425
  holdPrompt,
1373
1426
  isTaskRunning,
1427
+ loadedSkillTokens,
1374
1428
  markAction,
1375
1429
  markRequestFor,
1376
1430
  namedRepos,
@@ -1383,6 +1437,7 @@ function newTaskFields(title, prompt) {
1383
1437
  reduceTaskLog,
1384
1438
  replayTaskLog,
1385
1439
  runnerToolSubject,
1440
+ skillTokens,
1386
1441
  stopTurn,
1387
1442
  summarizeToolCall,
1388
1443
  taskOrderLabel,