agentfootprint-lens 0.41.0 → 0.43.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.
- package/README.md +78 -2
- package/dist/{useCursorPositions-CF9RDUw0.d.cts → Lens-B039-UGw.d.cts} +98 -48
- package/dist/{useCursorPositions-B1HJiarC.d.ts → Lens-ey1EgN9i.d.ts} +98 -48
- package/dist/{chunk-36MMC2GY.js → chunk-CWKOGPOJ.js} +219 -203
- package/dist/chunk-CWKOGPOJ.js.map +1 -0
- package/dist/{chunk-OZUS4IAS.js → chunk-F473UD5M.js} +3 -3
- package/dist/{chunk-OZUS4IAS.js.map → chunk-F473UD5M.js.map} +1 -1
- package/dist/{chunk-5E2N7IP7.js → chunk-FFQ5EARP.js} +2 -2
- package/dist/{chunk-HBVKOHFU.js → chunk-UWN5VKQ2.js} +2 -2
- package/dist/{chunk-XO5VNJYM.js → chunk-VBMVWQUO.js} +134 -77
- package/dist/chunk-VBMVWQUO.js.map +1 -0
- package/dist/{chunk-6RXMOK2E.js → chunk-VBRT372Q.js} +63 -8
- package/dist/chunk-VBRT372Q.js.map +1 -0
- package/dist/core.cjs +198 -82
- package/dist/core.cjs.map +1 -1
- package/dist/core.d.cts +5 -5
- package/dist/core.d.ts +5 -5
- package/dist/core.js +7 -3
- package/dist/index.cjs +424 -291
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +8 -8
- package/dist/index.d.ts +8 -8
- package/dist/index.js +11 -7
- package/dist/index.js.map +1 -1
- package/dist/{stepForRuntimeStageId-Bl6cG9wB.d.ts → resolveNavigation-o4E4cM_1.d.cts} +128 -1
- package/dist/{stepForRuntimeStageId-Bl6cG9wB.d.cts → resolveNavigation-o4E4cM_1.d.ts} +128 -1
- package/dist/{stepForCommitIdx-feXP5i-2.d.cts → scrubAxisFor-CNceBlz-.d.cts} +48 -2
- package/dist/{stepForCommitIdx-PnR_Kael.d.ts → scrubAxisFor-Cz214OHj.d.ts} +48 -2
- package/dist/{selectSkillFrameContext-AX9VtcCf.d.ts → selectSkillFrameContext-CT_EKu4u.d.cts} +1 -1
- package/dist/{selectSkillFrameContext-C19Sqv3W.d.cts → selectSkillFrameContext-D0xQV_px.d.ts} +1 -1
- package/dist/skillgraph.cjs +63 -7
- package/dist/skillgraph.cjs.map +1 -1
- package/dist/skillgraph.d.cts +15 -11
- package/dist/skillgraph.d.ts +15 -11
- package/dist/skillgraph.js +5 -3
- package/dist/why.cjs +259 -128
- package/dist/why.cjs.map +1 -1
- package/dist/why.d.cts +5 -5
- package/dist/why.d.ts +5 -5
- package/dist/why.js +8 -6
- package/dist/why.js.map +1 -1
- package/package.json +3 -2
- package/dist/chunk-36MMC2GY.js.map +0 -1
- package/dist/chunk-6RXMOK2E.js.map +0 -1
- package/dist/chunk-XO5VNJYM.js.map +0 -1
- /package/dist/{chunk-5E2N7IP7.js.map → chunk-FFQ5EARP.js.map} +0 -0
- /package/dist/{chunk-HBVKOHFU.js.map → chunk-UWN5VKQ2.js.map} +0 -0
package/README.md
CHANGED
|
@@ -76,8 +76,8 @@ changes.
|
|
|
76
76
|
|
|
77
77
|
| import | the job |
|
|
78
78
|
|---|---|
|
|
79
|
-
| `agentfootprint-lens/why` | Replay a recording as the agent's own milestones. `<WhyLens recording={...} />` takes the recording straight (`recordRun()`'s `{ snapshot, events, structure }`, or the `persistRecording` envelope), validates it at mount, and mounts the shipped `<Lens>` shell on the milestone axis — plus the axis helpers (`scrubAxisFor`, `stepForCommitIdx`, `stepForRuntimeStageId`) for hosts holding one cursor across views. |
|
|
80
|
-
| `agentfootprint-lens/skillgraph` | Debug how a run routed through its skills. `<SkillGraphDebugger recorder={...} />` plus its headless selectors (`selectSkillRoute`, `selectSkillBeats`, `selectSkillTopology`, `selectSkillFrameContext`, `stepForRuntimeStageId`). |
|
|
79
|
+
| `agentfootprint-lens/why` | Replay a recording as the agent's own milestones. `<WhyLens recording={...} />` takes the recording straight (`recordRun()`'s `{ snapshot, events, structure }`, or the `persistRecording` envelope), validates it at mount, and mounts the shipped `<Lens>` shell on the milestone axis — plus the axis helpers (`scrubAxisFor`, `stepForCommitIdx`, `stepForRuntimeStageId`, `resolveNavigation`) for hosts holding one cursor across views. |
|
|
80
|
+
| `agentfootprint-lens/skillgraph` | Debug how a run routed through its skills. `<SkillGraphDebugger recorder={...} />` plus its headless selectors (`selectSkillRoute`, `selectSkillBeats`, `selectSkillTopology`, `selectSkillFrameContext`, `stepForRuntimeStageId`, `resolveNavigation`). |
|
|
81
81
|
|
|
82
82
|
The axis model in three sentences: one run leaves one causal trace, and each
|
|
83
83
|
lens replays one AXIS of it — the Why reading scrubs the milestones, the Flow
|
|
@@ -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
|
|
@@ -654,6 +668,67 @@ click, a WHAT HAPPENED moment, a provenance jump, and the auto-advance that
|
|
|
654
668
|
follows a live run. One cursor, one funnel — a mover that moved without telling
|
|
655
669
|
you would be a second cursor wearing the first one's clothes.
|
|
656
670
|
|
|
671
|
+
### Pointing at a step: `navigatorRef`
|
|
672
|
+
|
|
673
|
+
`step` lets you *own* the cursor. `navigatorRef` lets you *say where* — when the
|
|
674
|
+
only thing you know is a stage's address. That is what a chat answer has: it can
|
|
675
|
+
tell you the tool call went wrong, and now it can point at the exact step it
|
|
676
|
+
means.
|
|
677
|
+
|
|
678
|
+
```tsx
|
|
679
|
+
import { Lens, type LensNavigator } from 'agentfootprint-lens';
|
|
680
|
+
|
|
681
|
+
const nav = useRef<LensNavigator>(null);
|
|
682
|
+
|
|
683
|
+
<Lens recorder={recorder} navigatorRef={nav} />
|
|
684
|
+
|
|
685
|
+
// Anywhere — a chat message, a dashboard row, a deep link:
|
|
686
|
+
const to = nav.current?.navigateTo('call-llm#18');
|
|
687
|
+
// → { ok: true, step: 7, runtimeStageId: 'call-llm#18', match: 'exact', label: 'call-llm 1' }
|
|
688
|
+
```
|
|
689
|
+
|
|
690
|
+
It resolves against **the ruler you are actually scrubbing**, so the same
|
|
691
|
+
address is step 7 under `granularity="step"` and step 3 under
|
|
692
|
+
`granularity="group"` — and then it goes through the *same funnel* a click on
|
|
693
|
+
that stop uses. Uncontrolled, the lens moves and reports. Controlled, it reports
|
|
694
|
+
and your `step` lands it. Nothing new holds a position.
|
|
695
|
+
|
|
696
|
+
**A miss is answered, never guessed.** Three rungs, in order:
|
|
697
|
+
|
|
698
|
+
| | what happened | you get |
|
|
699
|
+
|---|---|---|
|
|
700
|
+
| `match: 'exact'` | a stop **is** that address | `{ ok: true, step, label }` |
|
|
701
|
+
| `match: 'enclosing'` | no stop is that address, but one **contains** it (a stage inside a subflow, on a ruler that stops at whole subflows) | `{ ok: true, step, runtimeStageId }` — the stop's own address, so you always know where it went |
|
|
702
|
+
| — | nothing holds it | `{ ok: false, reason, message, nearest? }` — **the cursor did not move** |
|
|
703
|
+
|
|
704
|
+
`nearest` is the stop just *before* the address, handed back as data. It is an
|
|
705
|
+
**offer, not a jump**: a cursor that silently lands somewhere the person did not
|
|
706
|
+
ask for is worse than one that stays put. Take it when you want to — one more
|
|
707
|
+
call, and it is an exact hit by construction:
|
|
708
|
+
|
|
709
|
+
```tsx
|
|
710
|
+
const to = nav.current?.navigateTo(stageId);
|
|
711
|
+
if (to?.ok) {
|
|
712
|
+
// landed
|
|
713
|
+
} else if (to?.nearest) {
|
|
714
|
+
// "That step isn't on this ruler. Go to Iteration 1 instead?"
|
|
715
|
+
onConfirm(() => nav.current?.navigateTo(to.nearest.runtimeStageId));
|
|
716
|
+
} else {
|
|
717
|
+
show(to?.message); // says exactly why, in a sentence you can print
|
|
718
|
+
}
|
|
719
|
+
```
|
|
720
|
+
|
|
721
|
+
**No component? Same answer.** The resolver is pure and ships headlessly, so a
|
|
722
|
+
server-rendered link or a CLI can compute the step with nothing mounted:
|
|
723
|
+
|
|
724
|
+
```ts
|
|
725
|
+
import { scrubAxisFor, resolveNavigation } from 'agentfootprint-lens/core';
|
|
726
|
+
|
|
727
|
+
const positions = scrubAxisFor(recorder, 'step'); // the ruler, as data
|
|
728
|
+
const to = resolveNavigation(positions, 'call-llm#18');
|
|
729
|
+
const href = to.ok ? `/runs/${runId}?step=${to.step}` : undefined;
|
|
730
|
+
```
|
|
731
|
+
|
|
657
732
|
---
|
|
658
733
|
|
|
659
734
|
## Rendering your own detail pane
|
|
@@ -812,6 +887,7 @@ graph in one call. Returns an unsubscribe. Call it once per run.
|
|
|
812
887
|
| `granularity` | `'step' \| 'group'?` | Which ruler is scrubbing the chart. `'group'` paints the cursor's group as a named place. Default `'step'`. See [Scrubbing by group](#scrubbing-by-group--the-active-group-is-a-named-place). |
|
|
813
888
|
| `step` | `number?` | Controlled cursor. **Omit it and the lens is self-driving, exactly as before.** Pass it and you own the position; out-of-range values are clamped and reported. See [Driving the cursor](#driving-the-cursor-from-your-app). |
|
|
814
889
|
| `onStepChange` | `(step, at) => void?` | Fires on every cursor move — required for movement in controlled mode, an observation hook otherwise. `at` carries `runtimeStageId`, `commitIdx`, `label`, `kind` and `clamped`. |
|
|
890
|
+
| `navigatorRef` | `Ref<LensNavigator>?` | Move the cursor to a stage **by its `runtimeStageId`**. `ref.current.navigateTo(id)` returns `{ ok: true, step, match, label }` or `{ ok: false, reason, message, nearest? }` — a miss never moves. See [Pointing at a step](#pointing-at-a-step-navigatorref). |
|
|
815
891
|
| `slots` | `LensSlots?` | Slot overrides. `slots.detail` renders your content in the shipped right column. Omit for the built-in timeline. See [Rendering your own detail pane](#rendering-your-own-detail-pane). |
|
|
816
892
|
|
|
817
893
|
### `<LensFlow>` — the chart canvas on its own
|
|
@@ -2,9 +2,9 @@ import * as agentfootprint_observe from 'agentfootprint/observe';
|
|
|
2
2
|
import { ToolChoiceCall, ToolChoiceSummary } from 'agentfootprint/observe';
|
|
3
3
|
import * as agentfootprint from 'agentfootprint';
|
|
4
4
|
import { CommentaryTemplates } from 'agentfootprint';
|
|
5
|
-
import React__default from 'react';
|
|
6
|
-
import {
|
|
7
|
-
import { C as ChartGroupHighlight, H as Humanizer } from './
|
|
5
|
+
import React__default, { Ref } from 'react';
|
|
6
|
+
import { d as NavigationResult, C as CursorPosition, L as LensRecorder } from './resolveNavigation-o4E4cM_1.cjs';
|
|
7
|
+
import { C as ChartGroupHighlight, H as Humanizer } from './scrubAxisFor-CNceBlz-.cjs';
|
|
8
8
|
import { NodeTypes } from '@xyflow/react';
|
|
9
9
|
import { TraceGraph, TraceFlowLayout, RuntimeOverlay } from 'footprint-explainable-ui/flowchart';
|
|
10
10
|
|
|
@@ -217,6 +217,73 @@ interface UseLensCursorResult {
|
|
|
217
217
|
declare function clampStep(n: number, maxStep: number): number;
|
|
218
218
|
declare function useLensCursor({ controlledStep, onStepChange, maxStep, describe, }: UseLensCursorArgs): UseLensCursorResult;
|
|
219
219
|
|
|
220
|
+
/**
|
|
221
|
+
* useLensNavigator — move the ONE cursor to a stage by its address.
|
|
222
|
+
*
|
|
223
|
+
* `<Lens step onStepChange>` lets a host OWN the cursor. This is the other
|
|
224
|
+
* half a pointing host needs: a way to SAY WHERE, when the only thing it knows
|
|
225
|
+
* is a `runtimeStageId` — a chat answer citing the step it means, a dashboard
|
|
226
|
+
* row, a deep link.
|
|
227
|
+
*
|
|
228
|
+
* THE ONE-CURSOR LAW, kept: this adds NO state and NO second channel. It is a
|
|
229
|
+
* RESOLUTION (`resolveNavigation`, the shipped ladder) followed by the SAME
|
|
230
|
+
* `moveTo` funnel every internal mover already goes through — the step strip,
|
|
231
|
+
* the ◀ ▶ buttons, the arrow keys, a chart click, the live auto-advance. So it
|
|
232
|
+
* behaves exactly like a person clicking that stop:
|
|
233
|
+
*
|
|
234
|
+
* - **Uncontrolled** — the cursor moves, and `onStepChange` reports it.
|
|
235
|
+
* - **Controlled** — nothing moves on its own; `onStepChange` fires with the
|
|
236
|
+
* step and the host's own `step` prop lands it. Two owners never fight,
|
|
237
|
+
* because there is still only one owner.
|
|
238
|
+
* - **Already there** — no move, no event (a non-move is not a change), and
|
|
239
|
+
* still `{ ok: true }` with the step the cursor is standing on.
|
|
240
|
+
*
|
|
241
|
+
* HONEST MISSES: an address the axis cannot hold comes back `{ ok: false }`
|
|
242
|
+
* with the nearest-previous stop OFFERED as data, never taken. See
|
|
243
|
+
* `resolveNavigation` for the ladder.
|
|
244
|
+
*
|
|
245
|
+
* @example The handle, on the component.
|
|
246
|
+
* ```tsx
|
|
247
|
+
* const nav = useRef<LensNavigator>(null);
|
|
248
|
+
*
|
|
249
|
+
* <Lens recorder={recorder} navigatorRef={nav} />
|
|
250
|
+
*
|
|
251
|
+
* // Later — a chat answer points at its evidence:
|
|
252
|
+
* const to = nav.current?.navigateTo('llm#7');
|
|
253
|
+
* if (to?.ok) show(`Jumped to ${to.label}`);
|
|
254
|
+
* else if (to?.nearest) offer(`Not on this ruler. Go to ${to.nearest.label}?`);
|
|
255
|
+
* // Taking the offer is one more call — `nearest.runtimeStageId` is an exact
|
|
256
|
+
* // hit by construction:
|
|
257
|
+
* // nav.current?.navigateTo(to.nearest.runtimeStageId);
|
|
258
|
+
* ```
|
|
259
|
+
*/
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* The imperative handle `<Lens navigatorRef>` fills in — the lens's cursor,
|
|
263
|
+
* addressable by stage.
|
|
264
|
+
*/
|
|
265
|
+
interface LensNavigator {
|
|
266
|
+
/**
|
|
267
|
+
* Move the ONE cursor to the stop that holds `runtimeStageId`, on whatever
|
|
268
|
+
* axis the lens is currently scrubbing (`granularity="step"` → the commit
|
|
269
|
+
* axis, `granularity="group"` → the milestone axis).
|
|
270
|
+
*
|
|
271
|
+
* Returns where it went — or, on a miss, why it did not and what was nearby.
|
|
272
|
+
* Never throws, and never moves on a miss.
|
|
273
|
+
*/
|
|
274
|
+
navigateTo(runtimeStageId: string): NavigationResult;
|
|
275
|
+
}
|
|
276
|
+
interface UseLensNavigatorArgs {
|
|
277
|
+
/** The ACTIVE scrub axis — the same list the lens renders its ruler from. */
|
|
278
|
+
readonly positions: readonly CursorPosition[];
|
|
279
|
+
/** The one cursor funnel (`useLensCursor`'s `moveTo`). */
|
|
280
|
+
readonly moveTo: (step: number) => void;
|
|
281
|
+
/** The host's ref, filled with the handle. Omit and the hook still returns
|
|
282
|
+
* the navigator for in-tree use. */
|
|
283
|
+
readonly navigatorRef?: Ref<LensNavigator> | undefined;
|
|
284
|
+
}
|
|
285
|
+
declare function useLensNavigator({ positions, moveTo, navigatorRef, }: UseLensNavigatorArgs): LensNavigator;
|
|
286
|
+
|
|
220
287
|
/**
|
|
221
288
|
* useToolChoice — async reader for the agentfootprint/observe
|
|
222
289
|
* `toolChoiceRecorder` handle (RFC-002 block C7).
|
|
@@ -498,6 +565,33 @@ interface LensProps {
|
|
|
498
565
|
* Memoize via `useCallback` to avoid downstream re-renders.
|
|
499
566
|
*/
|
|
500
567
|
readonly onStepChange?: (step: number, at: LensCursorAt) => void;
|
|
568
|
+
/**
|
|
569
|
+
* Move the cursor to a STAGE, by its address — the pointing half of the
|
|
570
|
+
* cursor API. `step` / `onStepChange` let a host OWN the cursor; this lets
|
|
571
|
+
* one SAY WHERE when all it knows is a `runtimeStageId` (a chat answer
|
|
572
|
+
* citing the step it means, a dashboard row, a deep link).
|
|
573
|
+
*
|
|
574
|
+
* ```tsx
|
|
575
|
+
* const nav = useRef<LensNavigator>(null);
|
|
576
|
+
* <Lens recorder={recorder} navigatorRef={nav} />
|
|
577
|
+
*
|
|
578
|
+
* const to = nav.current?.navigateTo('llm#7');
|
|
579
|
+
* // { ok: true, step: 7, runtimeStageId: 'llm#7', match: 'exact', label: … }
|
|
580
|
+
* ```
|
|
581
|
+
*
|
|
582
|
+
* It is a RESOLUTION plus the cursor channel you already have — not a second
|
|
583
|
+
* channel. The address is resolved against the ACTIVE axis (`granularity`),
|
|
584
|
+
* then handed to the same funnel a click on that stop uses: uncontrolled,
|
|
585
|
+
* the lens moves and reports; controlled, it reports and your `step` lands
|
|
586
|
+
* it. Nothing here holds a position.
|
|
587
|
+
*
|
|
588
|
+
* An address the axis cannot hold comes back `{ ok: false, reason, message }`
|
|
589
|
+
* with the nearest earlier stop OFFERED as `nearest` — never taken. The
|
|
590
|
+
* caller decides. See `resolveNavigation` for the ladder (exact → enclosing
|
|
591
|
+
* → nearest-previous-as-an-offer), which is also exported headlessly for
|
|
592
|
+
* hosts with nothing mounted.
|
|
593
|
+
*/
|
|
594
|
+
readonly navigatorRef?: React__default.Ref<LensNavigator>;
|
|
501
595
|
/**
|
|
502
596
|
* Optional slot overrides. Should be stable across renders (define at module
|
|
503
597
|
* scope or `useMemo`). Omit and the shipped panes render unchanged.
|
|
@@ -548,48 +642,4 @@ interface LensDetailSlotProps {
|
|
|
548
642
|
}
|
|
549
643
|
declare const Lens: React__default.FC<LensProps>;
|
|
550
644
|
|
|
551
|
-
|
|
552
|
-
* useCursorPositions — React hook exposing the slider's valid positions
|
|
553
|
-
* at the current drill level, on the requested AXIS.
|
|
554
|
-
*
|
|
555
|
-
* Layer 2 / Tier B / Lens v0.1.
|
|
556
|
-
*
|
|
557
|
-
* TWO AXES, ONE CURSOR (the 0.39.0 correction):
|
|
558
|
-
*
|
|
559
|
-
* `'commit'` — one stop per executed stage, straight off the commit log.
|
|
560
|
-
* The Flow Lens's axis (`granularity="step"`): every stage
|
|
561
|
-
* is a stop, nothing skippable, and the ruler's count is the
|
|
562
|
-
* commit log's count by construction.
|
|
563
|
-
* `'milestone'` — one stop per agent-meaningful moment (iteration → context
|
|
564
|
-
* → LLM turn → route → tool call), classified by the
|
|
565
|
-
* domain's `milestoneFor`. The Why Lens's axis
|
|
566
|
-
* (`granularity="group"`), which `stepBands` bands by
|
|
567
|
-
* iteration.
|
|
568
|
-
*
|
|
569
|
-
* The cursor type is still `runtimeStageId` either way. Only the SET of valid
|
|
570
|
-
* positions differs — the same compound-time-axis rule that already scaled the
|
|
571
|
-
* set by drill depth now also scales it by reading.
|
|
572
|
-
*
|
|
573
|
-
* Lifecycle
|
|
574
|
-
* ─────────
|
|
575
|
-
* Reactive to BOTH the recorder (events advance the commit log /
|
|
576
|
-
* open new groups) and to `drillPath` changes (user drill-in /
|
|
577
|
-
* drill-out). Memoized so a stable drillPath + recorder = stable
|
|
578
|
-
* array identity.
|
|
579
|
-
*/
|
|
580
|
-
|
|
581
|
-
/** Which projection of the run the scrub axis stops at. */
|
|
582
|
-
type ScrubAxis = 'commit' | 'milestone';
|
|
583
|
-
/**
|
|
584
|
-
* The scrub axis for a recording, as a PURE function — the same positions the
|
|
585
|
-
* mounted `<Lens>` scrubs at that granularity, computable outside React.
|
|
586
|
-
*
|
|
587
|
-
* This is the export a HOST holding the cursor across two granularities needs:
|
|
588
|
-
* to carry a position from one axis to the other, build the target axis here
|
|
589
|
-
* and resolve the commit with `stepForCommitIdx` (or an address with
|
|
590
|
-
* `stepForRuntimeStageId`). Returns `[]` when the recording has no commits yet
|
|
591
|
-
* (or on any read error — same posture as the hook).
|
|
592
|
-
*/
|
|
593
|
-
declare function scrubAxisFor(recorder: LensRecorder, granularity: 'step' | 'group', drillPath?: readonly string[]): readonly CursorPosition[];
|
|
594
|
-
|
|
595
|
-
export { type LensProps as L, type ScrubAxis as S, type ToolChoiceSource as T, type UseLensCursorArgs as U, Lens as a, type LensCursorAt as b, type LensDetailSlotProps as c, type LensSlots as d, type LensTheme as e, type LensView as f, type LensCursorPlace as g, LensFlow as h, type LensFlowProps as i, type UseLensCursorResult as j, type UseToolChoiceResult as k, clampStep as l, useToolChoice as m, scrubAxisFor as s, useLensCursor as u };
|
|
645
|
+
export { type LensProps as L, type ToolChoiceSource as T, type UseLensCursorArgs as U, Lens as a, type LensCursorAt as b, type LensDetailSlotProps as c, type LensSlots as d, type LensTheme as e, type LensView as f, type LensCursorPlace as g, LensFlow as h, type LensFlowProps as i, type LensNavigator as j, type UseLensCursorResult as k, type UseLensNavigatorArgs as l, type UseToolChoiceResult as m, clampStep as n, useLensNavigator as o, useToolChoice as p, useLensCursor as u };
|
|
@@ -2,9 +2,9 @@ import * as agentfootprint_observe from 'agentfootprint/observe';
|
|
|
2
2
|
import { ToolChoiceCall, ToolChoiceSummary } from 'agentfootprint/observe';
|
|
3
3
|
import * as agentfootprint from 'agentfootprint';
|
|
4
4
|
import { CommentaryTemplates } from 'agentfootprint';
|
|
5
|
-
import React__default from 'react';
|
|
6
|
-
import {
|
|
7
|
-
import { C as ChartGroupHighlight, H as Humanizer } from './
|
|
5
|
+
import React__default, { Ref } from 'react';
|
|
6
|
+
import { d as NavigationResult, C as CursorPosition, L as LensRecorder } from './resolveNavigation-o4E4cM_1.js';
|
|
7
|
+
import { C as ChartGroupHighlight, H as Humanizer } from './scrubAxisFor-Cz214OHj.js';
|
|
8
8
|
import { NodeTypes } from '@xyflow/react';
|
|
9
9
|
import { TraceGraph, TraceFlowLayout, RuntimeOverlay } from 'footprint-explainable-ui/flowchart';
|
|
10
10
|
|
|
@@ -217,6 +217,73 @@ interface UseLensCursorResult {
|
|
|
217
217
|
declare function clampStep(n: number, maxStep: number): number;
|
|
218
218
|
declare function useLensCursor({ controlledStep, onStepChange, maxStep, describe, }: UseLensCursorArgs): UseLensCursorResult;
|
|
219
219
|
|
|
220
|
+
/**
|
|
221
|
+
* useLensNavigator — move the ONE cursor to a stage by its address.
|
|
222
|
+
*
|
|
223
|
+
* `<Lens step onStepChange>` lets a host OWN the cursor. This is the other
|
|
224
|
+
* half a pointing host needs: a way to SAY WHERE, when the only thing it knows
|
|
225
|
+
* is a `runtimeStageId` — a chat answer citing the step it means, a dashboard
|
|
226
|
+
* row, a deep link.
|
|
227
|
+
*
|
|
228
|
+
* THE ONE-CURSOR LAW, kept: this adds NO state and NO second channel. It is a
|
|
229
|
+
* RESOLUTION (`resolveNavigation`, the shipped ladder) followed by the SAME
|
|
230
|
+
* `moveTo` funnel every internal mover already goes through — the step strip,
|
|
231
|
+
* the ◀ ▶ buttons, the arrow keys, a chart click, the live auto-advance. So it
|
|
232
|
+
* behaves exactly like a person clicking that stop:
|
|
233
|
+
*
|
|
234
|
+
* - **Uncontrolled** — the cursor moves, and `onStepChange` reports it.
|
|
235
|
+
* - **Controlled** — nothing moves on its own; `onStepChange` fires with the
|
|
236
|
+
* step and the host's own `step` prop lands it. Two owners never fight,
|
|
237
|
+
* because there is still only one owner.
|
|
238
|
+
* - **Already there** — no move, no event (a non-move is not a change), and
|
|
239
|
+
* still `{ ok: true }` with the step the cursor is standing on.
|
|
240
|
+
*
|
|
241
|
+
* HONEST MISSES: an address the axis cannot hold comes back `{ ok: false }`
|
|
242
|
+
* with the nearest-previous stop OFFERED as data, never taken. See
|
|
243
|
+
* `resolveNavigation` for the ladder.
|
|
244
|
+
*
|
|
245
|
+
* @example The handle, on the component.
|
|
246
|
+
* ```tsx
|
|
247
|
+
* const nav = useRef<LensNavigator>(null);
|
|
248
|
+
*
|
|
249
|
+
* <Lens recorder={recorder} navigatorRef={nav} />
|
|
250
|
+
*
|
|
251
|
+
* // Later — a chat answer points at its evidence:
|
|
252
|
+
* const to = nav.current?.navigateTo('llm#7');
|
|
253
|
+
* if (to?.ok) show(`Jumped to ${to.label}`);
|
|
254
|
+
* else if (to?.nearest) offer(`Not on this ruler. Go to ${to.nearest.label}?`);
|
|
255
|
+
* // Taking the offer is one more call — `nearest.runtimeStageId` is an exact
|
|
256
|
+
* // hit by construction:
|
|
257
|
+
* // nav.current?.navigateTo(to.nearest.runtimeStageId);
|
|
258
|
+
* ```
|
|
259
|
+
*/
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* The imperative handle `<Lens navigatorRef>` fills in — the lens's cursor,
|
|
263
|
+
* addressable by stage.
|
|
264
|
+
*/
|
|
265
|
+
interface LensNavigator {
|
|
266
|
+
/**
|
|
267
|
+
* Move the ONE cursor to the stop that holds `runtimeStageId`, on whatever
|
|
268
|
+
* axis the lens is currently scrubbing (`granularity="step"` → the commit
|
|
269
|
+
* axis, `granularity="group"` → the milestone axis).
|
|
270
|
+
*
|
|
271
|
+
* Returns where it went — or, on a miss, why it did not and what was nearby.
|
|
272
|
+
* Never throws, and never moves on a miss.
|
|
273
|
+
*/
|
|
274
|
+
navigateTo(runtimeStageId: string): NavigationResult;
|
|
275
|
+
}
|
|
276
|
+
interface UseLensNavigatorArgs {
|
|
277
|
+
/** The ACTIVE scrub axis — the same list the lens renders its ruler from. */
|
|
278
|
+
readonly positions: readonly CursorPosition[];
|
|
279
|
+
/** The one cursor funnel (`useLensCursor`'s `moveTo`). */
|
|
280
|
+
readonly moveTo: (step: number) => void;
|
|
281
|
+
/** The host's ref, filled with the handle. Omit and the hook still returns
|
|
282
|
+
* the navigator for in-tree use. */
|
|
283
|
+
readonly navigatorRef?: Ref<LensNavigator> | undefined;
|
|
284
|
+
}
|
|
285
|
+
declare function useLensNavigator({ positions, moveTo, navigatorRef, }: UseLensNavigatorArgs): LensNavigator;
|
|
286
|
+
|
|
220
287
|
/**
|
|
221
288
|
* useToolChoice — async reader for the agentfootprint/observe
|
|
222
289
|
* `toolChoiceRecorder` handle (RFC-002 block C7).
|
|
@@ -498,6 +565,33 @@ interface LensProps {
|
|
|
498
565
|
* Memoize via `useCallback` to avoid downstream re-renders.
|
|
499
566
|
*/
|
|
500
567
|
readonly onStepChange?: (step: number, at: LensCursorAt) => void;
|
|
568
|
+
/**
|
|
569
|
+
* Move the cursor to a STAGE, by its address — the pointing half of the
|
|
570
|
+
* cursor API. `step` / `onStepChange` let a host OWN the cursor; this lets
|
|
571
|
+
* one SAY WHERE when all it knows is a `runtimeStageId` (a chat answer
|
|
572
|
+
* citing the step it means, a dashboard row, a deep link).
|
|
573
|
+
*
|
|
574
|
+
* ```tsx
|
|
575
|
+
* const nav = useRef<LensNavigator>(null);
|
|
576
|
+
* <Lens recorder={recorder} navigatorRef={nav} />
|
|
577
|
+
*
|
|
578
|
+
* const to = nav.current?.navigateTo('llm#7');
|
|
579
|
+
* // { ok: true, step: 7, runtimeStageId: 'llm#7', match: 'exact', label: … }
|
|
580
|
+
* ```
|
|
581
|
+
*
|
|
582
|
+
* It is a RESOLUTION plus the cursor channel you already have — not a second
|
|
583
|
+
* channel. The address is resolved against the ACTIVE axis (`granularity`),
|
|
584
|
+
* then handed to the same funnel a click on that stop uses: uncontrolled,
|
|
585
|
+
* the lens moves and reports; controlled, it reports and your `step` lands
|
|
586
|
+
* it. Nothing here holds a position.
|
|
587
|
+
*
|
|
588
|
+
* An address the axis cannot hold comes back `{ ok: false, reason, message }`
|
|
589
|
+
* with the nearest earlier stop OFFERED as `nearest` — never taken. The
|
|
590
|
+
* caller decides. See `resolveNavigation` for the ladder (exact → enclosing
|
|
591
|
+
* → nearest-previous-as-an-offer), which is also exported headlessly for
|
|
592
|
+
* hosts with nothing mounted.
|
|
593
|
+
*/
|
|
594
|
+
readonly navigatorRef?: React__default.Ref<LensNavigator>;
|
|
501
595
|
/**
|
|
502
596
|
* Optional slot overrides. Should be stable across renders (define at module
|
|
503
597
|
* scope or `useMemo`). Omit and the shipped panes render unchanged.
|
|
@@ -548,48 +642,4 @@ interface LensDetailSlotProps {
|
|
|
548
642
|
}
|
|
549
643
|
declare const Lens: React__default.FC<LensProps>;
|
|
550
644
|
|
|
551
|
-
|
|
552
|
-
* useCursorPositions — React hook exposing the slider's valid positions
|
|
553
|
-
* at the current drill level, on the requested AXIS.
|
|
554
|
-
*
|
|
555
|
-
* Layer 2 / Tier B / Lens v0.1.
|
|
556
|
-
*
|
|
557
|
-
* TWO AXES, ONE CURSOR (the 0.39.0 correction):
|
|
558
|
-
*
|
|
559
|
-
* `'commit'` — one stop per executed stage, straight off the commit log.
|
|
560
|
-
* The Flow Lens's axis (`granularity="step"`): every stage
|
|
561
|
-
* is a stop, nothing skippable, and the ruler's count is the
|
|
562
|
-
* commit log's count by construction.
|
|
563
|
-
* `'milestone'` — one stop per agent-meaningful moment (iteration → context
|
|
564
|
-
* → LLM turn → route → tool call), classified by the
|
|
565
|
-
* domain's `milestoneFor`. The Why Lens's axis
|
|
566
|
-
* (`granularity="group"`), which `stepBands` bands by
|
|
567
|
-
* iteration.
|
|
568
|
-
*
|
|
569
|
-
* The cursor type is still `runtimeStageId` either way. Only the SET of valid
|
|
570
|
-
* positions differs — the same compound-time-axis rule that already scaled the
|
|
571
|
-
* set by drill depth now also scales it by reading.
|
|
572
|
-
*
|
|
573
|
-
* Lifecycle
|
|
574
|
-
* ─────────
|
|
575
|
-
* Reactive to BOTH the recorder (events advance the commit log /
|
|
576
|
-
* open new groups) and to `drillPath` changes (user drill-in /
|
|
577
|
-
* drill-out). Memoized so a stable drillPath + recorder = stable
|
|
578
|
-
* array identity.
|
|
579
|
-
*/
|
|
580
|
-
|
|
581
|
-
/** Which projection of the run the scrub axis stops at. */
|
|
582
|
-
type ScrubAxis = 'commit' | 'milestone';
|
|
583
|
-
/**
|
|
584
|
-
* The scrub axis for a recording, as a PURE function — the same positions the
|
|
585
|
-
* mounted `<Lens>` scrubs at that granularity, computable outside React.
|
|
586
|
-
*
|
|
587
|
-
* This is the export a HOST holding the cursor across two granularities needs:
|
|
588
|
-
* to carry a position from one axis to the other, build the target axis here
|
|
589
|
-
* and resolve the commit with `stepForCommitIdx` (or an address with
|
|
590
|
-
* `stepForRuntimeStageId`). Returns `[]` when the recording has no commits yet
|
|
591
|
-
* (or on any read error — same posture as the hook).
|
|
592
|
-
*/
|
|
593
|
-
declare function scrubAxisFor(recorder: LensRecorder, granularity: 'step' | 'group', drillPath?: readonly string[]): readonly CursorPosition[];
|
|
594
|
-
|
|
595
|
-
export { type LensProps as L, type ScrubAxis as S, type ToolChoiceSource as T, type UseLensCursorArgs as U, Lens as a, type LensCursorAt as b, type LensDetailSlotProps as c, type LensSlots as d, type LensTheme as e, type LensView as f, type LensCursorPlace as g, LensFlow as h, type LensFlowProps as i, type UseLensCursorResult as j, type UseToolChoiceResult as k, clampStep as l, useToolChoice as m, scrubAxisFor as s, useLensCursor as u };
|
|
645
|
+
export { type LensProps as L, type ToolChoiceSource as T, type UseLensCursorArgs as U, Lens as a, type LensCursorAt as b, type LensDetailSlotProps as c, type LensSlots as d, type LensTheme as e, type LensView as f, type LensCursorPlace as g, LensFlow as h, type LensFlowProps as i, type LensNavigator as j, type UseLensCursorResult as k, type UseLensNavigatorArgs as l, type UseToolChoiceResult as m, clampStep as n, useLensNavigator as o, useToolChoice as p, useLensCursor as u };
|