agentfootprint-lens 0.42.0 → 0.44.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 (37) hide show
  1. package/README.md +91 -0
  2. package/dist/{chunk-VKBQYD6I.js → chunk-5YSPWSLW.js} +2 -2
  3. package/dist/{chunk-JE37MDVV.js → chunk-CGR5VFJU.js} +41 -2
  4. package/dist/chunk-CGR5VFJU.js.map +1 -0
  5. package/dist/{chunk-VBRT372Q.js → chunk-LCIEJYZG.js} +33 -1
  6. package/dist/chunk-LCIEJYZG.js.map +1 -0
  7. package/dist/{chunk-YQXVXNXK.js → chunk-LRGT7UQL.js} +4 -4
  8. package/dist/{chunk-F473UD5M.js → chunk-OQRL3II6.js} +12 -5
  9. package/dist/chunk-OQRL3II6.js.map +1 -0
  10. package/dist/{chunk-FFQ5EARP.js → chunk-QNMA25X5.js} +38 -12
  11. package/dist/chunk-QNMA25X5.js.map +1 -0
  12. package/dist/core.cjs +74 -0
  13. package/dist/core.cjs.map +1 -1
  14. package/dist/core.d.cts +106 -1
  15. package/dist/core.d.ts +106 -1
  16. package/dist/core.js +9 -3
  17. package/dist/index.cjs +114 -10
  18. package/dist/index.cjs.map +1 -1
  19. package/dist/index.d.cts +44 -2
  20. package/dist/index.d.ts +44 -2
  21. package/dist/index.js +12 -6
  22. package/dist/index.js.map +1 -1
  23. package/dist/skillgraph.cjs +69 -10
  24. package/dist/skillgraph.cjs.map +1 -1
  25. package/dist/skillgraph.d.cts +38 -1
  26. package/dist/skillgraph.d.ts +38 -1
  27. package/dist/skillgraph.js +3 -3
  28. package/dist/why.cjs +99 -8
  29. package/dist/why.cjs.map +1 -1
  30. package/dist/why.js +4 -4
  31. package/package.json +3 -2
  32. package/dist/chunk-F473UD5M.js.map +0 -1
  33. package/dist/chunk-FFQ5EARP.js.map +0 -1
  34. package/dist/chunk-JE37MDVV.js.map +0 -1
  35. package/dist/chunk-VBRT372Q.js.map +0 -1
  36. /package/dist/{chunk-VKBQYD6I.js.map → chunk-5YSPWSLW.js.map} +0 -0
  37. /package/dist/{chunk-YQXVXNXK.js.map → chunk-LRGT7UQL.js.map} +0 -0
package/README.md CHANGED
@@ -111,6 +111,20 @@ Lens watches agentfootprint's typed event stream — `agentfootprint.agent.*`,
111
111
  of the 65-type registry. You never wire events yourself; `recorder.observe()`
112
112
  subscribes to all of them.
113
113
 
114
+ **A long tool call is no longer a silence.** When a tool reports from inside
115
+ its own `execute` with `ctx.progress(payload)` (agentfootprint 9.52+), each
116
+ report lands in the stream between that call's start and its end:
117
+
118
+ ```
119
+ `walk_graph` reported progress (iteration 1): {"hop":1,"of":3,"node":"svc-a"}
120
+ ```
121
+
122
+ The three identity fields are stamped by the framework, so the line states them
123
+ as facts. The payload is the tool author's own data — the Lens shows a preview
124
+ of it rather than guessing at a shape it was never promised, and says so when
125
+ it had to cut one short. A tool that never calls `ctx.progress` files nothing,
126
+ and nothing here invents a report it did not make.
127
+
114
128
  ---
115
129
 
116
130
  ## Multiple watchers, one agent
@@ -586,6 +600,83 @@ a Vue or CLI shell.
586
600
 
587
601
  ---
588
602
 
603
+ ## Scrubbing without dead air — snap stops
604
+
605
+ Sharing an axis is not the same as sharing a stride.
606
+
607
+ A view mounted inside the lens scrubs the **host's** axis — that is the
608
+ one-cursor law working correctly. But the host's axis is the *run's*. A
609
+ four-tool turn puts 73 stops on it, and a view like the Skill Graph changes at
610
+ eight of them: 65 presses of ◀ ▶ walk framework stages that change nothing in
611
+ its picture. The scrubbing is not wrong, it is **dead air**.
612
+
613
+ The fix that must not be taken is a second slider with its own numbers. Two
614
+ transports over one run is the drift this package refuses. So pass `snapSteps` —
615
+ an ascending list of positions on the axis the transport **already has** — and
616
+ only the step buttons' landing set narrows:
617
+
618
+ ```tsx
619
+ <TimeTravel
620
+ total={73}
621
+ focusSeq={step}
622
+ onFocusChange={setStep}
623
+ isLive={false}
624
+ // ◀ ▶ and ← → now land only here. Everything else is untouched.
625
+ snapSteps={[0, 9, 17, 31, 44, 58, 72]}
626
+ />
627
+ ```
628
+
629
+ What stays true when it is set:
630
+
631
+ - **the drag track and the step strip keep the full axis** — every position is
632
+ still reachable, just not by ◀ ▶;
633
+ - **Home / End still go to the axis endpoints**, because they are jumps, not
634
+ steps (band clicks and strip clicks are jumps too, and also unaffected);
635
+ - **a position between two stops is disclosed, never rounded down.** Drag to a
636
+ step no stop covers and the readout says so — `between stops 2 and 3 of 4 ·
637
+ 8 / 12` — because with the buttons narrowed, that is a position they cannot
638
+ reproduce and the reader has to be told;
639
+ - **nothing is stored.** The position is still the host's `step`, and every
640
+ move still leaves through `onFocusChange(step)`.
641
+
642
+ Entries the axis cannot hold (negative, past the end, non-integer) are ignored —
643
+ a stop the axis does not have is not a stop. An empty list, or one whose entries
644
+ are all off-axis, behaves exactly as passing nothing.
645
+
646
+ `snapSteps` is orthogonal to `bands`: bands **group** the axis, snaps narrow the
647
+ unit of **movement** along it. Set both and the readout names all three truths —
648
+ `Iteration 2 · stop 3 of 4 · 10 / 12`.
649
+
650
+ `<SkillGraphDebugger>` forwards the same prop to the transport it mounts, so a
651
+ host can hand it the steps its routing picture actually changes at:
652
+
653
+ ```tsx
654
+ import { selectSkillBeats, selectSkillRoute, stepForRuntimeStageId } from 'agentfootprint-lens/skillgraph';
655
+
656
+ const beats = selectSkillBeats({ route: selectSkillRoute({ log: recorder.selectEventLog() }) });
657
+ const snapSteps = [
658
+ ...new Set(
659
+ beats
660
+ .map((b) => (b.runtimeStageId !== undefined ? stepForRuntimeStageId(positions, b.runtimeStageId) : -1))
661
+ .filter((s) => s >= 0),
662
+ ),
663
+ ].sort((a, b) => a - b);
664
+
665
+ <SkillGraphDebugger step={step} totalSteps={totalSteps} onStepChange={onNavigate} snapSteps={snapSteps} … />
666
+ ```
667
+
668
+ The host builds the list because the host owns the axis. On the debugger the
669
+ prop is **ignored when it is scrubbing its own routing stops** (no `step` /
670
+ `totalSteps`) — every routing stop already changes the picture, so there is
671
+ nothing to narrow.
672
+
673
+ Headless: `snapPositionOf`, `nextSnapStep` and `prevSnapStep` on
674
+ `agentfootprint-lens/core` are the pure queries behind it — the same
675
+ at-or-before resolution (with its `exact` flag) and the same strict
676
+ next/previous laws, for a shell that draws its own transport.
677
+
678
+ ---
679
+
589
680
  ## Driving the cursor from your app
590
681
 
591
682
  **Omitting these props keeps the lens self-driving.** It holds the position
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  formatBytes,
3
3
  structureGraphFromRunner
4
- } from "./chunk-JE37MDVV.js";
4
+ } from "./chunk-CGR5VFJU.js";
5
5
 
6
6
  // src/core/buildStepGraphFromSnapshot.ts
7
7
  function buildStepGraphFromSnapshot(snapshot) {
@@ -1189,4 +1189,4 @@ export {
1189
1189
  decisionSentence,
1190
1190
  isConsentDecision
1191
1191
  };
1192
- //# sourceMappingURL=chunk-VKBQYD6I.js.map
1192
+ //# sourceMappingURL=chunk-5YSPWSLW.js.map
@@ -3,7 +3,7 @@ import {
3
3
  humanizeRouteConflict,
4
4
  humanizeSkillRejected,
5
5
  humanizeTurnRouted
6
- } from "./chunk-VBRT372Q.js";
6
+ } from "./chunk-LCIEJYZG.js";
7
7
  import {
8
8
  selectAgentInstances
9
9
  } from "./chunk-2JAWSPNG.js";
@@ -1464,6 +1464,36 @@ function humanizeEvidenceChecked(p) {
1464
1464
  }
1465
1465
  }
1466
1466
 
1467
+ // src/core/humanizeToolProgress.ts
1468
+ var PREVIEW_LIMIT = 120;
1469
+ function previewProgressPayload(payload) {
1470
+ if (payload === void 0) return null;
1471
+ let text;
1472
+ if (typeof payload === "string") {
1473
+ text = payload;
1474
+ } else {
1475
+ try {
1476
+ const json = JSON.stringify(payload);
1477
+ if (json === void 0) return null;
1478
+ text = json;
1479
+ } catch {
1480
+ return "(payload could not be shown)";
1481
+ }
1482
+ }
1483
+ if (text.length <= PREVIEW_LIMIT) return text;
1484
+ return `${text.slice(0, PREVIEW_LIMIT)}\u2026 (truncated; ${text.length - PREVIEW_LIMIT} more chars)`;
1485
+ }
1486
+ function humanizeToolProgress(payload) {
1487
+ const tool = payload.toolName !== void 0 ? `\`${payload.toolName}\`` : "A tool";
1488
+ const iter = typeof payload.iteration === "number" && payload.iteration > 0 ? ` (iteration ${payload.iteration})` : "";
1489
+ const preview = previewProgressPayload(payload.payload);
1490
+ return preview === null ? `${tool} reported progress${iter}.` : `${tool} reported progress${iter}: ${preview}`;
1491
+ }
1492
+ function humanizeToolProgressTeaching(payload) {
1493
+ const tool = payload.toolName !== void 0 ? `The \`${payload.toolName}\` tool` : "A tool";
1494
+ return `${tool} reported progress while it was still running.`;
1495
+ }
1496
+
1467
1497
  // src/core/humanizeArtifacts.ts
1468
1498
  var ticket = (ref, kind, bytes) => `${ref ?? "art_?"} [${kind ?? "?"} \xB7 ${formatBytes(bytes ?? 0)}]`;
1469
1499
  function humanizeArtifactMinted(p) {
@@ -1552,6 +1582,12 @@ var defaultHumanizer = (event) => {
1552
1582
  return `Model replied in ${event.payload.durationMs}ms (${event.payload.usage.input}+${event.payload.usage.output} tokens, ${event.payload.toolCallCount} tool calls, stop: ${event.payload.stopReason}).`;
1553
1583
  case "agentfootprint.stream.tool_start":
1554
1584
  return `Calling tool "${event.payload.toolName}" with ${JSON.stringify(event.payload.args)}.`;
1585
+ // One report from INSIDE a still-running tool call (agentfootprint
1586
+ // 9.52.0). It arrives between this call's tool_start and its tool_end, so
1587
+ // the stream reads as the call speaking mid-flight. See humanizeToolProgress
1588
+ // for why the author's payload is previewed rather than interpreted.
1589
+ case "agentfootprint.stream.tool_progress":
1590
+ return humanizeToolProgress(event.payload);
1555
1591
  case "agentfootprint.stream.tool_end":
1556
1592
  return `Tool "${event.payload.toolCallId}" returned in ${event.payload.durationMs}ms${event.payload.error === true ? " (error)" : ""}.`;
1557
1593
  case "agentfootprint.stream.token":
@@ -1626,6 +1662,9 @@ function makeTeachingHumanizer(options = {}) {
1626
1662
  const templates = options.commentaryTemplates ? { ...defaultCommentaryTemplates, ...options.commentaryTemplates } : defaultCommentaryTemplates;
1627
1663
  const ctx = { appName, getToolDescription };
1628
1664
  return (event) => {
1665
+ if (event.type === "agentfootprint.stream.tool_progress") {
1666
+ return humanizeToolProgressTeaching(event.payload);
1667
+ }
1629
1668
  const key = selectCommentaryKey(event);
1630
1669
  if (key === null) return null;
1631
1670
  if (key === void 0) return defaultHumanizer(event);
@@ -2765,4 +2804,4 @@ export {
2765
2804
  structureGraphFromSpec,
2766
2805
  cursorProvenance
2767
2806
  };
2768
- //# sourceMappingURL=chunk-JE37MDVV.js.map
2807
+ //# sourceMappingURL=chunk-CGR5VFJU.js.map