agentfootprint-lens 0.2.1 → 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 +245 -65
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +8 -12
- package/dist/index.d.ts +8 -12
- package/dist/index.js +245 -65
- 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 },
|
|
@@ -311,7 +313,15 @@ function MessagesPanel({
|
|
|
311
313
|
},
|
|
312
314
|
children: [
|
|
313
315
|
systemPrompt && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SystemBubble, { text: systemPrompt }),
|
|
314
|
-
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
|
+
))
|
|
315
325
|
]
|
|
316
326
|
}
|
|
317
327
|
);
|
|
@@ -348,7 +358,7 @@ function SystemBubble({ text }) {
|
|
|
348
358
|
font: "inherit"
|
|
349
359
|
},
|
|
350
360
|
children: [
|
|
351
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: "
|
|
361
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: "How Neo is configured" }),
|
|
352
362
|
" ",
|
|
353
363
|
open ? "\u25BE" : "\u25B8",
|
|
354
364
|
" ",
|
|
@@ -375,31 +385,34 @@ function SystemBubble({ text }) {
|
|
|
375
385
|
}
|
|
376
386
|
function TurnBlock({
|
|
377
387
|
turn,
|
|
388
|
+
allMessages,
|
|
378
389
|
onToolCallClick
|
|
379
390
|
}) {
|
|
380
391
|
const t = useLensTheme();
|
|
381
392
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 12 }, children: [
|
|
382
393
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(TurnHeader, { turn }),
|
|
383
394
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(UserBubble, { text: turn.userPrompt }),
|
|
384
|
-
turn.iterations.map((iter) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
395
|
+
turn.iterations.map((iter, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
385
396
|
IterationBlock,
|
|
386
397
|
{
|
|
387
398
|
iter,
|
|
399
|
+
iterPositionInTurn: i + 1,
|
|
388
400
|
turnIndex: turn.index,
|
|
401
|
+
allMessages,
|
|
389
402
|
onToolCallClick
|
|
390
403
|
},
|
|
391
404
|
iter.index
|
|
392
405
|
)),
|
|
393
406
|
turn.finalContent && turn.iterations.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { fontSize: 11, color: t.textSubtle, textAlign: "center" }, children: [
|
|
394
|
-
"
|
|
395
|
-
turn.index + 1,
|
|
396
|
-
" final \xB7 ",
|
|
407
|
+
"Answer compiled \xB7 ",
|
|
397
408
|
turn.iterations.length,
|
|
398
|
-
"
|
|
409
|
+
" step",
|
|
410
|
+
turn.iterations.length === 1 ? "" : "s",
|
|
411
|
+
" \xB7 ",
|
|
399
412
|
turn.totalInputTokens,
|
|
400
413
|
"\u2192",
|
|
401
414
|
turn.totalOutputTokens,
|
|
402
|
-
"
|
|
415
|
+
" tokens \xB7 ",
|
|
403
416
|
(turn.totalDurationMs / 1e3).toFixed(1),
|
|
404
417
|
"s"
|
|
405
418
|
] })
|
|
@@ -423,7 +436,7 @@ function TurnHeader({ turn }) {
|
|
|
423
436
|
children: [
|
|
424
437
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { flex: 1, height: 1, background: t.border } }),
|
|
425
438
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { children: [
|
|
426
|
-
"
|
|
439
|
+
"Your question ",
|
|
427
440
|
turn.index + 1
|
|
428
441
|
] }),
|
|
429
442
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { flex: 1, height: 1, background: t.border } })
|
|
@@ -449,13 +462,35 @@ function UserBubble({ text }) {
|
|
|
449
462
|
}
|
|
450
463
|
) });
|
|
451
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
|
+
}
|
|
452
482
|
function IterationBlock({
|
|
453
483
|
iter,
|
|
484
|
+
iterPositionInTurn,
|
|
454
485
|
turnIndex,
|
|
486
|
+
allMessages,
|
|
455
487
|
onToolCallClick
|
|
456
488
|
}) {
|
|
457
489
|
const t = useLensTheme();
|
|
490
|
+
const [showContext, setShowContext] = (0, import_react.useState)(false);
|
|
458
491
|
const key = `${turnIndex}.${iter.index}`;
|
|
492
|
+
const headline = iterationHeadline(iter);
|
|
493
|
+
const contextMessages = allMessages.slice(0, iter.messagesSentCount);
|
|
459
494
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
460
495
|
"div",
|
|
461
496
|
{
|
|
@@ -466,9 +501,6 @@ function IterationBlock({
|
|
|
466
501
|
display: "flex",
|
|
467
502
|
flexDirection: "column",
|
|
468
503
|
gap: 6,
|
|
469
|
-
// When the parent adds data-iter-selected (via IterationStrip
|
|
470
|
-
// click), pulse a soft ring using the accent color. Subtle so
|
|
471
|
-
// the chat itself stays readable.
|
|
472
504
|
padding: 8,
|
|
473
505
|
margin: -8,
|
|
474
506
|
borderRadius: t.radius,
|
|
@@ -477,7 +509,63 @@ function IterationBlock({
|
|
|
477
509
|
transition: "outline-color 180ms ease, background 180ms ease"
|
|
478
510
|
},
|
|
479
511
|
children: [
|
|
480
|
-
/* @__PURE__ */ (0, import_jsx_runtime.
|
|
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
|
+
),
|
|
481
569
|
iter.assistantContent && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
482
570
|
"div",
|
|
483
571
|
{
|
|
@@ -492,35 +580,103 @@ function IterationBlock({
|
|
|
492
580
|
children: iter.assistantContent
|
|
493
581
|
}
|
|
494
582
|
),
|
|
495
|
-
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)) })
|
|
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
|
+
)
|
|
496
592
|
]
|
|
497
593
|
}
|
|
498
594
|
);
|
|
499
595
|
}
|
|
500
|
-
function
|
|
596
|
+
function ContextDrawer({
|
|
597
|
+
messagesSentCount,
|
|
598
|
+
contextMessages,
|
|
599
|
+
iter
|
|
600
|
+
}) {
|
|
501
601
|
const t = useLensTheme();
|
|
502
|
-
|
|
503
|
-
if (iter.model) bits.push(iter.model);
|
|
504
|
-
if (iter.inputTokens !== void 0)
|
|
505
|
-
bits.push(`${iter.inputTokens}\u2192${iter.outputTokens ?? "?"} tok`);
|
|
506
|
-
if (iter.durationMs !== void 0) bits.push(`${(iter.durationMs / 1e3).toFixed(2)}s`);
|
|
507
|
-
if (iter.stopReason) bits.push(iter.stopReason);
|
|
508
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
602
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
509
603
|
"div",
|
|
510
604
|
{
|
|
511
605
|
style: {
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
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
|
|
519
612
|
},
|
|
520
|
-
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
|
+
]
|
|
521
670
|
}
|
|
522
671
|
);
|
|
523
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
|
+
}
|
|
524
680
|
function ToolCallCard({
|
|
525
681
|
invocation,
|
|
526
682
|
onClick
|
|
@@ -529,6 +685,7 @@ function ToolCallCard({
|
|
|
529
685
|
const [open, setOpen] = (0, import_react.useState)(false);
|
|
530
686
|
const preview = shortArgs(invocation.arguments);
|
|
531
687
|
const errored = invocation.error === true;
|
|
688
|
+
const friendlyVerb = toolVerb(invocation);
|
|
532
689
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
533
690
|
"div",
|
|
534
691
|
{
|
|
@@ -553,12 +710,12 @@ function ToolCallCard({
|
|
|
553
710
|
display: "flex",
|
|
554
711
|
alignItems: "center",
|
|
555
712
|
gap: 10,
|
|
556
|
-
fontSize: 12
|
|
557
|
-
fontFamily: t.fontMono
|
|
713
|
+
fontSize: 12
|
|
558
714
|
},
|
|
559
715
|
children: [
|
|
560
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { color:
|
|
561
|
-
/* @__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: [
|
|
562
719
|
"(",
|
|
563
720
|
preview,
|
|
564
721
|
")"
|
|
@@ -573,11 +730,11 @@ function ToolCallCard({
|
|
|
573
730
|
borderRadius: 3,
|
|
574
731
|
background: `color-mix(in srgb, ${t.warning} 20%, transparent)`,
|
|
575
732
|
color: t.warning,
|
|
576
|
-
fontFamily: t.fontSans,
|
|
577
733
|
fontWeight: 600,
|
|
578
734
|
textTransform: "uppercase"
|
|
579
735
|
},
|
|
580
|
-
|
|
736
|
+
title: "This tool changed what skill is active",
|
|
737
|
+
children: "skill change"
|
|
581
738
|
}
|
|
582
739
|
),
|
|
583
740
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { color: t.textSubtle }, children: open ? "\u25BE" : "\u25B8" })
|
|
@@ -585,10 +742,10 @@ function ToolCallCard({
|
|
|
585
742
|
}
|
|
586
743
|
),
|
|
587
744
|
open && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { padding: "8px 12px", borderTop: `1px solid ${t.border}` }, children: [
|
|
588
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Label, { t, children: "
|
|
745
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Label, { t, children: "What Neo asked for" }),
|
|
589
746
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(JsonBlock, { value: invocation.arguments }),
|
|
590
747
|
invocation.result && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
591
|
-
/* @__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" }),
|
|
592
749
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
593
750
|
"pre",
|
|
594
751
|
{
|
|
@@ -609,7 +766,7 @@ function ToolCallCard({
|
|
|
609
766
|
)
|
|
610
767
|
] }),
|
|
611
768
|
invocation.decisionUpdate && Object.keys(invocation.decisionUpdate).length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
612
|
-
/* @__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" }),
|
|
613
770
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(JsonBlock, { value: invocation.decisionUpdate })
|
|
614
771
|
] })
|
|
615
772
|
] })
|
|
@@ -617,6 +774,11 @@ function ToolCallCard({
|
|
|
617
774
|
}
|
|
618
775
|
);
|
|
619
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
|
+
}
|
|
620
782
|
function Label({
|
|
621
783
|
t,
|
|
622
784
|
children,
|
|
@@ -673,14 +835,14 @@ var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
|
673
835
|
function IterationStrip({ timeline, selectedKey, onSelect }) {
|
|
674
836
|
const t = useLensTheme();
|
|
675
837
|
const chips = timeline.turns.flatMap(
|
|
676
|
-
(turn) => turn.iterations.map((iter) => ({
|
|
838
|
+
(turn) => turn.iterations.map((iter, stepIdx) => ({
|
|
677
839
|
key: `${turn.index}.${iter.index}`,
|
|
678
840
|
turn: turn.index + 1,
|
|
679
|
-
|
|
680
|
-
label:
|
|
681
|
-
tools: iter.toolCalls.length,
|
|
841
|
+
step: stepIdx + 1,
|
|
842
|
+
label: stepHeadline(iter),
|
|
682
843
|
durationMs: iter.durationMs ?? 0,
|
|
683
|
-
stopReason: iter.stopReason
|
|
844
|
+
stopReason: iter.stopReason,
|
|
845
|
+
toolCount: iter.toolCalls.length
|
|
684
846
|
}))
|
|
685
847
|
);
|
|
686
848
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
@@ -699,7 +861,8 @@ function IterationStrip({ timeline, selectedKey, onSelect }) {
|
|
|
699
861
|
chips.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { color: t.textSubtle, fontSize: 11 }, children: "No iterations yet." }),
|
|
700
862
|
chips.map((c) => {
|
|
701
863
|
const active = c.key === selectedKey;
|
|
702
|
-
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`;
|
|
703
866
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
704
867
|
"button",
|
|
705
868
|
{
|
|
@@ -709,23 +872,27 @@ function IterationStrip({ timeline, selectedKey, onSelect }) {
|
|
|
709
872
|
color: active ? "#fff" : t.textMuted,
|
|
710
873
|
border: `1px solid ${active ? t.accent : t.border}`,
|
|
711
874
|
borderRadius: 4,
|
|
712
|
-
padding: "4px
|
|
875
|
+
padding: "4px 10px",
|
|
713
876
|
fontSize: 11,
|
|
714
|
-
fontFamily:
|
|
877
|
+
fontFamily: t.fontSans,
|
|
715
878
|
cursor: "pointer",
|
|
716
879
|
whiteSpace: "nowrap",
|
|
717
|
-
flexShrink: 0
|
|
880
|
+
flexShrink: 0,
|
|
881
|
+
maxWidth: 280,
|
|
882
|
+
overflow: "hidden",
|
|
883
|
+
textOverflow: "ellipsis"
|
|
718
884
|
},
|
|
719
|
-
title: `
|
|
885
|
+
title: `Question ${c.turn} \xB7 Step ${c.step} \xB7 ${secs}${c.stopReason ? ` \xB7 stop: ${c.stopReason}` : ""}`,
|
|
720
886
|
children: [
|
|
721
|
-
"
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
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" })
|
|
729
896
|
]
|
|
730
897
|
},
|
|
731
898
|
c.key
|
|
@@ -735,11 +902,21 @@ function IterationStrip({ timeline, selectedKey, onSelect }) {
|
|
|
735
902
|
}
|
|
736
903
|
);
|
|
737
904
|
}
|
|
738
|
-
function
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
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`;
|
|
743
920
|
}
|
|
744
921
|
|
|
745
922
|
// src/panels/ToolCallInspector.tsx
|
|
@@ -778,13 +955,13 @@ function ToolCallInspector({
|
|
|
778
955
|
background: t.bgElev
|
|
779
956
|
},
|
|
780
957
|
children: [
|
|
781
|
-
"
|
|
958
|
+
"Every tool Neo called \xB7 ",
|
|
782
959
|
timeline.tools.length
|
|
783
960
|
]
|
|
784
961
|
}
|
|
785
962
|
),
|
|
786
963
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { overflow: "auto", flex: 1 }, children: [
|
|
787
|
-
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." }),
|
|
788
965
|
timeline.tools.map((tc) => {
|
|
789
966
|
const active = tc.id === selectedId;
|
|
790
967
|
const errored = tc.error === true;
|
|
@@ -1054,7 +1231,10 @@ var LiveTimelineBuilder = class {
|
|
|
1054
1231
|
toolCalls: [],
|
|
1055
1232
|
decisionAtStart: {},
|
|
1056
1233
|
visibleTools: [],
|
|
1057
|
-
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
|
|
1058
1238
|
};
|
|
1059
1239
|
this.currentTurn.iterations.push(this.currentIter);
|
|
1060
1240
|
}
|