agentfootprint-lens 0.2.0 → 0.3.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/dist/index.cjs +312 -79
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +10 -6
- package/dist/index.d.ts +10 -6
- package/dist/index.js +315 -82
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -193,8 +193,10 @@ function assembleTurns(messages, llmCalls, toolExecs, instructionEvals, toolReso
|
|
|
193
193
|
...tc,
|
|
194
194
|
turnIndex: currentTurn.index
|
|
195
195
|
}));
|
|
196
|
+
const msgsBefore = messages.indexOf(msg);
|
|
196
197
|
const iteration = {
|
|
197
198
|
index: iterIndex,
|
|
199
|
+
messagesSentCount: msgsBefore >= 0 ? msgsBefore : 0,
|
|
198
200
|
...call?.model && { model: call.model },
|
|
199
201
|
...call?.inputTokens !== void 0 && { inputTokens: call.inputTokens },
|
|
200
202
|
...call?.outputTokens !== void 0 && { outputTokens: call.outputTokens },
|
|
@@ -275,12 +277,26 @@ var import_jsx_runtime = require("react/jsx-runtime");
|
|
|
275
277
|
function MessagesPanel({
|
|
276
278
|
timeline,
|
|
277
279
|
onToolCallClick,
|
|
278
|
-
systemPrompt
|
|
280
|
+
systemPrompt,
|
|
281
|
+
selectedIterKey
|
|
279
282
|
}) {
|
|
280
283
|
const t = useLensTheme();
|
|
284
|
+
const scrollRef = (0, import_react.useRef)(null);
|
|
285
|
+
(0, import_react.useEffect)(() => {
|
|
286
|
+
if (!selectedIterKey || !scrollRef.current) return;
|
|
287
|
+
const target = scrollRef.current.querySelector(
|
|
288
|
+
`[data-iter-key="${CSS.escape(selectedIterKey)}"]`
|
|
289
|
+
);
|
|
290
|
+
if (!target) return;
|
|
291
|
+
target.scrollIntoView({ block: "start", behavior: "smooth" });
|
|
292
|
+
target.setAttribute("data-iter-selected", "true");
|
|
293
|
+
const h = window.setTimeout(() => target.removeAttribute("data-iter-selected"), 1200);
|
|
294
|
+
return () => window.clearTimeout(h);
|
|
295
|
+
}, [selectedIterKey]);
|
|
281
296
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
282
297
|
"div",
|
|
283
298
|
{
|
|
299
|
+
ref: scrollRef,
|
|
284
300
|
"data-fp-lens": "messages-panel",
|
|
285
301
|
style: {
|
|
286
302
|
display: "flex",
|
|
@@ -297,7 +313,15 @@ function MessagesPanel({
|
|
|
297
313
|
},
|
|
298
314
|
children: [
|
|
299
315
|
systemPrompt && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SystemBubble, { text: systemPrompt }),
|
|
300
|
-
timeline.turns.map((turn) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
316
|
+
timeline.turns.map((turn) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
317
|
+
TurnBlock,
|
|
318
|
+
{
|
|
319
|
+
turn,
|
|
320
|
+
allMessages: timeline.messages,
|
|
321
|
+
onToolCallClick
|
|
322
|
+
},
|
|
323
|
+
turn.index
|
|
324
|
+
))
|
|
301
325
|
]
|
|
302
326
|
}
|
|
303
327
|
);
|
|
@@ -334,7 +358,7 @@ function SystemBubble({ text }) {
|
|
|
334
358
|
font: "inherit"
|
|
335
359
|
},
|
|
336
360
|
children: [
|
|
337
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: "
|
|
361
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: "How Neo is configured" }),
|
|
338
362
|
" ",
|
|
339
363
|
open ? "\u25BE" : "\u25B8",
|
|
340
364
|
" ",
|
|
@@ -361,23 +385,34 @@ function SystemBubble({ text }) {
|
|
|
361
385
|
}
|
|
362
386
|
function TurnBlock({
|
|
363
387
|
turn,
|
|
388
|
+
allMessages,
|
|
364
389
|
onToolCallClick
|
|
365
390
|
}) {
|
|
366
391
|
const t = useLensTheme();
|
|
367
392
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 12 }, children: [
|
|
368
393
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(TurnHeader, { turn }),
|
|
369
394
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(UserBubble, { text: turn.userPrompt }),
|
|
370
|
-
turn.iterations.map((iter) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
395
|
+
turn.iterations.map((iter, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
396
|
+
IterationBlock,
|
|
397
|
+
{
|
|
398
|
+
iter,
|
|
399
|
+
iterPositionInTurn: i + 1,
|
|
400
|
+
turnIndex: turn.index,
|
|
401
|
+
allMessages,
|
|
402
|
+
onToolCallClick
|
|
403
|
+
},
|
|
404
|
+
iter.index
|
|
405
|
+
)),
|
|
371
406
|
turn.finalContent && turn.iterations.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { fontSize: 11, color: t.textSubtle, textAlign: "center" }, children: [
|
|
372
|
-
"
|
|
373
|
-
turn.index + 1,
|
|
374
|
-
" final \xB7 ",
|
|
407
|
+
"Answer compiled \xB7 ",
|
|
375
408
|
turn.iterations.length,
|
|
376
|
-
"
|
|
409
|
+
" step",
|
|
410
|
+
turn.iterations.length === 1 ? "" : "s",
|
|
411
|
+
" \xB7 ",
|
|
377
412
|
turn.totalInputTokens,
|
|
378
413
|
"\u2192",
|
|
379
414
|
turn.totalOutputTokens,
|
|
380
|
-
"
|
|
415
|
+
" tokens \xB7 ",
|
|
381
416
|
(turn.totalDurationMs / 1e3).toFixed(1),
|
|
382
417
|
"s"
|
|
383
418
|
] })
|
|
@@ -401,7 +436,7 @@ function TurnHeader({ turn }) {
|
|
|
401
436
|
children: [
|
|
402
437
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { flex: 1, height: 1, background: t.border } }),
|
|
403
438
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { children: [
|
|
404
|
-
"
|
|
439
|
+
"Your question ",
|
|
405
440
|
turn.index + 1
|
|
406
441
|
] }),
|
|
407
442
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { flex: 1, height: 1, background: t.border } })
|
|
@@ -427,54 +462,221 @@ function UserBubble({ text }) {
|
|
|
427
462
|
}
|
|
428
463
|
) });
|
|
429
464
|
}
|
|
465
|
+
function iterationHeadline(iter) {
|
|
466
|
+
if (iter.toolCalls.length === 0) {
|
|
467
|
+
return "Neo is ready to answer";
|
|
468
|
+
}
|
|
469
|
+
if (iter.toolCalls.length === 1) {
|
|
470
|
+
const tc = iter.toolCalls[0];
|
|
471
|
+
if (tc.name === "list_skills") return "Neo is looking up available skills";
|
|
472
|
+
if (tc.name === "read_skill") {
|
|
473
|
+
const id = tc.arguments?.id ?? "?";
|
|
474
|
+
return `Neo activated the \u201C${id}\u201D skill`;
|
|
475
|
+
}
|
|
476
|
+
return `Neo called ${tc.name} to get data`;
|
|
477
|
+
}
|
|
478
|
+
const names = iter.toolCalls.map((tc) => tc.name);
|
|
479
|
+
if (names.length <= 3) return `Neo called ${names.join(", ")} in parallel`;
|
|
480
|
+
return `Neo gathered data from ${names.length} sources in parallel`;
|
|
481
|
+
}
|
|
430
482
|
function IterationBlock({
|
|
431
483
|
iter,
|
|
484
|
+
iterPositionInTurn,
|
|
485
|
+
turnIndex,
|
|
486
|
+
allMessages,
|
|
432
487
|
onToolCallClick
|
|
433
488
|
}) {
|
|
434
489
|
const t = useLensTheme();
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
490
|
+
const [showContext, setShowContext] = (0, import_react.useState)(false);
|
|
491
|
+
const key = `${turnIndex}.${iter.index}`;
|
|
492
|
+
const headline = iterationHeadline(iter);
|
|
493
|
+
const contextMessages = allMessages.slice(0, iter.messagesSentCount);
|
|
494
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
495
|
+
"div",
|
|
496
|
+
{
|
|
497
|
+
"data-iter-key": key,
|
|
498
|
+
"data-turn-index": turnIndex,
|
|
499
|
+
"data-iter-index": iter.index,
|
|
500
|
+
style: {
|
|
501
|
+
display: "flex",
|
|
502
|
+
flexDirection: "column",
|
|
503
|
+
gap: 6,
|
|
504
|
+
padding: 8,
|
|
505
|
+
margin: -8,
|
|
506
|
+
borderRadius: t.radius,
|
|
507
|
+
outline: "2px solid transparent",
|
|
508
|
+
outlineOffset: 2,
|
|
509
|
+
transition: "outline-color 180ms ease, background 180ms ease"
|
|
510
|
+
},
|
|
511
|
+
children: [
|
|
512
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
513
|
+
"div",
|
|
514
|
+
{
|
|
515
|
+
style: {
|
|
516
|
+
display: "flex",
|
|
517
|
+
alignItems: "baseline",
|
|
518
|
+
gap: 8,
|
|
519
|
+
fontSize: 13,
|
|
520
|
+
color: t.textMuted
|
|
521
|
+
},
|
|
522
|
+
children: [
|
|
523
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: { color: t.accent, fontWeight: 600 }, children: [
|
|
524
|
+
"Step ",
|
|
525
|
+
iterPositionInTurn,
|
|
526
|
+
":"
|
|
527
|
+
] }),
|
|
528
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { color: t.text }, children: headline }),
|
|
529
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { flex: 1 } }),
|
|
530
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
531
|
+
"span",
|
|
532
|
+
{
|
|
533
|
+
style: {
|
|
534
|
+
fontSize: 10,
|
|
535
|
+
color: t.textSubtle,
|
|
536
|
+
fontFamily: t.fontMono
|
|
537
|
+
},
|
|
538
|
+
children: [
|
|
539
|
+
iter.inputTokens !== void 0 && `${iter.inputTokens}\u2192${iter.outputTokens ?? "?"} tok \xB7 `,
|
|
540
|
+
iter.durationMs !== void 0 && `${(iter.durationMs / 1e3).toFixed(2)}s`
|
|
541
|
+
]
|
|
542
|
+
}
|
|
543
|
+
),
|
|
544
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
545
|
+
"button",
|
|
546
|
+
{
|
|
547
|
+
onClick: () => setShowContext((v) => !v),
|
|
548
|
+
title: "See exactly what Neo saw when deciding this step",
|
|
549
|
+
style: {
|
|
550
|
+
fontSize: 11,
|
|
551
|
+
color: t.textMuted,
|
|
552
|
+
background: "transparent",
|
|
553
|
+
border: `1px solid ${t.border}`,
|
|
554
|
+
borderRadius: 4,
|
|
555
|
+
padding: "2px 8px",
|
|
556
|
+
cursor: "pointer",
|
|
557
|
+
fontWeight: 400,
|
|
558
|
+
width: "auto"
|
|
559
|
+
},
|
|
560
|
+
children: [
|
|
561
|
+
showContext ? "Hide" : "Show",
|
|
562
|
+
" what Neo saw"
|
|
563
|
+
]
|
|
564
|
+
}
|
|
565
|
+
)
|
|
566
|
+
]
|
|
567
|
+
}
|
|
568
|
+
),
|
|
569
|
+
iter.assistantContent && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
570
|
+
"div",
|
|
571
|
+
{
|
|
572
|
+
style: {
|
|
573
|
+
background: t.bgElev,
|
|
574
|
+
border: `1px solid ${t.border}`,
|
|
575
|
+
borderRadius: `2px ${t.radius} ${t.radius} ${t.radius}`,
|
|
576
|
+
padding: "10px 14px",
|
|
577
|
+
maxWidth: 820,
|
|
578
|
+
whiteSpace: "pre-wrap"
|
|
579
|
+
},
|
|
580
|
+
children: iter.assistantContent
|
|
581
|
+
}
|
|
582
|
+
),
|
|
583
|
+
iter.toolCalls.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { display: "flex", flexDirection: "column", gap: 6, paddingLeft: 12 }, children: iter.toolCalls.map((tc) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ToolCallCard, { invocation: tc, onClick: onToolCallClick }, tc.id)) }),
|
|
584
|
+
showContext && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
585
|
+
ContextDrawer,
|
|
586
|
+
{
|
|
587
|
+
messagesSentCount: iter.messagesSentCount,
|
|
588
|
+
contextMessages,
|
|
589
|
+
iter
|
|
590
|
+
}
|
|
591
|
+
)
|
|
592
|
+
]
|
|
593
|
+
}
|
|
594
|
+
);
|
|
453
595
|
}
|
|
454
|
-
function
|
|
596
|
+
function ContextDrawer({
|
|
597
|
+
messagesSentCount,
|
|
598
|
+
contextMessages,
|
|
599
|
+
iter
|
|
600
|
+
}) {
|
|
455
601
|
const t = useLensTheme();
|
|
456
|
-
|
|
457
|
-
if (iter.model) bits.push(iter.model);
|
|
458
|
-
if (iter.inputTokens !== void 0)
|
|
459
|
-
bits.push(`${iter.inputTokens}\u2192${iter.outputTokens ?? "?"} tok`);
|
|
460
|
-
if (iter.durationMs !== void 0) bits.push(`${(iter.durationMs / 1e3).toFixed(2)}s`);
|
|
461
|
-
if (iter.stopReason) bits.push(iter.stopReason);
|
|
462
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
602
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
463
603
|
"div",
|
|
464
604
|
{
|
|
465
605
|
style: {
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
fontFamily: t.fontMono
|
|
606
|
+
border: `1px dashed ${t.border}`,
|
|
607
|
+
borderRadius: t.radius,
|
|
608
|
+
padding: "10px 12px",
|
|
609
|
+
background: t.bg,
|
|
610
|
+
fontSize: 12,
|
|
611
|
+
color: t.textMuted
|
|
473
612
|
},
|
|
474
|
-
children:
|
|
613
|
+
children: [
|
|
614
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
615
|
+
"div",
|
|
616
|
+
{
|
|
617
|
+
style: {
|
|
618
|
+
fontSize: 10,
|
|
619
|
+
color: t.textSubtle,
|
|
620
|
+
textTransform: "uppercase",
|
|
621
|
+
letterSpacing: "0.08em",
|
|
622
|
+
fontWeight: 600,
|
|
623
|
+
marginBottom: 8
|
|
624
|
+
},
|
|
625
|
+
children: "What Neo saw before this step"
|
|
626
|
+
}
|
|
627
|
+
),
|
|
628
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { color: t.text, marginBottom: 8 }, children: [
|
|
629
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: messagesSentCount }),
|
|
630
|
+
" message",
|
|
631
|
+
messagesSentCount === 1 ? "" : "s",
|
|
632
|
+
" in context",
|
|
633
|
+
iter.model ? ` \xB7 sent to ${iter.model}` : "",
|
|
634
|
+
iter.inputTokens !== void 0 && ` \xB7 ${iter.inputTokens} input tokens`
|
|
635
|
+
] }),
|
|
636
|
+
contextMessages.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { color: t.textSubtle, fontStyle: "italic" }, children: "Just the system configuration \u2014 this is the first call of the conversation." }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("ol", { style: { margin: 0, paddingLeft: 18, display: "flex", flexDirection: "column", gap: 6 }, children: contextMessages.map((m, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("li", { style: { fontSize: 12 }, children: [
|
|
637
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
638
|
+
"span",
|
|
639
|
+
{
|
|
640
|
+
style: {
|
|
641
|
+
display: "inline-block",
|
|
642
|
+
padding: "1px 6px",
|
|
643
|
+
borderRadius: 3,
|
|
644
|
+
background: m.role === "user" ? `color-mix(in srgb, ${t.accent} 20%, transparent)` : m.role === "assistant" ? t.bgElev : m.role === "tool" ? `color-mix(in srgb, ${t.success} 18%, transparent)` : t.bgElev,
|
|
645
|
+
color: m.role === "user" ? t.accent : m.role === "tool" ? t.success : t.text,
|
|
646
|
+
fontFamily: t.fontMono,
|
|
647
|
+
fontSize: 10,
|
|
648
|
+
fontWeight: 600,
|
|
649
|
+
textTransform: "uppercase",
|
|
650
|
+
marginRight: 6
|
|
651
|
+
},
|
|
652
|
+
children: m.role
|
|
653
|
+
}
|
|
654
|
+
),
|
|
655
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { color: t.textMuted }, children: summarizeMessage(m) })
|
|
656
|
+
] }, i)) }),
|
|
657
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
658
|
+
"div",
|
|
659
|
+
{
|
|
660
|
+
style: {
|
|
661
|
+
marginTop: 10,
|
|
662
|
+
fontSize: 11,
|
|
663
|
+
color: t.textSubtle,
|
|
664
|
+
fontStyle: "italic"
|
|
665
|
+
},
|
|
666
|
+
children: "Plus the system configuration (see top of conversation) and the tools Neo had access to."
|
|
667
|
+
}
|
|
668
|
+
)
|
|
669
|
+
]
|
|
475
670
|
}
|
|
476
671
|
);
|
|
477
672
|
}
|
|
673
|
+
function summarizeMessage(m) {
|
|
674
|
+
if (m.role === "tool") {
|
|
675
|
+
return `tool result (${m.content.length.toLocaleString()} chars)`;
|
|
676
|
+
}
|
|
677
|
+
const t = m.content.replace(/\s+/g, " ").trim();
|
|
678
|
+
return t.length > 120 ? t.slice(0, 120) + "\u2026" : t;
|
|
679
|
+
}
|
|
478
680
|
function ToolCallCard({
|
|
479
681
|
invocation,
|
|
480
682
|
onClick
|
|
@@ -483,6 +685,7 @@ function ToolCallCard({
|
|
|
483
685
|
const [open, setOpen] = (0, import_react.useState)(false);
|
|
484
686
|
const preview = shortArgs(invocation.arguments);
|
|
485
687
|
const errored = invocation.error === true;
|
|
688
|
+
const friendlyVerb = toolVerb(invocation);
|
|
486
689
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
487
690
|
"div",
|
|
488
691
|
{
|
|
@@ -507,12 +710,12 @@ function ToolCallCard({
|
|
|
507
710
|
display: "flex",
|
|
508
711
|
alignItems: "center",
|
|
509
712
|
gap: 10,
|
|
510
|
-
fontSize: 12
|
|
511
|
-
fontFamily: t.fontMono
|
|
713
|
+
fontSize: 12
|
|
512
714
|
},
|
|
513
715
|
children: [
|
|
514
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { color:
|
|
515
|
-
/* @__PURE__ */ (0, import_jsx_runtime.
|
|
716
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { color: t.textMuted, fontFamily: t.fontSans }, children: friendlyVerb }),
|
|
717
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { color: errored ? t.error : t.accent, fontWeight: 600, fontFamily: t.fontMono }, children: invocation.name }),
|
|
718
|
+
preview && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: { color: t.textMuted, fontFamily: t.fontMono }, children: [
|
|
516
719
|
"(",
|
|
517
720
|
preview,
|
|
518
721
|
")"
|
|
@@ -527,11 +730,11 @@ function ToolCallCard({
|
|
|
527
730
|
borderRadius: 3,
|
|
528
731
|
background: `color-mix(in srgb, ${t.warning} 20%, transparent)`,
|
|
529
732
|
color: t.warning,
|
|
530
|
-
fontFamily: t.fontSans,
|
|
531
733
|
fontWeight: 600,
|
|
532
734
|
textTransform: "uppercase"
|
|
533
735
|
},
|
|
534
|
-
|
|
736
|
+
title: "This tool changed what skill is active",
|
|
737
|
+
children: "skill change"
|
|
535
738
|
}
|
|
536
739
|
),
|
|
537
740
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { color: t.textSubtle }, children: open ? "\u25BE" : "\u25B8" })
|
|
@@ -539,10 +742,10 @@ function ToolCallCard({
|
|
|
539
742
|
}
|
|
540
743
|
),
|
|
541
744
|
open && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { padding: "8px 12px", borderTop: `1px solid ${t.border}` }, children: [
|
|
542
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Label, { t, children: "
|
|
745
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Label, { t, children: "What Neo asked for" }),
|
|
543
746
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(JsonBlock, { value: invocation.arguments }),
|
|
544
747
|
invocation.result && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
545
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Label, { t, style: { marginTop: 10 }, children: "
|
|
748
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Label, { t, style: { marginTop: 10 }, children: "What the tool returned" }),
|
|
546
749
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
547
750
|
"pre",
|
|
548
751
|
{
|
|
@@ -563,7 +766,7 @@ function ToolCallCard({
|
|
|
563
766
|
)
|
|
564
767
|
] }),
|
|
565
768
|
invocation.decisionUpdate && Object.keys(invocation.decisionUpdate).length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
566
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Label, { t, style: { marginTop: 10 }, children: "
|
|
769
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Label, { t, style: { marginTop: 10 }, children: "What changed in Neo's state" }),
|
|
567
770
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(JsonBlock, { value: invocation.decisionUpdate })
|
|
568
771
|
] })
|
|
569
772
|
] })
|
|
@@ -571,6 +774,11 @@ function ToolCallCard({
|
|
|
571
774
|
}
|
|
572
775
|
);
|
|
573
776
|
}
|
|
777
|
+
function toolVerb(inv) {
|
|
778
|
+
if (inv.name === "list_skills") return "Asked for";
|
|
779
|
+
if (inv.name === "read_skill") return "Activated";
|
|
780
|
+
return "Called";
|
|
781
|
+
}
|
|
574
782
|
function Label({
|
|
575
783
|
t,
|
|
576
784
|
children,
|
|
@@ -627,14 +835,14 @@ var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
|
627
835
|
function IterationStrip({ timeline, selectedKey, onSelect }) {
|
|
628
836
|
const t = useLensTheme();
|
|
629
837
|
const chips = timeline.turns.flatMap(
|
|
630
|
-
(turn) => turn.iterations.map((iter) => ({
|
|
838
|
+
(turn) => turn.iterations.map((iter, stepIdx) => ({
|
|
631
839
|
key: `${turn.index}.${iter.index}`,
|
|
632
840
|
turn: turn.index + 1,
|
|
633
|
-
|
|
634
|
-
label:
|
|
635
|
-
tools: iter.toolCalls.length,
|
|
841
|
+
step: stepIdx + 1,
|
|
842
|
+
label: stepHeadline(iter),
|
|
636
843
|
durationMs: iter.durationMs ?? 0,
|
|
637
|
-
stopReason: iter.stopReason
|
|
844
|
+
stopReason: iter.stopReason,
|
|
845
|
+
toolCount: iter.toolCalls.length
|
|
638
846
|
}))
|
|
639
847
|
);
|
|
640
848
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
@@ -653,7 +861,8 @@ function IterationStrip({ timeline, selectedKey, onSelect }) {
|
|
|
653
861
|
chips.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { color: t.textSubtle, fontSize: 11 }, children: "No iterations yet." }),
|
|
654
862
|
chips.map((c) => {
|
|
655
863
|
const active = c.key === selectedKey;
|
|
656
|
-
const isFinal = c.
|
|
864
|
+
const isFinal = c.toolCount === 0;
|
|
865
|
+
const secs = c.durationMs >= 1e3 ? `${(c.durationMs / 1e3).toFixed(1)}s` : `${Math.round(c.durationMs)}ms`;
|
|
657
866
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
658
867
|
"button",
|
|
659
868
|
{
|
|
@@ -663,23 +872,27 @@ function IterationStrip({ timeline, selectedKey, onSelect }) {
|
|
|
663
872
|
color: active ? "#fff" : t.textMuted,
|
|
664
873
|
border: `1px solid ${active ? t.accent : t.border}`,
|
|
665
874
|
borderRadius: 4,
|
|
666
|
-
padding: "4px
|
|
875
|
+
padding: "4px 10px",
|
|
667
876
|
fontSize: 11,
|
|
668
|
-
fontFamily:
|
|
877
|
+
fontFamily: t.fontSans,
|
|
669
878
|
cursor: "pointer",
|
|
670
879
|
whiteSpace: "nowrap",
|
|
671
|
-
flexShrink: 0
|
|
880
|
+
flexShrink: 0,
|
|
881
|
+
maxWidth: 280,
|
|
882
|
+
overflow: "hidden",
|
|
883
|
+
textOverflow: "ellipsis"
|
|
672
884
|
},
|
|
673
|
-
title: `
|
|
885
|
+
title: `Question ${c.turn} \xB7 Step ${c.step} \xB7 ${secs}${c.stopReason ? ` \xB7 stop: ${c.stopReason}` : ""}`,
|
|
674
886
|
children: [
|
|
675
|
-
"
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
887
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { style: { fontWeight: 600 }, children: [
|
|
888
|
+
"Step ",
|
|
889
|
+
c.step
|
|
890
|
+
] }),
|
|
891
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { style: { opacity: 0.85 }, children: [
|
|
892
|
+
" \xB7 ",
|
|
893
|
+
c.label
|
|
894
|
+
] }),
|
|
895
|
+
isFinal && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { marginLeft: 6 }, children: "\u2713" })
|
|
683
896
|
]
|
|
684
897
|
},
|
|
685
898
|
c.key
|
|
@@ -689,11 +902,21 @@ function IterationStrip({ timeline, selectedKey, onSelect }) {
|
|
|
689
902
|
}
|
|
690
903
|
);
|
|
691
904
|
}
|
|
692
|
-
function
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
905
|
+
function stepHeadline(iter) {
|
|
906
|
+
if (iter.toolCalls.length === 0) return "Ready to answer";
|
|
907
|
+
if (iter.toolCalls.length === 1) {
|
|
908
|
+
const tc = iter.toolCalls[0];
|
|
909
|
+
if (tc.name === "list_skills") return "Looking up skills";
|
|
910
|
+
if (tc.name === "read_skill") {
|
|
911
|
+
const id = tc.arguments?.id;
|
|
912
|
+
return id ? `Activated ${id}` : "Activating skill";
|
|
913
|
+
}
|
|
914
|
+
return `Called ${tc.name}`;
|
|
915
|
+
}
|
|
916
|
+
if (iter.toolCalls.length <= 3) {
|
|
917
|
+
return `Called ${iter.toolCalls.map((tc) => tc.name).join(", ")}`;
|
|
918
|
+
}
|
|
919
|
+
return `Called ${iter.toolCalls.length} tools in parallel`;
|
|
697
920
|
}
|
|
698
921
|
|
|
699
922
|
// src/panels/ToolCallInspector.tsx
|
|
@@ -732,13 +955,13 @@ function ToolCallInspector({
|
|
|
732
955
|
background: t.bgElev
|
|
733
956
|
},
|
|
734
957
|
children: [
|
|
735
|
-
"
|
|
958
|
+
"Every tool Neo called \xB7 ",
|
|
736
959
|
timeline.tools.length
|
|
737
960
|
]
|
|
738
961
|
}
|
|
739
962
|
),
|
|
740
963
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { overflow: "auto", flex: 1 }, children: [
|
|
741
|
-
timeline.tools.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { padding: 14, color: t.textSubtle, fontSize: 12 }, children: "
|
|
964
|
+
timeline.tools.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { padding: 14, color: t.textSubtle, fontSize: 12 }, children: "Neo hasn't called any tools yet." }),
|
|
742
965
|
timeline.tools.map((tc) => {
|
|
743
966
|
const active = tc.id === selectedId;
|
|
744
967
|
const errored = tc.error === true;
|
|
@@ -884,6 +1107,12 @@ function AgentLens({
|
|
|
884
1107
|
fontFamily: t.fontSans
|
|
885
1108
|
},
|
|
886
1109
|
children: [
|
|
1110
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("style", { children: `
|
|
1111
|
+
[data-iter-selected="true"] {
|
|
1112
|
+
outline-color: currentColor !important;
|
|
1113
|
+
background: color-mix(in srgb, currentColor 8%, transparent);
|
|
1114
|
+
}
|
|
1115
|
+
` }),
|
|
887
1116
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: { gridArea: "strip" }, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
888
1117
|
IterationStrip,
|
|
889
1118
|
{
|
|
@@ -897,6 +1126,7 @@ function AgentLens({
|
|
|
897
1126
|
{
|
|
898
1127
|
timeline,
|
|
899
1128
|
onToolCallClick: handleToolClick,
|
|
1129
|
+
selectedIterKey,
|
|
900
1130
|
...derivedSystemPrompt && { systemPrompt: derivedSystemPrompt }
|
|
901
1131
|
}
|
|
902
1132
|
) }),
|
|
@@ -1001,7 +1231,10 @@ var LiveTimelineBuilder = class {
|
|
|
1001
1231
|
toolCalls: [],
|
|
1002
1232
|
decisionAtStart: {},
|
|
1003
1233
|
visibleTools: [],
|
|
1004
|
-
startMs: Date.now()
|
|
1234
|
+
startMs: Date.now(),
|
|
1235
|
+
// Freeze the message count here so "What Neo saw" can reproduce
|
|
1236
|
+
// the context window at this exact iteration later.
|
|
1237
|
+
messagesSentCount: this.messages.length
|
|
1005
1238
|
};
|
|
1006
1239
|
this.currentTurn.iterations.push(this.currentIter);
|
|
1007
1240
|
}
|