agentfootprint-lens 0.46.0 → 0.47.1
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 +152 -16
- package/dist/{Lens-Bdz-JzVm.d.ts → Lens-9wZ84e70.d.ts} +2 -2
- package/dist/{Lens-6elRg27j.d.cts → Lens-Ccs8UUDQ.d.cts} +2 -2
- package/dist/{chunk-SJEKKUTI.js → chunk-4PENVNUY.js} +520 -2
- package/dist/chunk-4PENVNUY.js.map +1 -0
- package/dist/{chunk-A4EIPCLY.js → chunk-UO6IZSBY.js} +1176 -279
- package/dist/chunk-UO6IZSBY.js.map +1 -0
- package/dist/{chunk-WN2RJKEH.js → chunk-XFNFYUPC.js} +2 -2
- package/dist/core.cjs +519 -2
- package/dist/core.cjs.map +1 -1
- package/dist/core.d.cts +447 -8
- package/dist/core.d.ts +447 -8
- package/dist/core.js +18 -4
- package/dist/index.cjs +2145 -735
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +139 -10
- package/dist/index.d.ts +139 -10
- package/dist/index.js +22 -4
- package/dist/index.js.map +1 -1
- package/dist/{lensStops-hQ10t3Lt.d.cts → lensStops-DfNxsaH0.d.cts} +1 -1
- package/dist/{lensStops-DAc3GB8G.d.ts → lensStops-Di41Rg3f.d.ts} +1 -1
- package/dist/{resolveNavigation-o4E4cM_1.d.ts → resolveNavigation-Ckr2nXHY.d.cts} +9 -0
- package/dist/{resolveNavigation-o4E4cM_1.d.cts → resolveNavigation-Ckr2nXHY.d.ts} +9 -0
- package/dist/{selectSkillFrameContext-IPsw4Pbj.d.ts → selectSkillFrameContext-DEk_qpXr.d.ts} +1 -1
- package/dist/{selectSkillFrameContext-DJkvrggG.d.cts → selectSkillFrameContext-DjZDveZw.d.cts} +1 -1
- package/dist/skillgraph.d.cts +4 -4
- package/dist/skillgraph.d.ts +4 -4
- package/dist/why.cjs +1600 -206
- 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 +2 -2
- package/package.json +3 -3
- package/dist/chunk-A4EIPCLY.js.map +0 -1
- package/dist/chunk-SJEKKUTI.js.map +0 -1
- /package/dist/{chunk-WN2RJKEH.js.map → chunk-XFNFYUPC.js.map} +0 -0
package/README.md
CHANGED
|
@@ -891,26 +891,28 @@ if (snapshot) {
|
|
|
891
891
|
}
|
|
892
892
|
```
|
|
893
893
|
|
|
894
|
-
A **stored** recording
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
894
|
+
A **stored** recording meets the port with no cast either, since footprintjs
|
|
895
|
+
9.18. The lens types `Recording.snapshot.commitLog` as `readonly unknown[]` —
|
|
896
|
+
a recording arrives as parsed JSON, and the lens will not claim that what came
|
|
897
|
+
back off disk is a `CommitBundle` — and `TimeTravelSource.commitLog` accepts
|
|
898
|
+
exactly that, narrowing per row where it folds, which is the only place that
|
|
899
|
+
can honestly do it. A row that is not a bundle is reported by index in
|
|
900
|
+
`stateAt().skipped`, never crashed on:
|
|
900
901
|
|
|
901
902
|
```ts
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
903
|
+
if (recording.snapshot) {
|
|
904
|
+
const tt = timeTravel(recording.snapshot, { strategy: lensStopsStrategy(positions) });
|
|
905
|
+
tt.jumpTo(7);
|
|
906
|
+
tt.stateAt().skipped; // undefined, or the rows the fold could not read
|
|
907
|
+
}
|
|
906
908
|
```
|
|
907
909
|
|
|
908
|
-
|
|
909
|
-
`
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
910
|
+
(Under footprintjs 9.17 — still the peer floor — the same call needs
|
|
911
|
+
`recording.snapshot as unknown as TimeTravelSource`, and a bad row throws
|
|
912
|
+
inside the fold; a types-only difference the lens's `foldFactsAt` reports as
|
|
913
|
+
`foldError`.) **Movement never needs a snapshot at all**: `openLensCursor`
|
|
914
|
+
reads the stops and nothing else, which is why the lens's own cursor is
|
|
915
|
+
unaffected either way.
|
|
914
916
|
|
|
915
917
|
### Two axes, and drilling
|
|
916
918
|
|
|
@@ -935,6 +937,130 @@ not answer, since it takes an exact stop.
|
|
|
935
937
|
|
|
936
938
|
---
|
|
937
939
|
|
|
940
|
+
## The Served tab
|
|
941
|
+
|
|
942
|
+
**At every LLM call, exactly what the model was served — provable from the log.**
|
|
943
|
+
The Why Lens's right rail has a second tab, **Served**, mounted for every run.
|
|
944
|
+
Stand on an LLM turn and it shows the request that call went out with: the system
|
|
945
|
+
prompt (piece by piece), the messages as sent, the tools as sent, the dials, the
|
|
946
|
+
cache breakpoints — and beside every field, what the record can PROVE about it.
|
|
947
|
+
|
|
948
|
+
### Why
|
|
949
|
+
|
|
950
|
+
The request a provider receives is assembled from committed pieces and is itself
|
|
951
|
+
never committed — the `call-llm` bundle holds the answer, not the ask. Every
|
|
952
|
+
earlier "what did the model see?" panel in this family read an event
|
|
953
|
+
(`llm_start`) that only some runs record, or rebuilt the prompt from the pieces
|
|
954
|
+
with no way to know whether the rebuild matched what went out.
|
|
955
|
+
|
|
956
|
+
agentfootprint 9.88.0 closes that with two halves and one law:
|
|
957
|
+
|
|
958
|
+
```
|
|
959
|
+
hash(servedAt(k)) === receiptAt(k).hash
|
|
960
|
+
```
|
|
961
|
+
|
|
962
|
+
`servedAt(k)` REBUILDS the request for epoch `k` (one epoch = one LLM call) from
|
|
963
|
+
the committed pieces. `receiptAt(k)` reads the **receipt** — the hashes-only
|
|
964
|
+
record the call itself committed at the stop (system hash and pieces, one hash
|
|
965
|
+
per message, tool names and schema hashes, the sampling dials, the cache
|
|
966
|
+
verdict). When the two agree the record is complete; when they disagree,
|
|
967
|
+
something reached the model that the run never wrote down. The tab renders both
|
|
968
|
+
halves at the lens's one cursor and checks them with the library's own
|
|
969
|
+
`receiptHash` over `messageDigestInput` (a message) and `toolDigestInput` (a
|
|
970
|
+
tool schema).
|
|
971
|
+
|
|
972
|
+
### What each badge means
|
|
973
|
+
|
|
974
|
+
| badge | exactly this |
|
|
975
|
+
|---|---|
|
|
976
|
+
| **Verified** | the receipt's hash for the field EQUALS the hash of what the rebuild produced — run-salted SHA-256, computed with agentfootprint's exported `receiptHash` (over `messageDigestInput` for a message, `toolDigestInput` for a tool schema). System text, every piece, every message and every tool schema can read it. Nothing softer earns it. |
|
|
977
|
+
| **Reconstructed** | rebuilt from the log, but nothing to check it against: this epoch committed no receipt, the receipt carries no hash for this KIND of row, or a gap on the view covers the field (a declared hole, printed beside it). Tool NAMES are always here — they carry no hash. Tool SCHEMAS are here only under an agentfootprint peer older than 9.89.0, which does not export `toolDigestInput`; the lens detects the export at call time rather than copy the serializer. |
|
|
978
|
+
| **Damaged** | the record contradicts itself: the receipt's hash disagrees with the rebuild and no gap excuses it, the rebuild produced a row the receipt never witnessed (no gap says a rebuild may be LONG — the receipt is the witness in both directions), or something under the receipt key was refused as not-a-receipt (`cause: 'receipt-shape-rejected'` — the library refuses a value with no `basis.epoch`, the lens refuses one missing the containers it reads). |
|
|
979
|
+
| **Not on record** | the field is absent on both sides — a receipt-only field (model, provider, params, cache) on an epoch that minted no receipt. |
|
|
980
|
+
|
|
981
|
+
### The laws the tab keeps
|
|
982
|
+
|
|
983
|
+
- **Omit, never deny.** A field a gap covers is never rendered as "empty" or
|
|
984
|
+
"none". The gap IS the empty state: its `why` sentence, verbatim from
|
|
985
|
+
`SERVED_GAPS`, is printed beside the field it covers, and the section is
|
|
986
|
+
marked with the gap's name.
|
|
987
|
+
- **The tab writes no claim sentences of its own.** Every explanatory sentence
|
|
988
|
+
on it is the library's — `SERVED_GAPS[k].why`, `UNGAPPED_FIELDS[k]`,
|
|
989
|
+
`RECEIPT_BOUNDARY` — or is computed data: a status, a count, a hash, a diff.
|
|
990
|
+
The strings the tab owns are labels (`SERVED_LABELS`), and
|
|
991
|
+
`test/served/no-own-claims.test.ts` walks every literal in the tab's source to
|
|
992
|
+
keep it that way; its header states what such a walk cannot catch.
|
|
993
|
+
- **Authority omissions come from the fold.** A receipt never names what a
|
|
994
|
+
caller's ROLE was not allowed to see (the library's first law). The tab's
|
|
995
|
+
audience is an operator, so it MAY show the skill ids hidden from the model —
|
|
996
|
+
but it reads them from the committed state at the stop through footprintjs's
|
|
997
|
+
`stateAt`, labelled **hidden from the model**, never from the receipt.
|
|
998
|
+
- **One cursor.** The tab takes the lens's position as props and holds none of
|
|
999
|
+
its own. On an llm-turn stop it shows that epoch. On any other stop it shows
|
|
1000
|
+
the nearest PRECEDING call with the note *as of call k — this stop is between
|
|
1001
|
+
calls*. Clicking the call's id asks the lens to move the one cursor there.
|
|
1002
|
+
A resumed leg's first call has no previous epoch IN THIS RECORDING; the tab
|
|
1003
|
+
prints that epoch's number with *Not on record*, never "no previous epoch".
|
|
1004
|
+
- **A record never takes the Lens down.** A half-shaped receipt reads
|
|
1005
|
+
*Damaged*; a commit-log row the fold cannot read is data in the FOLD
|
|
1006
|
+
section; a render throw is caught by a boundary around the tab and printed
|
|
1007
|
+
as the Damaged badge plus the message. The rest of the Lens — its one
|
|
1008
|
+
cursor, its *What happened* tab — stays mounted.
|
|
1009
|
+
|
|
1010
|
+
### The sections
|
|
1011
|
+
|
|
1012
|
+
**SERVED** — system prompt with per-piece boundaries (slot · source) and a
|
|
1013
|
+
word-level diff against the previous epoch when the text changed; messages as
|
|
1014
|
+
sent (role, tool-call ids, request-only lines marked with the mechanism that
|
|
1015
|
+
composed them); tools as sent (names, expandable schemas, the forced tool
|
|
1016
|
+
marked, `withheld` shown as the library states it). **BASIS** — epoch, call id,
|
|
1017
|
+
commit index, model, provider, params (only the dials the receipt carries — an
|
|
1018
|
+
absent dial is not rendered as a default), cache (transform, breakpoints
|
|
1019
|
+
applied). **FOLD** — `iteration`, `currentSkillId`, `stepPointer`, engagement,
|
|
1020
|
+
active injections, hidden skill ids, read from the fold at the stop; a row the
|
|
1021
|
+
fold could not read is printed there as data (skipped indices, or the fold's
|
|
1022
|
+
error), beside a Damaged badge.
|
|
1023
|
+
**OMISSIONS** — attention drops from the receipt when present, else the
|
|
1024
|
+
library's `UNGAPPED_FIELDS` sentence for the field. **GAPS** — every gap on the
|
|
1025
|
+
view: its kind, the fields it covers, its sentence verbatim, and its `cause`
|
|
1026
|
+
when the library established one (`receipt-shape-rejected` styled as damage).
|
|
1027
|
+
**SINCE PREVIOUS** — messages entered/left, tools added/removed, schemas whose
|
|
1028
|
+
receipt hashes changed, and the system-text word diff.
|
|
1029
|
+
|
|
1030
|
+
### Headless
|
|
1031
|
+
|
|
1032
|
+
```ts
|
|
1033
|
+
import {
|
|
1034
|
+
servedRowAt, servedRowForEpoch, verify, sincePrevious, foldFactsAt,
|
|
1035
|
+
} from 'agentfootprint-lens/core';
|
|
1036
|
+
|
|
1037
|
+
const snapshot = runner.getLastSnapshot();
|
|
1038
|
+
const row = servedRowAt(snapshot, { runtimeStageId: 'call-llm#18', commitIdx: 15 });
|
|
1039
|
+
if (row) {
|
|
1040
|
+
row.epoch; // 1
|
|
1041
|
+
row.betweenCalls; // false — on the call itself
|
|
1042
|
+
const checks = verify(row.view, row.receipt, row.receipt?.basis.runId ?? '');
|
|
1043
|
+
checks.system.status; // 'verified'
|
|
1044
|
+
checks.messages.map((c) => c.status); // ['verified']
|
|
1045
|
+
row.view.gaps.map((g) => g.why); // the library's sentences
|
|
1046
|
+
const prev = row.previousEpoch !== undefined
|
|
1047
|
+
? servedRowForEpoch(snapshot, row.previousEpoch) : undefined;
|
|
1048
|
+
if (prev) sincePrevious(row, prev).tools.added; // ['charge']
|
|
1049
|
+
foldFactsAt(snapshot, { runtimeStageId: 'call-llm#18', commitIdx: 15 }).hiddenSkillIds;
|
|
1050
|
+
}
|
|
1051
|
+
```
|
|
1052
|
+
|
|
1053
|
+
Every function is pure and every return is frozen. `<ServedTab runner
|
|
1054
|
+
cursorRuntimeStageId commitIdx onJumpTo>` is exported for shells that hold the
|
|
1055
|
+
one cursor themselves.
|
|
1056
|
+
|
|
1057
|
+
**A recording made before agentfootprint 9.88** still renders: the rebuild works
|
|
1058
|
+
on every epoch, no receipt was minted, and the tab says so with the library's
|
|
1059
|
+
`no-receipt-on-chart` gap and `cause: 'no-receipt-committed'` — every row
|
|
1060
|
+
**Reconstructed**, never a fabricated **Verified**.
|
|
1061
|
+
|
|
1062
|
+
---
|
|
1063
|
+
|
|
938
1064
|
## Rendering your own detail pane
|
|
939
1065
|
|
|
940
1066
|
`slots.detail` replaces the CONTENT of the shipped right column. The column
|
|
@@ -1154,6 +1280,16 @@ exact `formatSlice` text the LLM tool returns. Honest absence stays honest:
|
|
|
1154
1280
|
"never written — initial state / args / a closure", and reads-off runs say
|
|
1155
1281
|
"unknowable, not absent".
|
|
1156
1282
|
|
|
1283
|
+
### `<ServedTab>` — what the model was served at the cursor's call
|
|
1284
|
+
|
|
1285
|
+
`<ServedTab runner cursorRuntimeStageId commitIdx onJumpTo?>`. The Why Lens
|
|
1286
|
+
mounts it as the right rail's second tab; exported for consumer-built shells.
|
|
1287
|
+
Renders `servedAt(k)` and `receiptAt(k)` (agentfootprint 9.88.0) at the one
|
|
1288
|
+
cursor with a **Verified / Reconstructed / Damaged / Not on record** badge per
|
|
1289
|
+
field, the library's gap sentences verbatim, the fold's hidden skill ids, and a
|
|
1290
|
+
since-previous diff. Headless: `servedRowAt` · `verify` · `sincePrevious` ·
|
|
1291
|
+
`foldFactsAt` in `/core`. See "The Served tab" above.
|
|
1292
|
+
|
|
1157
1293
|
### `<BugReportButton>` — report a bug with the run attached, consent first
|
|
1158
1294
|
|
|
1159
1295
|
A small button for a debug UI. The dialog it opens shows every selectable unit
|
|
@@ -3,8 +3,8 @@ import { ToolChoiceCall, ToolChoiceSummary } from 'agentfootprint/observe';
|
|
|
3
3
|
import * as agentfootprint from 'agentfootprint';
|
|
4
4
|
import { CommentaryTemplates } from 'agentfootprint';
|
|
5
5
|
import React__default, { Ref } from 'react';
|
|
6
|
-
import { d as NavigationResult, C as CursorPosition, L as LensRecorder } from './resolveNavigation-
|
|
7
|
-
import { C as ChartGroupHighlight, a as LensCursorPort, H as Humanizer } from './lensStops-
|
|
6
|
+
import { d as NavigationResult, C as CursorPosition, L as LensRecorder } from './resolveNavigation-Ckr2nXHY.js';
|
|
7
|
+
import { C as ChartGroupHighlight, a as LensCursorPort, H as Humanizer } from './lensStops-Di41Rg3f.js';
|
|
8
8
|
import { NodeTypes } from '@xyflow/react';
|
|
9
9
|
import { TraceGraph, TraceFlowLayout, RuntimeOverlay } from 'footprint-explainable-ui/flowchart';
|
|
10
10
|
|
|
@@ -3,8 +3,8 @@ import { ToolChoiceCall, ToolChoiceSummary } from 'agentfootprint/observe';
|
|
|
3
3
|
import * as agentfootprint from 'agentfootprint';
|
|
4
4
|
import { CommentaryTemplates } from 'agentfootprint';
|
|
5
5
|
import React__default, { Ref } from 'react';
|
|
6
|
-
import { d as NavigationResult, C as CursorPosition, L as LensRecorder } from './resolveNavigation-
|
|
7
|
-
import { C as ChartGroupHighlight, a as LensCursorPort, H as Humanizer } from './lensStops-
|
|
6
|
+
import { d as NavigationResult, C as CursorPosition, L as LensRecorder } from './resolveNavigation-Ckr2nXHY.cjs';
|
|
7
|
+
import { C as ChartGroupHighlight, a as LensCursorPort, H as Humanizer } from './lensStops-DfNxsaH0.cjs';
|
|
8
8
|
import { NodeTypes } from '@xyflow/react';
|
|
9
9
|
import { TraceGraph, TraceFlowLayout, RuntimeOverlay } from 'footprint-explainable-ui/flowchart';
|
|
10
10
|
|