agentfootprint-lens 0.13.0 → 0.13.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/dist/index.cjs +158 -68
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +160 -69
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1217,12 +1217,31 @@ var RunTreeFlow = ({
|
|
|
1217
1217
|
}
|
|
1218
1218
|
} : void 0;
|
|
1219
1219
|
const containerRef = (0, import_react6.useRef)(null);
|
|
1220
|
+
const graphFingerprint = (0, import_react6.useMemo)(() => {
|
|
1221
|
+
let h = 0;
|
|
1222
|
+
for (const n of nodes) {
|
|
1223
|
+
const s = `${n.id}|${n.position.x}|${n.position.y}`;
|
|
1224
|
+
for (let i = 0; i < s.length; i++) h = (h << 5) - h + s.charCodeAt(i) | 0;
|
|
1225
|
+
}
|
|
1226
|
+
return `${nodes.length}:${edges.length}:${h}`;
|
|
1227
|
+
}, [nodes, edges]);
|
|
1220
1228
|
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
1221
1229
|
"div",
|
|
1222
1230
|
{
|
|
1223
1231
|
ref: containerRef,
|
|
1224
1232
|
"data-fp-lens": "run-tree-flow",
|
|
1225
|
-
style: {
|
|
1233
|
+
style: {
|
|
1234
|
+
width: "100%",
|
|
1235
|
+
height: "100%",
|
|
1236
|
+
// minHeight keeps the flowchart usable when the parent is
|
|
1237
|
+
// shorter than the natural layout. minWidth was missing and
|
|
1238
|
+
// let parents squeeze us to ~280px, which made React Flow
|
|
1239
|
+
// auto-zoom to ~30% and render nodes invisibly small.
|
|
1240
|
+
// 480px keeps nodes legible in side-panel layouts.
|
|
1241
|
+
minHeight: 320,
|
|
1242
|
+
minWidth: 480,
|
|
1243
|
+
background: "var(--lens-bg, transparent)"
|
|
1244
|
+
},
|
|
1226
1245
|
children: [
|
|
1227
1246
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("style", { children: LENS_DEFAULT_CSS }),
|
|
1228
1247
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
@@ -1246,9 +1265,9 @@ var RunTreeFlow = ({
|
|
|
1246
1265
|
preventScrolling: false,
|
|
1247
1266
|
proOptions: { hideAttribution: true },
|
|
1248
1267
|
children: [
|
|
1249
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(FitViewOnResize, { depKey:
|
|
1268
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(FitViewOnResize, { depKey: graphFingerprint, containerRef }),
|
|
1250
1269
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_react7.Background, { gap: 20, size: 1, color: "var(--lens-background-dots, #e5e7eb)" }),
|
|
1251
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_react7.Controls, { showInteractive: false })
|
|
1270
|
+
nodes.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_react7.Controls, { showInteractive: false })
|
|
1252
1271
|
]
|
|
1253
1272
|
}
|
|
1254
1273
|
)
|
|
@@ -1261,11 +1280,13 @@ function FitViewOnResize({
|
|
|
1261
1280
|
containerRef
|
|
1262
1281
|
}) {
|
|
1263
1282
|
const { fitView } = (0, import_react7.useReactFlow)();
|
|
1283
|
+
const nodesInitialized = (0, import_react7.useNodesInitialized)();
|
|
1264
1284
|
(0, import_react6.useEffect)(() => {
|
|
1285
|
+
if (!nodesInitialized) return;
|
|
1265
1286
|
const handler = () => {
|
|
1266
1287
|
requestAnimationFrame(() => fitView({ padding: 0.3, duration: 200 }));
|
|
1267
1288
|
};
|
|
1268
|
-
|
|
1289
|
+
handler();
|
|
1269
1290
|
const el = containerRef.current;
|
|
1270
1291
|
let observer;
|
|
1271
1292
|
if (el && typeof ResizeObserver !== "undefined") {
|
|
@@ -1274,11 +1295,10 @@ function FitViewOnResize({
|
|
|
1274
1295
|
}
|
|
1275
1296
|
window.addEventListener("resize", handler);
|
|
1276
1297
|
return () => {
|
|
1277
|
-
clearTimeout(timer);
|
|
1278
1298
|
observer?.disconnect();
|
|
1279
1299
|
window.removeEventListener("resize", handler);
|
|
1280
1300
|
};
|
|
1281
|
-
}, [fitView, depKey, containerRef]);
|
|
1301
|
+
}, [fitView, depKey, containerRef, nodesInitialized]);
|
|
1282
1302
|
return null;
|
|
1283
1303
|
}
|
|
1284
1304
|
function buildFlow(view, graph, selectedId) {
|
|
@@ -1309,7 +1329,12 @@ function buildFlow(view, graph, selectedId) {
|
|
|
1309
1329
|
selected: agent.groupId === selectedId,
|
|
1310
1330
|
...agent.primitiveKind ? { primitiveKind: agent.primitiveKind } : {}
|
|
1311
1331
|
},
|
|
1312
|
-
|
|
1332
|
+
// xyflow v12: parent sizing comes from top-level `width`/`height`.
|
|
1333
|
+
// Setting `style.width/height` AS WELL appears to confuse RF —
|
|
1334
|
+
// children get clipped to a phantom zero-size box. Single source
|
|
1335
|
+
// of truth: top-level only.
|
|
1336
|
+
width: AGENT_GROUP_WIDTH,
|
|
1337
|
+
height: AGENT_GROUP_HEIGHT,
|
|
1313
1338
|
selectable: true,
|
|
1314
1339
|
draggable: false
|
|
1315
1340
|
});
|
|
@@ -1317,7 +1342,6 @@ function buildFlow(view, graph, selectedId) {
|
|
|
1317
1342
|
nodes.push({
|
|
1318
1343
|
id: `${agent.groupId}-ctx`,
|
|
1319
1344
|
parentId: agent.groupId,
|
|
1320
|
-
extent: "parent",
|
|
1321
1345
|
position: CONTEXT_BIN_IN_GROUP,
|
|
1322
1346
|
type: "contextBin",
|
|
1323
1347
|
data: { chips: chipsForAgent },
|
|
@@ -1328,7 +1352,6 @@ function buildFlow(view, graph, selectedId) {
|
|
|
1328
1352
|
nodes.push({
|
|
1329
1353
|
id: agent.llmId,
|
|
1330
1354
|
parentId: agent.groupId,
|
|
1331
|
-
extent: "parent",
|
|
1332
1355
|
position: LLM_IN_GROUP,
|
|
1333
1356
|
type: "llm",
|
|
1334
1357
|
data: { updatedSlot },
|
|
@@ -1871,32 +1894,66 @@ var ReActStepBody = ({ node }) => {
|
|
|
1871
1894
|
if (node.llmModel) rows.push(["model", node.llmModel]);
|
|
1872
1895
|
if (node.slotUpdated) rows.push(["what landed in", node.slotUpdated]);
|
|
1873
1896
|
if (duration !== void 0 && duration > 0) rows.push(["duration", `${Math.round(duration)}ms`]);
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
((
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
/* @__PURE__ */ (0, import_jsx_runtime9.
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
inj.contentSummary
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1897
|
+
const ioSections = ioSectionsFor(node);
|
|
1898
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
|
|
1899
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: sectionStyle, children: [
|
|
1900
|
+
rows.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: { display: "grid", gap: 4, fontSize: 12, padding: 8 }, children: rows.map(([label, value]) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Field, { label, children: value }, label)) }),
|
|
1901
|
+
(() => {
|
|
1902
|
+
const engineered = (node.injections ?? []).filter(
|
|
1903
|
+
(inj) => !BASELINE_SOURCES2.has(inj.source)
|
|
1904
|
+
);
|
|
1905
|
+
if (engineered.length === 0) return null;
|
|
1906
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: { padding: "0 8px 8px" }, children: [
|
|
1907
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: sectionLabelStyle, children: "Context engineering" }),
|
|
1908
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("ul", { style: { margin: "4px 0 0", paddingLeft: 14, fontSize: 11, color: T.textSecondary }, children: engineered.map((inj, i) => /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("li", { style: { padding: "2px 0" }, children: [
|
|
1909
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("code", { style: { fontSize: 11 }, children: [
|
|
1910
|
+
"[",
|
|
1911
|
+
inj.slot,
|
|
1912
|
+
"] ",
|
|
1913
|
+
inj.source,
|
|
1914
|
+
inj.sourceId ? `:${inj.sourceId}` : ""
|
|
1915
|
+
] }),
|
|
1916
|
+
inj.contentSummary && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("span", { style: { opacity: 0.7, marginLeft: 6 }, children: [
|
|
1917
|
+
"\xB7 ",
|
|
1918
|
+
inj.contentSummary
|
|
1919
|
+
] })
|
|
1920
|
+
] }, i)) })
|
|
1921
|
+
] });
|
|
1922
|
+
})()
|
|
1923
|
+
] }),
|
|
1924
|
+
ioSections.map((s) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(PayloadSection, { label: s.label, payload: s.payload, emptyHint: "(none)" }, s.label))
|
|
1898
1925
|
] });
|
|
1899
1926
|
};
|
|
1927
|
+
function ioSectionsFor(node) {
|
|
1928
|
+
const out = [];
|
|
1929
|
+
switch (node.kind) {
|
|
1930
|
+
case "llm->tool": {
|
|
1931
|
+
if (node.assistantText) {
|
|
1932
|
+
out.push({ label: "LLM's reasoning", payload: node.assistantText });
|
|
1933
|
+
}
|
|
1934
|
+
if (node.toolArgs !== void 0) {
|
|
1935
|
+
out.push({ label: "Tool input (args)", payload: node.toolArgs });
|
|
1936
|
+
}
|
|
1937
|
+
break;
|
|
1938
|
+
}
|
|
1939
|
+
case "tool->llm": {
|
|
1940
|
+
if (node.toolResult !== void 0) {
|
|
1941
|
+
out.push({ label: "Tool result sent to LLM", payload: node.toolResult });
|
|
1942
|
+
}
|
|
1943
|
+
break;
|
|
1944
|
+
}
|
|
1945
|
+
case "llm->user": {
|
|
1946
|
+
if (node.assistantText) {
|
|
1947
|
+
out.push({ label: "Final answer", payload: node.assistantText });
|
|
1948
|
+
}
|
|
1949
|
+
break;
|
|
1950
|
+
}
|
|
1951
|
+
case "user->llm":
|
|
1952
|
+
default:
|
|
1953
|
+
break;
|
|
1954
|
+
}
|
|
1955
|
+
return out;
|
|
1956
|
+
}
|
|
1900
1957
|
var BASELINE_SOURCES2 = /* @__PURE__ */ new Set([
|
|
1901
1958
|
"user",
|
|
1902
1959
|
// current-turn user message
|
|
@@ -1914,15 +1971,20 @@ var Field = ({ label, children }) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx
|
|
|
1914
1971
|
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { style: { color: T.textPrimary }, children })
|
|
1915
1972
|
] });
|
|
1916
1973
|
function prettyPrint(value) {
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1974
|
+
let str;
|
|
1975
|
+
if (typeof value === "string") {
|
|
1976
|
+
str = value;
|
|
1977
|
+
} else {
|
|
1978
|
+
try {
|
|
1979
|
+
str = JSON.stringify(value, null, 2);
|
|
1980
|
+
} catch {
|
|
1981
|
+
return "(unable to serialize)";
|
|
1921
1982
|
}
|
|
1922
|
-
return str;
|
|
1923
|
-
} catch {
|
|
1924
|
-
return "(unable to serialize)";
|
|
1925
1983
|
}
|
|
1984
|
+
if (str.length > 4e3) {
|
|
1985
|
+
return str.slice(0, 4e3) + "\n\n... (truncated; " + (str.length - 4e3) + " chars)";
|
|
1986
|
+
}
|
|
1987
|
+
return str;
|
|
1926
1988
|
}
|
|
1927
1989
|
var panelStyle = {
|
|
1928
1990
|
display: "flex",
|
|
@@ -2202,6 +2264,42 @@ var EngineerView = ({ stepGraph, summary, log, humanizer, total, focusStep, onFo
|
|
|
2202
2264
|
const focusedNode = stepGraph?.nodes[focusStep];
|
|
2203
2265
|
const focusedRuntimeStageId = focusedNode?.runtimeStageId;
|
|
2204
2266
|
const currentStepLabel = focusedNode?.label;
|
|
2267
|
+
const stepToEventSeq = (0, import_react11.useMemo)(() => {
|
|
2268
|
+
if (!stepGraph || log.length === 0) return [];
|
|
2269
|
+
const firstSeq = log[0].seq;
|
|
2270
|
+
const seqs = [];
|
|
2271
|
+
let lastResolvedSeq = firstSeq;
|
|
2272
|
+
const anchorSide = (kind) => kind === "llm->user" ? "last" : "first";
|
|
2273
|
+
for (const node of stepGraph.nodes) {
|
|
2274
|
+
const id = node.runtimeStageId;
|
|
2275
|
+
let resolved = -1;
|
|
2276
|
+
if (id !== void 0) {
|
|
2277
|
+
const side = anchorSide(node.kind);
|
|
2278
|
+
if (side === "first") {
|
|
2279
|
+
for (const e of log) {
|
|
2280
|
+
const stageId = e.event.meta?.runtimeStageId;
|
|
2281
|
+
if (stageId === id) {
|
|
2282
|
+
resolved = e.seq;
|
|
2283
|
+
break;
|
|
2284
|
+
}
|
|
2285
|
+
}
|
|
2286
|
+
} else {
|
|
2287
|
+
for (let i = log.length - 1; i >= 0; i--) {
|
|
2288
|
+
const stageId = log[i].event.meta?.runtimeStageId;
|
|
2289
|
+
if (stageId === id) {
|
|
2290
|
+
resolved = log[i].seq;
|
|
2291
|
+
break;
|
|
2292
|
+
}
|
|
2293
|
+
}
|
|
2294
|
+
}
|
|
2295
|
+
}
|
|
2296
|
+
if (resolved === -1) resolved = lastResolvedSeq;
|
|
2297
|
+
seqs.push(resolved);
|
|
2298
|
+
lastResolvedSeq = resolved;
|
|
2299
|
+
}
|
|
2300
|
+
return seqs;
|
|
2301
|
+
}, [stepGraph, log]);
|
|
2302
|
+
const focusedSeq = stepToEventSeq[focusStep] ?? -1;
|
|
2205
2303
|
const handleNodeSelect = (nodeId) => {
|
|
2206
2304
|
if (!stepGraph) return;
|
|
2207
2305
|
const idx = stepGraph.nodes.findIndex((n) => n.id === nodeId);
|
|
@@ -2249,7 +2347,7 @@ var EngineerView = ({ stepGraph, summary, log, humanizer, total, focusStep, onFo
|
|
|
2249
2347
|
overflow: "hidden"
|
|
2250
2348
|
},
|
|
2251
2349
|
children: [
|
|
2252
|
-
leftExpanded ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_jsx_runtime10.Fragment, { children: [
|
|
2350
|
+
agentNodes.length >= 2 && (leftExpanded ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_jsx_runtime10.Fragment, { children: [
|
|
2253
2351
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
2254
2352
|
"div",
|
|
2255
2353
|
{
|
|
@@ -2291,7 +2389,7 @@ var EngineerView = ({ stepGraph, summary, log, humanizer, total, focusStep, onFo
|
|
|
2291
2389
|
side: "left",
|
|
2292
2390
|
onClick: () => setLeftExpanded(true)
|
|
2293
2391
|
}
|
|
2294
|
-
),
|
|
2392
|
+
)),
|
|
2295
2393
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
2296
2394
|
"div",
|
|
2297
2395
|
{
|
|
@@ -2351,20 +2449,21 @@ var EngineerView = ({ stepGraph, summary, log, humanizer, total, focusStep, onFo
|
|
|
2351
2449
|
"div",
|
|
2352
2450
|
{
|
|
2353
2451
|
style: {
|
|
2354
|
-
width
|
|
2355
|
-
|
|
2452
|
+
// Flex-shrink 1 with min/max so the panel yields width to
|
|
2453
|
+
// the central flowchart when the container is narrow. The
|
|
2454
|
+
// hard 320px-fixed width was squeezing the flowchart to
|
|
2455
|
+
// ~280px in compact layouts (e.g., embedded in a 30%
|
|
2456
|
+
// sidebar), causing React Flow to auto-zoom to ~30% and
|
|
2457
|
+
// render nodes invisibly small.
|
|
2458
|
+
flex: "0 1 320px",
|
|
2459
|
+
minWidth: 220,
|
|
2460
|
+
maxWidth: 360,
|
|
2356
2461
|
display: "flex",
|
|
2357
2462
|
flexDirection: "column",
|
|
2358
2463
|
overflow: "hidden",
|
|
2359
2464
|
borderLeft: `1px solid ${T.border}`
|
|
2360
2465
|
},
|
|
2361
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2362
|
-
NodeDetailPanel,
|
|
2363
|
-
{
|
|
2364
|
-
...focusedNode ? { node: focusedNode } : {},
|
|
2365
|
-
onClose: () => onFocusChange(0)
|
|
2366
|
-
}
|
|
2367
|
-
)
|
|
2466
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(NodeDetailPanel, { ...focusedNode ? { node: focusedNode } : {} })
|
|
2368
2467
|
}
|
|
2369
2468
|
)
|
|
2370
2469
|
]
|
|
@@ -2397,7 +2496,8 @@ var EngineerView = ({ stepGraph, summary, log, humanizer, total, focusStep, onFo
|
|
|
2397
2496
|
log,
|
|
2398
2497
|
humanizer,
|
|
2399
2498
|
liveStreamLine,
|
|
2400
|
-
|
|
2499
|
+
isLastStep: stepGraph != null && focusStep === stepGraph.nodes.length - 1,
|
|
2500
|
+
focusedSeq
|
|
2401
2501
|
}
|
|
2402
2502
|
)
|
|
2403
2503
|
}
|
|
@@ -2406,16 +2506,16 @@ var EngineerView = ({ stepGraph, summary, log, humanizer, total, focusStep, onFo
|
|
|
2406
2506
|
}
|
|
2407
2507
|
);
|
|
2408
2508
|
};
|
|
2409
|
-
var Commentary = ({ log, humanizer,
|
|
2509
|
+
var Commentary = ({ log, humanizer, focusedSeq, liveStreamLine, isLastStep }) => {
|
|
2410
2510
|
const containerRef = (0, import_react11.useRef)(null);
|
|
2411
2511
|
const firstFocusRef = (0, import_react11.useRef)(null);
|
|
2412
2512
|
(0, import_react11.useEffect)(() => {
|
|
2413
|
-
if (
|
|
2513
|
+
if (focusedSeq === void 0 || focusedSeq < 0 || !firstFocusRef.current) return;
|
|
2414
2514
|
firstFocusRef.current.scrollIntoView({
|
|
2415
2515
|
block: "center",
|
|
2416
2516
|
behavior: "smooth"
|
|
2417
2517
|
});
|
|
2418
|
-
}, [
|
|
2518
|
+
}, [focusedSeq]);
|
|
2419
2519
|
let firstFocusAssigned = false;
|
|
2420
2520
|
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2421
2521
|
"div",
|
|
@@ -2434,24 +2534,14 @@ var Commentary = ({ log, humanizer, focusRuntimeStageId, liveStreamLine }) => {
|
|
|
2434
2534
|
if (log.length === 0) {
|
|
2435
2535
|
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { style: { color: T.textSecondary, fontStyle: "italic" }, children: "No moments yet \u2014 run a sample to see commentary." });
|
|
2436
2536
|
}
|
|
2437
|
-
const
|
|
2438
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
2439
|
-
e.event.meta?.runtimeStageId
|
|
2440
|
-
);
|
|
2441
|
-
let lastFocusIdx = -1;
|
|
2442
|
-
if (focusRuntimeStageId !== void 0) {
|
|
2443
|
-
for (let i = 0; i < log.length; i++) {
|
|
2444
|
-
if (idOf(log[i]) === focusRuntimeStageId) lastFocusIdx = i;
|
|
2445
|
-
}
|
|
2446
|
-
}
|
|
2447
|
-
const cutoff = lastFocusIdx === -1 ? log.length - 1 : lastFocusIdx;
|
|
2537
|
+
const cutoff = isLastStep || focusedSeq === void 0 || focusedSeq < 0 ? log.length - 1 : Math.max(0, log.findIndex((e) => e.seq === focusedSeq));
|
|
2448
2538
|
const visible = log.slice(0, cutoff + 1);
|
|
2449
2539
|
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_jsx_runtime10.Fragment, { children: [
|
|
2450
2540
|
visible.map((entry, i) => {
|
|
2451
2541
|
const line = humanizer(entry.event);
|
|
2452
2542
|
if (line === null) return null;
|
|
2453
|
-
const focused =
|
|
2454
|
-
const isLastFocused = focused && i ===
|
|
2543
|
+
const focused = focusedSeq !== void 0 && entry.seq === focusedSeq;
|
|
2544
|
+
const isLastFocused = focused && i === cutoff;
|
|
2455
2545
|
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
2456
2546
|
"div",
|
|
2457
2547
|
{
|