agentfootprint-lens 0.3.0 → 0.4.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 +2824 -195
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +232 -3
- package/dist/index.d.ts +232 -3
- package/dist/index.js +2819 -198
- package/dist/index.js.map +1 -1
- package/package.json +7 -2
package/dist/index.cjs
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
2
3
|
var __defProp = Object.defineProperty;
|
|
3
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
5
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
8
|
var __export = (target, all) => {
|
|
7
9
|
for (var name in all)
|
|
@@ -15,16 +17,30 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
15
17
|
}
|
|
16
18
|
return to;
|
|
17
19
|
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
18
28
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
29
|
|
|
20
30
|
// src/index.ts
|
|
21
31
|
var src_exports = {};
|
|
22
32
|
__export(src_exports, {
|
|
23
33
|
AgentLens: () => AgentLens,
|
|
34
|
+
AskCard: () => AskCard,
|
|
24
35
|
IterationStrip: () => IterationStrip,
|
|
25
36
|
LiveTimelineBuilder: () => LiveTimelineBuilder,
|
|
26
37
|
MessagesPanel: () => MessagesPanel,
|
|
38
|
+
RunSummary: () => RunSummary,
|
|
39
|
+
SkillsPanel: () => SkillsPanel,
|
|
40
|
+
StageFlow: () => StageFlow,
|
|
41
|
+
TimeTravel: () => TimeTravel,
|
|
27
42
|
ToolCallInspector: () => ToolCallInspector,
|
|
43
|
+
deriveStages: () => deriveStages,
|
|
28
44
|
fromAgentSnapshot: () => fromAgentSnapshot,
|
|
29
45
|
resolveLensTheme: () => resolve,
|
|
30
46
|
useLensTheme: () => useLensTheme,
|
|
@@ -33,7 +49,7 @@ __export(src_exports, {
|
|
|
33
49
|
module.exports = __toCommonJS(src_exports);
|
|
34
50
|
|
|
35
51
|
// src/AgentLens.tsx
|
|
36
|
-
var
|
|
52
|
+
var import_react6 = require("react");
|
|
37
53
|
|
|
38
54
|
// src/adapters/fromAgentSnapshot.ts
|
|
39
55
|
function fromAgentSnapshot(runtime) {
|
|
@@ -241,7 +257,7 @@ function finalizeTurn(t) {
|
|
|
241
257
|
}
|
|
242
258
|
|
|
243
259
|
// src/panels/MessagesPanel.tsx
|
|
244
|
-
var import_react = require("react");
|
|
260
|
+
var import_react = __toESM(require("react"), 1);
|
|
245
261
|
|
|
246
262
|
// src/theme/useLensTheme.ts
|
|
247
263
|
var import_footprint_explainable_ui = require("footprint-explainable-ui");
|
|
@@ -278,27 +294,105 @@ function MessagesPanel({
|
|
|
278
294
|
timeline,
|
|
279
295
|
onToolCallClick,
|
|
280
296
|
systemPrompt,
|
|
281
|
-
selectedIterKey
|
|
297
|
+
selectedIterKey,
|
|
298
|
+
stages,
|
|
299
|
+
focusIndex,
|
|
300
|
+
onFocusChange,
|
|
301
|
+
isLive
|
|
282
302
|
}) {
|
|
283
303
|
const t = useLensTheme();
|
|
284
304
|
const scrollRef = (0, import_react.useRef)(null);
|
|
305
|
+
const iterRanges = useIterationStageRanges(stages);
|
|
306
|
+
(0, import_react.useEffect)(() => {
|
|
307
|
+
if (!scrollRef.current) {
|
|
308
|
+
console.log("[Lens scroll] selectedIter effect skipped: no scrollRef");
|
|
309
|
+
return;
|
|
310
|
+
}
|
|
311
|
+
if (selectedIterKey) {
|
|
312
|
+
const target = scrollRef.current.querySelector(
|
|
313
|
+
`[data-iter-key="${CSS.escape(selectedIterKey)}"]`
|
|
314
|
+
);
|
|
315
|
+
console.log("[Lens scroll] selectedIterKey path", {
|
|
316
|
+
selectedIterKey,
|
|
317
|
+
foundTarget: !!target
|
|
318
|
+
});
|
|
319
|
+
if (target) {
|
|
320
|
+
target.scrollIntoView({ block: "start", behavior: "smooth" });
|
|
321
|
+
target.setAttribute("data-iter-selected", "true");
|
|
322
|
+
const h = window.setTimeout(() => target.removeAttribute("data-iter-selected"), 1200);
|
|
323
|
+
return () => window.clearTimeout(h);
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
}, [selectedIterKey]);
|
|
285
327
|
(0, import_react.useEffect)(() => {
|
|
286
|
-
|
|
328
|
+
const ctx = {
|
|
329
|
+
focusIndex,
|
|
330
|
+
isLive,
|
|
331
|
+
stagesLen: stages?.length ?? 0,
|
|
332
|
+
iterRangesSize: iterRanges.size,
|
|
333
|
+
hasScrollRef: !!scrollRef.current
|
|
334
|
+
};
|
|
335
|
+
if (!scrollRef.current || focusIndex === void 0 || !stages?.length) {
|
|
336
|
+
console.log("[Lens scroll] focus effect SKIPPED", ctx);
|
|
337
|
+
return;
|
|
338
|
+
}
|
|
339
|
+
if (isLive) {
|
|
340
|
+
const el = scrollRef.current;
|
|
341
|
+
const beforeTop2 = el.scrollTop;
|
|
342
|
+
const sh = el.scrollHeight;
|
|
343
|
+
const ch = el.clientHeight;
|
|
344
|
+
const canScroll = sh > ch;
|
|
345
|
+
const alreadyAtBottom = Math.abs(sh - ch - beforeTop2) < 2;
|
|
346
|
+
el.scrollTo({ top: sh, behavior: "auto" });
|
|
347
|
+
const afterTop = el.scrollTop;
|
|
348
|
+
const moved = afterTop !== beforeTop2;
|
|
349
|
+
console.log(
|
|
350
|
+
`[Lens scroll] LIVE tail \u2192 ${moved ? "moved" : canScroll ? "NO-OP (scrollTo returned same top)" : alreadyAtBottom ? "already at bottom" : "CONTAINER NOT SCROLLABLE (scrollHeight<=clientHeight)"} \xB7 sh=${sh} ch=${ch} before=${beforeTop2} after=${afterTop}`,
|
|
351
|
+
{ ...ctx, scrollHeight: sh, clientHeight: ch, beforeScrollTop: beforeTop2, afterScrollTop: afterTop }
|
|
352
|
+
);
|
|
353
|
+
return;
|
|
354
|
+
}
|
|
355
|
+
const key = keyForStage(iterRanges, focusIndex);
|
|
356
|
+
if (!key) {
|
|
357
|
+
console.log("[Lens scroll] focus effect: no iterKey for focusIndex", ctx);
|
|
358
|
+
return;
|
|
359
|
+
}
|
|
287
360
|
const target = scrollRef.current.querySelector(
|
|
288
|
-
`[data-iter-key="${CSS.escape(
|
|
361
|
+
`[data-iter-key="${CSS.escape(key)}"]`
|
|
289
362
|
);
|
|
290
|
-
if (!target)
|
|
363
|
+
if (!target) {
|
|
364
|
+
console.log("[Lens scroll] focus effect: DOM node missing for key", {
|
|
365
|
+
...ctx,
|
|
366
|
+
key
|
|
367
|
+
});
|
|
368
|
+
return;
|
|
369
|
+
}
|
|
370
|
+
const container = scrollRef.current;
|
|
371
|
+
const rect = target.getBoundingClientRect();
|
|
372
|
+
const cRect = container.getBoundingClientRect();
|
|
373
|
+
const relTop = rect.top - cRect.top;
|
|
374
|
+
const beforeTop = container.scrollTop;
|
|
291
375
|
target.scrollIntoView({ block: "start", behavior: "smooth" });
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
376
|
+
console.log(
|
|
377
|
+
`[Lens scroll] SCRUB key=${key} \xB7 relTop=${Math.round(relTop)} sh=${container.scrollHeight} ch=${container.clientHeight} before=${beforeTop}`,
|
|
378
|
+
{ ...ctx, key }
|
|
379
|
+
);
|
|
380
|
+
}, [focusIndex, isLive, iterRanges, stages?.length]);
|
|
296
381
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
297
382
|
"div",
|
|
298
383
|
{
|
|
299
384
|
ref: scrollRef,
|
|
300
385
|
"data-fp-lens": "messages-panel",
|
|
301
386
|
style: {
|
|
387
|
+
// Absolute + inset:0 inside a `position: relative` wrapper
|
|
388
|
+
// forces the panel to be EXACTLY the size of its wrapper cell,
|
|
389
|
+
// regardless of flex/grid height resolution quirks upstream.
|
|
390
|
+
// Without this, percentage heights and 1fr rows can fail to
|
|
391
|
+
// resolve and the panel grows to its content → no scroll.
|
|
392
|
+
// The grid-area wrapper in AgentLens sets `position: relative`
|
|
393
|
+
// to make this the containing block.
|
|
394
|
+
position: "absolute",
|
|
395
|
+
inset: 0,
|
|
302
396
|
display: "flex",
|
|
303
397
|
flexDirection: "column",
|
|
304
398
|
gap: 16,
|
|
@@ -318,7 +412,11 @@ function MessagesPanel({
|
|
|
318
412
|
{
|
|
319
413
|
turn,
|
|
320
414
|
allMessages: timeline.messages,
|
|
321
|
-
onToolCallClick
|
|
415
|
+
onToolCallClick,
|
|
416
|
+
iterRanges,
|
|
417
|
+
focusIndex,
|
|
418
|
+
stages,
|
|
419
|
+
onFocusChange
|
|
322
420
|
},
|
|
323
421
|
turn.index
|
|
324
422
|
))
|
|
@@ -386,23 +484,44 @@ function SystemBubble({ text }) {
|
|
|
386
484
|
function TurnBlock({
|
|
387
485
|
turn,
|
|
388
486
|
allMessages,
|
|
389
|
-
onToolCallClick
|
|
487
|
+
onToolCallClick,
|
|
488
|
+
iterRanges,
|
|
489
|
+
focusIndex,
|
|
490
|
+
stages,
|
|
491
|
+
onFocusChange
|
|
390
492
|
}) {
|
|
391
493
|
const t = useLensTheme();
|
|
392
494
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 12 }, children: [
|
|
393
495
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(TurnHeader, { turn }),
|
|
394
496
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(UserBubble, { text: turn.userPrompt }),
|
|
395
|
-
turn.iterations.map((iter, i) =>
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
|
|
497
|
+
turn.iterations.map((iter, i) => {
|
|
498
|
+
const key = `${turn.index}.${iter.index}`;
|
|
499
|
+
const range = iterRanges?.get(key);
|
|
500
|
+
let state = "future";
|
|
501
|
+
if (range && focusIndex !== void 0) {
|
|
502
|
+
if (focusIndex < range.firstStageIndex) state = "future";
|
|
503
|
+
else if (focusIndex > range.lastStageIndex) state = "past";
|
|
504
|
+
else state = "active";
|
|
505
|
+
} else if (!range && focusIndex === void 0) {
|
|
506
|
+
state = "active";
|
|
507
|
+
}
|
|
508
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
509
|
+
IterationBlock,
|
|
510
|
+
{
|
|
511
|
+
iter,
|
|
512
|
+
iterPositionInTurn: i + 1,
|
|
513
|
+
turnIndex: turn.index,
|
|
514
|
+
allMessages,
|
|
515
|
+
onToolCallClick,
|
|
516
|
+
state,
|
|
517
|
+
stages,
|
|
518
|
+
range,
|
|
519
|
+
focusIndex,
|
|
520
|
+
...range && onFocusChange ? { onClick: () => onFocusChange(range.lastStageIndex) } : {}
|
|
521
|
+
},
|
|
522
|
+
iter.index
|
|
523
|
+
);
|
|
524
|
+
}),
|
|
406
525
|
turn.finalContent && turn.iterations.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { fontSize: 11, color: t.textSubtle, textAlign: "center" }, children: [
|
|
407
526
|
"Answer compiled \xB7 ",
|
|
408
527
|
turn.iterations.length,
|
|
@@ -467,30 +586,105 @@ function iterationHeadline(iter) {
|
|
|
467
586
|
return "Neo is ready to answer";
|
|
468
587
|
}
|
|
469
588
|
if (iter.toolCalls.length === 1) {
|
|
470
|
-
|
|
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`;
|
|
589
|
+
return singleToolHeadline(iter.toolCalls[0]);
|
|
477
590
|
}
|
|
478
591
|
const names = iter.toolCalls.map((tc) => tc.name);
|
|
479
|
-
if (names.length <= 3)
|
|
480
|
-
|
|
592
|
+
if (names.length <= 3) {
|
|
593
|
+
return `Neo called ${names.length} tools in parallel (${names.join(", ")})`;
|
|
594
|
+
}
|
|
595
|
+
return `Neo gathered data from ${names.length} tools in parallel`;
|
|
596
|
+
}
|
|
597
|
+
function singleToolHeadline(tc) {
|
|
598
|
+
if (tc.name === "list_skills") return "Neo is looking up available skills";
|
|
599
|
+
if (tc.name === "read_skill") {
|
|
600
|
+
const id = tc.arguments?.id ?? "?";
|
|
601
|
+
return `Neo activated the "${id}" skill`;
|
|
602
|
+
}
|
|
603
|
+
if (tc.name === "ask_human" || tc.name === "ask_user") {
|
|
604
|
+
return "Neo asked the user for clarification";
|
|
605
|
+
}
|
|
606
|
+
return `Neo called tool (${tc.name})`;
|
|
481
607
|
}
|
|
482
608
|
function IterationBlock({
|
|
483
609
|
iter,
|
|
484
610
|
iterPositionInTurn,
|
|
485
611
|
turnIndex,
|
|
486
612
|
allMessages,
|
|
487
|
-
onToolCallClick
|
|
613
|
+
onToolCallClick,
|
|
614
|
+
state = "active",
|
|
615
|
+
stages,
|
|
616
|
+
range,
|
|
617
|
+
focusIndex,
|
|
618
|
+
onClick
|
|
488
619
|
}) {
|
|
489
620
|
const t = useLensTheme();
|
|
490
621
|
const [showContext, setShowContext] = (0, import_react.useState)(false);
|
|
491
622
|
const key = `${turnIndex}.${iter.index}`;
|
|
492
623
|
const headline = iterationHeadline(iter);
|
|
493
624
|
const contextMessages = allMessages.slice(0, iter.messagesSentCount);
|
|
625
|
+
let revealIdx = Number.POSITIVE_INFINITY;
|
|
626
|
+
if (range && focusIndex !== void 0) {
|
|
627
|
+
if (state === "future") revealIdx = -1;
|
|
628
|
+
else if (state === "past") revealIdx = range.lastStageIndex;
|
|
629
|
+
else revealIdx = focusIndex;
|
|
630
|
+
}
|
|
631
|
+
const roundHasStarted = revealIdx >= (range?.firstStageIndex ?? 0);
|
|
632
|
+
const revealedMutations = (() => {
|
|
633
|
+
if (!stages || !range) return void 0;
|
|
634
|
+
const agg = {
|
|
635
|
+
systemPrompt: false,
|
|
636
|
+
tools: false,
|
|
637
|
+
systemPromptDeltaChars: 0,
|
|
638
|
+
toolsAdded: 0,
|
|
639
|
+
toolsRemoved: 0,
|
|
640
|
+
systemPromptAdded: "",
|
|
641
|
+
toolsAddedList: []
|
|
642
|
+
};
|
|
643
|
+
const stop = Math.min(revealIdx, range.lastStageIndex);
|
|
644
|
+
for (let i = range.firstStageIndex; i <= stop; i++) {
|
|
645
|
+
const m = stages[i]?.mutations;
|
|
646
|
+
if (!m) continue;
|
|
647
|
+
if (m.systemPrompt) agg.systemPrompt = true;
|
|
648
|
+
if (m.tools) agg.tools = true;
|
|
649
|
+
if (m.systemPromptDeltaChars) agg.systemPromptDeltaChars += m.systemPromptDeltaChars;
|
|
650
|
+
if (m.toolsAdded) agg.toolsAdded += m.toolsAdded;
|
|
651
|
+
if (m.toolsRemoved) agg.toolsRemoved += m.toolsRemoved;
|
|
652
|
+
if (m.systemPromptAdded) {
|
|
653
|
+
agg.systemPromptAdded = agg.systemPromptAdded ? `${agg.systemPromptAdded}
|
|
654
|
+
|
|
655
|
+
${m.systemPromptAdded}` : m.systemPromptAdded;
|
|
656
|
+
}
|
|
657
|
+
if (m.activatedSkillId && !agg.activatedSkillId) {
|
|
658
|
+
agg.activatedSkillId = m.activatedSkillId;
|
|
659
|
+
}
|
|
660
|
+
if (m.toolsAddedList?.length) {
|
|
661
|
+
for (const name of m.toolsAddedList) {
|
|
662
|
+
if (!agg.toolsAddedList.includes(name)) agg.toolsAddedList.push(name);
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
return agg;
|
|
667
|
+
})();
|
|
668
|
+
const mutations = revealedMutations;
|
|
669
|
+
const toolStageIdx = /* @__PURE__ */ new Map();
|
|
670
|
+
if (stages) {
|
|
671
|
+
for (const tc of iter.toolCalls) {
|
|
672
|
+
let outIdx = -1;
|
|
673
|
+
let retIdx = -1;
|
|
674
|
+
for (let i = 0; i < stages.length; i++) {
|
|
675
|
+
const s = stages[i];
|
|
676
|
+
if (s.turnIndex !== turnIndex || s.iterIndex !== iter.index) continue;
|
|
677
|
+
if (s.toolName !== tc.name) continue;
|
|
678
|
+
if (s.from === "agent" && s.to === "tool" && outIdx < 0) outIdx = i;
|
|
679
|
+
else if (s.from === "tool" && s.to === "agent" && retIdx < 0) retIdx = i;
|
|
680
|
+
}
|
|
681
|
+
toolStageIdx.set(tc.id, { outIdx, retIdx });
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
const opacity = state === "future" ? 0.4 : state === "past" ? 0.85 : 1;
|
|
685
|
+
const isActiveRound = state === "active";
|
|
686
|
+
const background = isActiveRound ? `color-mix(in srgb, ${t.accent} 10%, ${t.bg})` : "transparent";
|
|
687
|
+
const boxShadow = isActiveRound ? `0 0 0 1px ${t.accent}, 0 0 24px color-mix(in srgb, ${t.accent} 22%, transparent)` : "none";
|
|
494
688
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
495
689
|
"div",
|
|
496
690
|
{
|
|
@@ -498,17 +692,36 @@ function IterationBlock({
|
|
|
498
692
|
"data-turn-index": turnIndex,
|
|
499
693
|
"data-iter-index": iter.index,
|
|
500
694
|
style: {
|
|
695
|
+
position: "relative",
|
|
501
696
|
display: "flex",
|
|
502
697
|
flexDirection: "column",
|
|
503
698
|
gap: 6,
|
|
504
|
-
padding:
|
|
505
|
-
margin: -
|
|
506
|
-
borderRadius:
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
699
|
+
padding: 12,
|
|
700
|
+
margin: isActiveRound ? "2px -12px" : "-8px",
|
|
701
|
+
borderRadius: 8,
|
|
702
|
+
background,
|
|
703
|
+
borderLeft: isActiveRound ? `3px solid ${t.accent}` : "3px solid transparent",
|
|
704
|
+
boxShadow,
|
|
705
|
+
opacity,
|
|
706
|
+
transition: "background 220ms ease, box-shadow 220ms ease, opacity 220ms ease, border-left-color 220ms ease, margin 220ms ease"
|
|
510
707
|
},
|
|
511
708
|
children: [
|
|
709
|
+
isActiveRound && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
710
|
+
"span",
|
|
711
|
+
{
|
|
712
|
+
"aria-hidden": "true",
|
|
713
|
+
style: {
|
|
714
|
+
position: "absolute",
|
|
715
|
+
left: -3,
|
|
716
|
+
top: 8,
|
|
717
|
+
bottom: 8,
|
|
718
|
+
width: 3,
|
|
719
|
+
background: t.accent,
|
|
720
|
+
boxShadow: `0 0 8px ${t.accent}`,
|
|
721
|
+
pointerEvents: "none"
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
),
|
|
512
725
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
513
726
|
"div",
|
|
514
727
|
{
|
|
@@ -520,12 +733,36 @@ function IterationBlock({
|
|
|
520
733
|
color: t.textMuted
|
|
521
734
|
},
|
|
522
735
|
children: [
|
|
523
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
524
|
-
"
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
736
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
737
|
+
"button",
|
|
738
|
+
{
|
|
739
|
+
onClick,
|
|
740
|
+
disabled: !onClick,
|
|
741
|
+
title: onClick ? "Jump the slider to this round" : void 0,
|
|
742
|
+
style: {
|
|
743
|
+
background: "transparent",
|
|
744
|
+
border: "none",
|
|
745
|
+
padding: 0,
|
|
746
|
+
margin: 0,
|
|
747
|
+
display: "flex",
|
|
748
|
+
alignItems: "baseline",
|
|
749
|
+
gap: 8,
|
|
750
|
+
cursor: onClick ? "pointer" : "default",
|
|
751
|
+
color: "inherit",
|
|
752
|
+
font: "inherit",
|
|
753
|
+
width: "auto",
|
|
754
|
+
textAlign: "left"
|
|
755
|
+
},
|
|
756
|
+
children: [
|
|
757
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: { color: t.accent, fontWeight: 600 }, children: [
|
|
758
|
+
"Round ",
|
|
759
|
+
iterPositionInTurn,
|
|
760
|
+
":"
|
|
761
|
+
] }),
|
|
762
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { color: t.text }, children: headline })
|
|
763
|
+
]
|
|
764
|
+
}
|
|
765
|
+
),
|
|
529
766
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { flex: 1 } }),
|
|
530
767
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
531
768
|
"span",
|
|
@@ -566,21 +803,57 @@ function IterationBlock({
|
|
|
566
803
|
]
|
|
567
804
|
}
|
|
568
805
|
),
|
|
569
|
-
iter.
|
|
806
|
+
roundHasStarted && (iter.model || iter.stopReason || (iter.matchedInstructions?.length ?? 0) > 0) && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
570
807
|
"div",
|
|
571
808
|
{
|
|
572
809
|
style: {
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
810
|
+
display: "flex",
|
|
811
|
+
flexWrap: "wrap",
|
|
812
|
+
gap: 6,
|
|
813
|
+
fontSize: 10,
|
|
814
|
+
color: t.textSubtle,
|
|
815
|
+
fontFamily: t.fontMono,
|
|
816
|
+
paddingLeft: 12
|
|
579
817
|
},
|
|
580
|
-
children:
|
|
818
|
+
children: [
|
|
819
|
+
iter.model && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MetaPill, { t, title: "Model the LLM call was routed to", children: iter.model }),
|
|
820
|
+
iter.stopReason && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(MetaPill, { t, title: "Why the LLM stopped producing tokens", children: [
|
|
821
|
+
"stop: ",
|
|
822
|
+
iter.stopReason
|
|
823
|
+
] }),
|
|
824
|
+
iter.matchedInstructions?.map((id) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
825
|
+
MetaPill,
|
|
826
|
+
{
|
|
827
|
+
t,
|
|
828
|
+
title: "Instruction injected into this round",
|
|
829
|
+
accent: true,
|
|
830
|
+
children: [
|
|
831
|
+
"\u25B8 ",
|
|
832
|
+
id
|
|
833
|
+
]
|
|
834
|
+
},
|
|
835
|
+
id
|
|
836
|
+
))
|
|
837
|
+
]
|
|
581
838
|
}
|
|
582
839
|
),
|
|
583
|
-
|
|
840
|
+
roundHasStarted && iter.assistantContent && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ReasoningBubble, { text: iter.assistantContent }),
|
|
841
|
+
roundHasStarted && 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) => {
|
|
842
|
+
const idx = toolStageIdx.get(tc.id);
|
|
843
|
+
const cardRevealed = !idx || idx.outIdx < 0 || revealIdx >= idx.outIdx;
|
|
844
|
+
if (!cardRevealed) return null;
|
|
845
|
+
const resultRevealed = !idx || idx.retIdx < 0 || revealIdx >= idx.retIdx;
|
|
846
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
847
|
+
ToolCallCard,
|
|
848
|
+
{
|
|
849
|
+
invocation: tc,
|
|
850
|
+
onClick: onToolCallClick,
|
|
851
|
+
resultRevealed
|
|
852
|
+
},
|
|
853
|
+
tc.id
|
|
854
|
+
);
|
|
855
|
+
}) }),
|
|
856
|
+
mutations && (mutations.systemPrompt || mutations.tools) && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MutationStrip, { mutations, iter }),
|
|
584
857
|
showContext && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
585
858
|
ContextDrawer,
|
|
586
859
|
{
|
|
@@ -593,6 +866,448 @@ function IterationBlock({
|
|
|
593
866
|
}
|
|
594
867
|
);
|
|
595
868
|
}
|
|
869
|
+
function ReasoningBubble({ text }) {
|
|
870
|
+
const t = useLensTheme();
|
|
871
|
+
const [open, setOpen] = (0, import_react.useState)(false);
|
|
872
|
+
const PREVIEW_LEN = 140;
|
|
873
|
+
const flat = text.replace(/\s+/g, " ").trim();
|
|
874
|
+
const needsToggle = flat.length > PREVIEW_LEN;
|
|
875
|
+
const preview = needsToggle ? flat.slice(0, PREVIEW_LEN - 1) + "\u2026" : flat;
|
|
876
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
877
|
+
"div",
|
|
878
|
+
{
|
|
879
|
+
style: {
|
|
880
|
+
background: t.bgElev,
|
|
881
|
+
border: `1px solid ${t.border}`,
|
|
882
|
+
borderRadius: `2px ${t.radius} ${t.radius} ${t.radius}`,
|
|
883
|
+
padding: "10px 14px",
|
|
884
|
+
maxWidth: 820,
|
|
885
|
+
whiteSpace: "pre-wrap",
|
|
886
|
+
fontSize: 13,
|
|
887
|
+
lineHeight: 1.55
|
|
888
|
+
},
|
|
889
|
+
children: needsToggle && !open ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
890
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: preview }),
|
|
891
|
+
" ",
|
|
892
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
893
|
+
"button",
|
|
894
|
+
{
|
|
895
|
+
onClick: () => setOpen(true),
|
|
896
|
+
style: {
|
|
897
|
+
background: "transparent",
|
|
898
|
+
border: "none",
|
|
899
|
+
padding: 0,
|
|
900
|
+
color: t.accent,
|
|
901
|
+
cursor: "pointer",
|
|
902
|
+
fontSize: 12,
|
|
903
|
+
fontWeight: 600,
|
|
904
|
+
width: "auto"
|
|
905
|
+
},
|
|
906
|
+
children: "\u25B8 Show full reasoning"
|
|
907
|
+
}
|
|
908
|
+
)
|
|
909
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
910
|
+
text,
|
|
911
|
+
needsToggle && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { marginTop: 6 }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
912
|
+
"button",
|
|
913
|
+
{
|
|
914
|
+
onClick: () => setOpen(false),
|
|
915
|
+
style: {
|
|
916
|
+
background: "transparent",
|
|
917
|
+
border: "none",
|
|
918
|
+
padding: 0,
|
|
919
|
+
color: t.textMuted,
|
|
920
|
+
cursor: "pointer",
|
|
921
|
+
fontSize: 12,
|
|
922
|
+
fontWeight: 500,
|
|
923
|
+
width: "auto"
|
|
924
|
+
},
|
|
925
|
+
children: "\u25BE Collapse"
|
|
926
|
+
}
|
|
927
|
+
) })
|
|
928
|
+
] })
|
|
929
|
+
}
|
|
930
|
+
);
|
|
931
|
+
}
|
|
932
|
+
function MetaPill({
|
|
933
|
+
t,
|
|
934
|
+
children,
|
|
935
|
+
title,
|
|
936
|
+
accent
|
|
937
|
+
}) {
|
|
938
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
939
|
+
"span",
|
|
940
|
+
{
|
|
941
|
+
title,
|
|
942
|
+
style: {
|
|
943
|
+
padding: "1px 6px",
|
|
944
|
+
borderRadius: 3,
|
|
945
|
+
background: accent ? `color-mix(in srgb, ${t.warning} 18%, transparent)` : t.bgElev,
|
|
946
|
+
color: accent ? t.warning : t.textSubtle,
|
|
947
|
+
fontWeight: accent ? 600 : 500,
|
|
948
|
+
letterSpacing: "0.02em",
|
|
949
|
+
whiteSpace: "nowrap"
|
|
950
|
+
},
|
|
951
|
+
children
|
|
952
|
+
}
|
|
953
|
+
);
|
|
954
|
+
}
|
|
955
|
+
function MutationStrip({
|
|
956
|
+
mutations,
|
|
957
|
+
iter
|
|
958
|
+
}) {
|
|
959
|
+
const t = useLensTheme();
|
|
960
|
+
const [open, setOpen] = (0, import_react.useState)(false);
|
|
961
|
+
const fallbackReadSkill = mutations.systemPromptAdded ? void 0 : iter.toolCalls.find((tc) => tc.name === "read_skill");
|
|
962
|
+
const skillId = mutations.activatedSkillId || (fallbackReadSkill?.arguments?.id ?? "");
|
|
963
|
+
const skillBody = mutations.systemPromptAdded || fallbackReadSkill?.result || "";
|
|
964
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
965
|
+
"div",
|
|
966
|
+
{
|
|
967
|
+
style: {
|
|
968
|
+
display: "flex",
|
|
969
|
+
flexDirection: "column",
|
|
970
|
+
gap: 6,
|
|
971
|
+
paddingLeft: 12,
|
|
972
|
+
fontSize: 11,
|
|
973
|
+
color: t.textMuted,
|
|
974
|
+
fontFamily: t.fontSans
|
|
975
|
+
},
|
|
976
|
+
children: [
|
|
977
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
978
|
+
"button",
|
|
979
|
+
{
|
|
980
|
+
onClick: () => setOpen((v) => !v),
|
|
981
|
+
style: {
|
|
982
|
+
display: "flex",
|
|
983
|
+
flexWrap: "wrap",
|
|
984
|
+
alignItems: "center",
|
|
985
|
+
gap: 6,
|
|
986
|
+
background: "transparent",
|
|
987
|
+
border: "none",
|
|
988
|
+
padding: 0,
|
|
989
|
+
margin: 0,
|
|
990
|
+
cursor: "pointer",
|
|
991
|
+
color: "inherit",
|
|
992
|
+
font: "inherit",
|
|
993
|
+
width: "auto",
|
|
994
|
+
textAlign: "left"
|
|
995
|
+
},
|
|
996
|
+
title: "Click to see the actual diff",
|
|
997
|
+
children: [
|
|
998
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { fontSize: 10, color: t.textSubtle }, children: open ? "\u25BE" : "\u25B8" }),
|
|
999
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1000
|
+
"span",
|
|
1001
|
+
{
|
|
1002
|
+
style: {
|
|
1003
|
+
fontWeight: 700,
|
|
1004
|
+
color: t.accent,
|
|
1005
|
+
textTransform: "uppercase",
|
|
1006
|
+
letterSpacing: "0.06em",
|
|
1007
|
+
fontSize: 10
|
|
1008
|
+
},
|
|
1009
|
+
children: "\u270E Changed"
|
|
1010
|
+
}
|
|
1011
|
+
),
|
|
1012
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: "in Neo's input:" }),
|
|
1013
|
+
mutations.systemPrompt && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1014
|
+
"span",
|
|
1015
|
+
{
|
|
1016
|
+
style: {
|
|
1017
|
+
padding: "1px 7px",
|
|
1018
|
+
borderRadius: 3,
|
|
1019
|
+
background: `color-mix(in srgb, ${t.accent} 18%, transparent)`,
|
|
1020
|
+
color: t.accent,
|
|
1021
|
+
fontWeight: 600,
|
|
1022
|
+
letterSpacing: "0.02em"
|
|
1023
|
+
},
|
|
1024
|
+
children: [
|
|
1025
|
+
"System Prompt",
|
|
1026
|
+
mutations.systemPromptDeltaChars > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: { fontWeight: 400, marginLeft: 4 }, children: [
|
|
1027
|
+
"+",
|
|
1028
|
+
mutations.systemPromptDeltaChars.toLocaleString(),
|
|
1029
|
+
" chars"
|
|
1030
|
+
] })
|
|
1031
|
+
]
|
|
1032
|
+
}
|
|
1033
|
+
),
|
|
1034
|
+
mutations.tools && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1035
|
+
"span",
|
|
1036
|
+
{
|
|
1037
|
+
style: {
|
|
1038
|
+
padding: "1px 7px",
|
|
1039
|
+
borderRadius: 3,
|
|
1040
|
+
background: `color-mix(in srgb, ${t.accent} 18%, transparent)`,
|
|
1041
|
+
color: t.accent,
|
|
1042
|
+
fontWeight: 600,
|
|
1043
|
+
letterSpacing: "0.02em"
|
|
1044
|
+
},
|
|
1045
|
+
children: [
|
|
1046
|
+
"Tools",
|
|
1047
|
+
(mutations.toolsAdded > 0 || mutations.toolsRemoved > 0) && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: { fontWeight: 400, marginLeft: 4 }, children: [
|
|
1048
|
+
mutations.toolsAdded > 0 ? `+${mutations.toolsAdded}` : "",
|
|
1049
|
+
mutations.toolsRemoved > 0 ? ` -${mutations.toolsRemoved}` : ""
|
|
1050
|
+
] })
|
|
1051
|
+
]
|
|
1052
|
+
}
|
|
1053
|
+
)
|
|
1054
|
+
]
|
|
1055
|
+
}
|
|
1056
|
+
),
|
|
1057
|
+
open && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1058
|
+
MutationDiffModal,
|
|
1059
|
+
{
|
|
1060
|
+
mutations,
|
|
1061
|
+
skillId,
|
|
1062
|
+
skillBody,
|
|
1063
|
+
visibleTools: iter.visibleTools,
|
|
1064
|
+
onClose: () => setOpen(false)
|
|
1065
|
+
}
|
|
1066
|
+
)
|
|
1067
|
+
]
|
|
1068
|
+
}
|
|
1069
|
+
);
|
|
1070
|
+
}
|
|
1071
|
+
function MutationDiffModal({
|
|
1072
|
+
mutations,
|
|
1073
|
+
skillId,
|
|
1074
|
+
skillBody,
|
|
1075
|
+
visibleTools,
|
|
1076
|
+
onClose
|
|
1077
|
+
}) {
|
|
1078
|
+
const t = useLensTheme();
|
|
1079
|
+
(0, import_react.useEffect)(() => {
|
|
1080
|
+
const onKey = (e) => {
|
|
1081
|
+
if (e.key === "Escape") onClose();
|
|
1082
|
+
};
|
|
1083
|
+
window.addEventListener("keydown", onKey);
|
|
1084
|
+
return () => window.removeEventListener("keydown", onKey);
|
|
1085
|
+
}, [onClose]);
|
|
1086
|
+
const toolsToShow = mutations.toolsAddedList.length > 0 ? mutations.toolsAddedList : visibleTools;
|
|
1087
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1088
|
+
"div",
|
|
1089
|
+
{
|
|
1090
|
+
onClick: onClose,
|
|
1091
|
+
role: "dialog",
|
|
1092
|
+
"aria-modal": "true",
|
|
1093
|
+
style: {
|
|
1094
|
+
position: "fixed",
|
|
1095
|
+
inset: 0,
|
|
1096
|
+
background: "rgba(0, 0, 0, 0.55)",
|
|
1097
|
+
backdropFilter: "blur(4px)",
|
|
1098
|
+
WebkitBackdropFilter: "blur(4px)",
|
|
1099
|
+
display: "flex",
|
|
1100
|
+
alignItems: "center",
|
|
1101
|
+
justifyContent: "center",
|
|
1102
|
+
zIndex: 1e3,
|
|
1103
|
+
padding: 24
|
|
1104
|
+
},
|
|
1105
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1106
|
+
"div",
|
|
1107
|
+
{
|
|
1108
|
+
onClick: (e) => e.stopPropagation(),
|
|
1109
|
+
style: {
|
|
1110
|
+
background: t.bg,
|
|
1111
|
+
color: t.text,
|
|
1112
|
+
border: `1px solid ${t.border}`,
|
|
1113
|
+
borderRadius: 12,
|
|
1114
|
+
boxShadow: "0 24px 64px rgba(0, 0, 0, 0.45)",
|
|
1115
|
+
width: "min(880px, 100%)",
|
|
1116
|
+
maxHeight: "min(80dvh, 800px)",
|
|
1117
|
+
display: "flex",
|
|
1118
|
+
flexDirection: "column",
|
|
1119
|
+
fontFamily: t.fontSans
|
|
1120
|
+
},
|
|
1121
|
+
children: [
|
|
1122
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1123
|
+
"div",
|
|
1124
|
+
{
|
|
1125
|
+
style: {
|
|
1126
|
+
display: "flex",
|
|
1127
|
+
alignItems: "center",
|
|
1128
|
+
padding: "14px 18px",
|
|
1129
|
+
borderBottom: `1px solid ${t.border}`
|
|
1130
|
+
},
|
|
1131
|
+
children: [
|
|
1132
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
|
|
1133
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1134
|
+
"div",
|
|
1135
|
+
{
|
|
1136
|
+
style: {
|
|
1137
|
+
fontSize: 10,
|
|
1138
|
+
color: t.textSubtle,
|
|
1139
|
+
textTransform: "uppercase",
|
|
1140
|
+
letterSpacing: "0.08em",
|
|
1141
|
+
fontWeight: 600
|
|
1142
|
+
},
|
|
1143
|
+
children: "\u270E Changed in Neo's input"
|
|
1144
|
+
}
|
|
1145
|
+
),
|
|
1146
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { fontSize: 15, fontWeight: 600, marginTop: 2 }, children: [
|
|
1147
|
+
"Round diff",
|
|
1148
|
+
skillId && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
1149
|
+
" \xB7 ",
|
|
1150
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1151
|
+
"code",
|
|
1152
|
+
{
|
|
1153
|
+
style: {
|
|
1154
|
+
fontFamily: t.fontMono,
|
|
1155
|
+
color: t.accent,
|
|
1156
|
+
fontWeight: 600
|
|
1157
|
+
},
|
|
1158
|
+
children: skillId
|
|
1159
|
+
}
|
|
1160
|
+
)
|
|
1161
|
+
] })
|
|
1162
|
+
] })
|
|
1163
|
+
] }),
|
|
1164
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { flex: 1 } }),
|
|
1165
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1166
|
+
"button",
|
|
1167
|
+
{
|
|
1168
|
+
onClick: onClose,
|
|
1169
|
+
title: "Close (Esc)",
|
|
1170
|
+
style: {
|
|
1171
|
+
background: "transparent",
|
|
1172
|
+
border: `1px solid ${t.border}`,
|
|
1173
|
+
color: t.textMuted,
|
|
1174
|
+
padding: "4px 10px",
|
|
1175
|
+
borderRadius: 6,
|
|
1176
|
+
cursor: "pointer",
|
|
1177
|
+
fontSize: 12,
|
|
1178
|
+
width: "auto"
|
|
1179
|
+
},
|
|
1180
|
+
children: "Esc"
|
|
1181
|
+
}
|
|
1182
|
+
)
|
|
1183
|
+
]
|
|
1184
|
+
}
|
|
1185
|
+
),
|
|
1186
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1187
|
+
"div",
|
|
1188
|
+
{
|
|
1189
|
+
style: {
|
|
1190
|
+
padding: 18,
|
|
1191
|
+
overflow: "auto",
|
|
1192
|
+
display: "flex",
|
|
1193
|
+
flexDirection: "column",
|
|
1194
|
+
gap: 16
|
|
1195
|
+
},
|
|
1196
|
+
children: [
|
|
1197
|
+
mutations.systemPrompt && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { children: [
|
|
1198
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1199
|
+
"div",
|
|
1200
|
+
{
|
|
1201
|
+
style: {
|
|
1202
|
+
fontSize: 11,
|
|
1203
|
+
color: t.textSubtle,
|
|
1204
|
+
textTransform: "uppercase",
|
|
1205
|
+
letterSpacing: "0.08em",
|
|
1206
|
+
fontWeight: 600,
|
|
1207
|
+
marginBottom: 8
|
|
1208
|
+
},
|
|
1209
|
+
children: [
|
|
1210
|
+
"System Prompt",
|
|
1211
|
+
mutations.systemPromptDeltaChars > 0 && ` \xB7 +${mutations.systemPromptDeltaChars.toLocaleString()} chars`
|
|
1212
|
+
]
|
|
1213
|
+
}
|
|
1214
|
+
),
|
|
1215
|
+
skillBody ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1216
|
+
"pre",
|
|
1217
|
+
{
|
|
1218
|
+
style: {
|
|
1219
|
+
margin: 0,
|
|
1220
|
+
padding: "12px 14px",
|
|
1221
|
+
background: t.bgElev,
|
|
1222
|
+
border: `1px solid ${t.border}`,
|
|
1223
|
+
borderLeft: `3px solid ${t.accent}`,
|
|
1224
|
+
borderRadius: 6,
|
|
1225
|
+
fontSize: 12,
|
|
1226
|
+
lineHeight: 1.55,
|
|
1227
|
+
fontFamily: t.fontMono,
|
|
1228
|
+
color: t.text,
|
|
1229
|
+
whiteSpace: "pre-wrap"
|
|
1230
|
+
},
|
|
1231
|
+
children: skillBody
|
|
1232
|
+
}
|
|
1233
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1234
|
+
"div",
|
|
1235
|
+
{
|
|
1236
|
+
style: {
|
|
1237
|
+
padding: "10px 12px",
|
|
1238
|
+
border: `1px dashed ${t.border}`,
|
|
1239
|
+
borderRadius: 6,
|
|
1240
|
+
color: t.textSubtle,
|
|
1241
|
+
fontStyle: "italic",
|
|
1242
|
+
fontSize: 12
|
|
1243
|
+
},
|
|
1244
|
+
children: [
|
|
1245
|
+
"System Prompt grew by ",
|
|
1246
|
+
mutations.systemPromptDeltaChars.toLocaleString(),
|
|
1247
|
+
" ",
|
|
1248
|
+
"chars but the source text isn't flowing through the adapter for this round."
|
|
1249
|
+
]
|
|
1250
|
+
}
|
|
1251
|
+
)
|
|
1252
|
+
] }),
|
|
1253
|
+
mutations.tools && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { children: [
|
|
1254
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1255
|
+
"div",
|
|
1256
|
+
{
|
|
1257
|
+
style: {
|
|
1258
|
+
fontSize: 11,
|
|
1259
|
+
color: t.textSubtle,
|
|
1260
|
+
textTransform: "uppercase",
|
|
1261
|
+
letterSpacing: "0.08em",
|
|
1262
|
+
fontWeight: 600,
|
|
1263
|
+
marginBottom: 8
|
|
1264
|
+
},
|
|
1265
|
+
children: [
|
|
1266
|
+
"Tools",
|
|
1267
|
+
mutations.toolsAdded > 0 && ` \xB7 +${mutations.toolsAdded} added`,
|
|
1268
|
+
mutations.toolsRemoved > 0 && ` \xB7 -${mutations.toolsRemoved} removed`
|
|
1269
|
+
]
|
|
1270
|
+
}
|
|
1271
|
+
),
|
|
1272
|
+
toolsToShow.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { display: "flex", flexWrap: "wrap", gap: 6 }, children: toolsToShow.map((name) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1273
|
+
"span",
|
|
1274
|
+
{
|
|
1275
|
+
style: {
|
|
1276
|
+
padding: "3px 9px",
|
|
1277
|
+
borderRadius: 4,
|
|
1278
|
+
background: t.bgElev,
|
|
1279
|
+
border: `1px solid ${t.border}`,
|
|
1280
|
+
color: t.text,
|
|
1281
|
+
fontFamily: t.fontMono,
|
|
1282
|
+
fontSize: 11
|
|
1283
|
+
},
|
|
1284
|
+
children: name
|
|
1285
|
+
},
|
|
1286
|
+
name
|
|
1287
|
+
)) }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1288
|
+
"div",
|
|
1289
|
+
{
|
|
1290
|
+
style: {
|
|
1291
|
+
padding: "10px 12px",
|
|
1292
|
+
border: `1px dashed ${t.border}`,
|
|
1293
|
+
borderRadius: 6,
|
|
1294
|
+
color: t.textSubtle,
|
|
1295
|
+
fontStyle: "italic",
|
|
1296
|
+
fontSize: 12
|
|
1297
|
+
},
|
|
1298
|
+
children: "The tool list that came online in this round isn't flowing through the adapter yet \u2014 counts are available, names aren't."
|
|
1299
|
+
}
|
|
1300
|
+
)
|
|
1301
|
+
] })
|
|
1302
|
+
]
|
|
1303
|
+
}
|
|
1304
|
+
)
|
|
1305
|
+
]
|
|
1306
|
+
}
|
|
1307
|
+
)
|
|
1308
|
+
}
|
|
1309
|
+
);
|
|
1310
|
+
}
|
|
596
1311
|
function ContextDrawer({
|
|
597
1312
|
messagesSentCount,
|
|
598
1313
|
contextMessages,
|
|
@@ -679,19 +1394,21 @@ function summarizeMessage(m) {
|
|
|
679
1394
|
}
|
|
680
1395
|
function ToolCallCard({
|
|
681
1396
|
invocation,
|
|
682
|
-
onClick
|
|
1397
|
+
onClick,
|
|
1398
|
+
resultRevealed = true
|
|
683
1399
|
}) {
|
|
684
1400
|
const t = useLensTheme();
|
|
685
1401
|
const [open, setOpen] = (0, import_react.useState)(false);
|
|
686
1402
|
const preview = shortArgs(invocation.arguments);
|
|
687
1403
|
const errored = invocation.error === true;
|
|
688
1404
|
const friendlyVerb = toolVerb(invocation);
|
|
1405
|
+
const borderStyle = resultRevealed ? "solid" : "dashed";
|
|
689
1406
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
690
1407
|
"div",
|
|
691
1408
|
{
|
|
692
1409
|
style: {
|
|
693
|
-
border: `1px
|
|
694
|
-
borderLeft: `3px
|
|
1410
|
+
border: `1px ${borderStyle} ${errored ? t.error : t.border}`,
|
|
1411
|
+
borderLeft: `3px ${borderStyle} ${errored ? t.error : t.accent}`,
|
|
695
1412
|
borderRadius: 6,
|
|
696
1413
|
background: t.bg,
|
|
697
1414
|
overflow: "hidden"
|
|
@@ -721,6 +1438,23 @@ function ToolCallCard({
|
|
|
721
1438
|
")"
|
|
722
1439
|
] }),
|
|
723
1440
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { flex: 1 } }),
|
|
1441
|
+
!resultRevealed && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1442
|
+
"span",
|
|
1443
|
+
{
|
|
1444
|
+
style: {
|
|
1445
|
+
fontSize: 10,
|
|
1446
|
+
padding: "1px 6px",
|
|
1447
|
+
borderRadius: 3,
|
|
1448
|
+
background: `color-mix(in srgb, ${t.accent} 18%, transparent)`,
|
|
1449
|
+
color: t.accent,
|
|
1450
|
+
fontWeight: 600,
|
|
1451
|
+
textTransform: "uppercase",
|
|
1452
|
+
letterSpacing: "0.04em"
|
|
1453
|
+
},
|
|
1454
|
+
title: "Args sent; waiting for the tool to return",
|
|
1455
|
+
children: "in flight"
|
|
1456
|
+
}
|
|
1457
|
+
),
|
|
724
1458
|
invocation.decisionUpdate && Object.keys(invocation.decisionUpdate).length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
725
1459
|
"span",
|
|
726
1460
|
{
|
|
@@ -744,7 +1478,7 @@ function ToolCallCard({
|
|
|
744
1478
|
open && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { padding: "8px 12px", borderTop: `1px solid ${t.border}` }, children: [
|
|
745
1479
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Label, { t, children: "What Neo asked for" }),
|
|
746
1480
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(JsonBlock, { value: invocation.arguments }),
|
|
747
|
-
invocation.result && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
1481
|
+
resultRevealed && invocation.result && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
748
1482
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Label, { t, style: { marginTop: 10 }, children: "What the tool returned" }),
|
|
749
1483
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
750
1484
|
"pre",
|
|
@@ -765,7 +1499,22 @@ function ToolCallCard({
|
|
|
765
1499
|
}
|
|
766
1500
|
)
|
|
767
1501
|
] }),
|
|
768
|
-
|
|
1502
|
+
!resultRevealed && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1503
|
+
"div",
|
|
1504
|
+
{
|
|
1505
|
+
style: {
|
|
1506
|
+
marginTop: 10,
|
|
1507
|
+
padding: "10px 12px",
|
|
1508
|
+
border: `1px dashed ${t.border}`,
|
|
1509
|
+
borderRadius: 4,
|
|
1510
|
+
fontSize: 12,
|
|
1511
|
+
color: t.textSubtle,
|
|
1512
|
+
fontStyle: "italic"
|
|
1513
|
+
},
|
|
1514
|
+
children: "Neo has sent the args; advance the slider to see the result this tool returned."
|
|
1515
|
+
}
|
|
1516
|
+
),
|
|
1517
|
+
resultRevealed && invocation.decisionUpdate && Object.keys(invocation.decisionUpdate).length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
769
1518
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Label, { t, style: { marginTop: 10 }, children: "What changed in Neo's state" }),
|
|
770
1519
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(JsonBlock, { value: invocation.decisionUpdate })
|
|
771
1520
|
] })
|
|
@@ -777,7 +1526,8 @@ function ToolCallCard({
|
|
|
777
1526
|
function toolVerb(inv) {
|
|
778
1527
|
if (inv.name === "list_skills") return "Asked for";
|
|
779
1528
|
if (inv.name === "read_skill") return "Activated";
|
|
780
|
-
return "
|
|
1529
|
+
if (inv.name === "ask_human" || inv.name === "ask_user") return "Asked user for";
|
|
1530
|
+
return "Called tool";
|
|
781
1531
|
}
|
|
782
1532
|
function Label({
|
|
783
1533
|
t,
|
|
@@ -829,10 +1579,1985 @@ function shortArgs(args) {
|
|
|
829
1579
|
}
|
|
830
1580
|
return keys.join(", ");
|
|
831
1581
|
}
|
|
1582
|
+
function useIterationStageRanges(stages) {
|
|
1583
|
+
return import_react.default.useMemo(() => {
|
|
1584
|
+
const map = /* @__PURE__ */ new Map();
|
|
1585
|
+
if (!stages?.length) return map;
|
|
1586
|
+
const turnIters = /* @__PURE__ */ new Map();
|
|
1587
|
+
for (const s of stages) {
|
|
1588
|
+
if (s.iterIndex === void 0) continue;
|
|
1589
|
+
const list = turnIters.get(s.turnIndex) ?? [];
|
|
1590
|
+
if (!list.includes(s.iterIndex)) list.push(s.iterIndex);
|
|
1591
|
+
turnIters.set(s.turnIndex, list);
|
|
1592
|
+
}
|
|
1593
|
+
stages.forEach((s, idx) => {
|
|
1594
|
+
let iter = s.iterIndex;
|
|
1595
|
+
if (iter === void 0) {
|
|
1596
|
+
const iters = turnIters.get(s.turnIndex);
|
|
1597
|
+
if (!iters?.length) return;
|
|
1598
|
+
iter = s.from === "user" ? iters[0] : iters[iters.length - 1];
|
|
1599
|
+
}
|
|
1600
|
+
const key = `${s.turnIndex}.${iter}`;
|
|
1601
|
+
const prev = map.get(key);
|
|
1602
|
+
if (!prev) {
|
|
1603
|
+
map.set(key, { firstStageIndex: idx, lastStageIndex: idx });
|
|
1604
|
+
} else {
|
|
1605
|
+
map.set(key, {
|
|
1606
|
+
firstStageIndex: Math.min(prev.firstStageIndex, idx),
|
|
1607
|
+
lastStageIndex: Math.max(prev.lastStageIndex, idx)
|
|
1608
|
+
});
|
|
1609
|
+
}
|
|
1610
|
+
});
|
|
1611
|
+
return map;
|
|
1612
|
+
}, [stages]);
|
|
1613
|
+
}
|
|
1614
|
+
function keyForStage(ranges, focusIndex) {
|
|
1615
|
+
for (const [key, r] of ranges) {
|
|
1616
|
+
if (focusIndex >= r.firstStageIndex && focusIndex <= r.lastStageIndex) return key;
|
|
1617
|
+
}
|
|
1618
|
+
return null;
|
|
1619
|
+
}
|
|
832
1620
|
|
|
833
|
-
// src/panels/
|
|
1621
|
+
// src/panels/SkillsPanel.tsx
|
|
1622
|
+
var import_react2 = require("react");
|
|
834
1623
|
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
835
|
-
function
|
|
1624
|
+
function SkillsPanel({ skills, onClose, activeSkillId }) {
|
|
1625
|
+
const t = useLensTheme();
|
|
1626
|
+
const [selectedId, setSelectedId] = (0, import_react2.useState)(
|
|
1627
|
+
activeSkillId ?? skills[0]?.id ?? null
|
|
1628
|
+
);
|
|
1629
|
+
const [mode, setMode] = (0, import_react2.useState)("formatted");
|
|
1630
|
+
const selected = skills.find((s) => s.id === selectedId) ?? null;
|
|
1631
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
1632
|
+
"div",
|
|
1633
|
+
{
|
|
1634
|
+
onClick: onClose,
|
|
1635
|
+
style: {
|
|
1636
|
+
position: "absolute",
|
|
1637
|
+
inset: 0,
|
|
1638
|
+
background: "rgba(0, 0, 0, 0.5)",
|
|
1639
|
+
zIndex: 100,
|
|
1640
|
+
display: "flex",
|
|
1641
|
+
alignItems: "stretch",
|
|
1642
|
+
justifyContent: "stretch"
|
|
1643
|
+
},
|
|
1644
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
1645
|
+
"div",
|
|
1646
|
+
{
|
|
1647
|
+
onClick: (e) => e.stopPropagation(),
|
|
1648
|
+
style: {
|
|
1649
|
+
display: "grid",
|
|
1650
|
+
gridTemplateColumns: "minmax(220px, 280px) 1fr",
|
|
1651
|
+
gridTemplateRows: "auto 1fr",
|
|
1652
|
+
gridTemplateAreas: '"header header" "list detail"',
|
|
1653
|
+
width: "100%",
|
|
1654
|
+
height: "100%",
|
|
1655
|
+
background: t.bg,
|
|
1656
|
+
color: t.text,
|
|
1657
|
+
fontFamily: t.fontSans,
|
|
1658
|
+
border: `1px solid ${t.border}`
|
|
1659
|
+
},
|
|
1660
|
+
children: [
|
|
1661
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
1662
|
+
"div",
|
|
1663
|
+
{
|
|
1664
|
+
style: {
|
|
1665
|
+
gridArea: "header",
|
|
1666
|
+
padding: "10px 14px",
|
|
1667
|
+
borderBottom: `1px solid ${t.border}`,
|
|
1668
|
+
background: t.bgElev,
|
|
1669
|
+
display: "flex",
|
|
1670
|
+
alignItems: "center",
|
|
1671
|
+
gap: 10
|
|
1672
|
+
},
|
|
1673
|
+
children: [
|
|
1674
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("strong", { style: { color: t.text, fontSize: 13 }, children: "Skills registered with Neo" }),
|
|
1675
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { style: { color: t.textMuted, fontSize: 12 }, children: [
|
|
1676
|
+
skills.length,
|
|
1677
|
+
" total"
|
|
1678
|
+
] }),
|
|
1679
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { flex: 1 } }),
|
|
1680
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
1681
|
+
"button",
|
|
1682
|
+
{
|
|
1683
|
+
onClick: onClose,
|
|
1684
|
+
style: {
|
|
1685
|
+
background: "transparent",
|
|
1686
|
+
border: `1px solid ${t.border}`,
|
|
1687
|
+
color: t.textMuted,
|
|
1688
|
+
borderRadius: 4,
|
|
1689
|
+
padding: "2px 10px",
|
|
1690
|
+
cursor: "pointer",
|
|
1691
|
+
fontSize: 14,
|
|
1692
|
+
width: "auto",
|
|
1693
|
+
fontWeight: 400
|
|
1694
|
+
},
|
|
1695
|
+
title: "Close (Esc)",
|
|
1696
|
+
children: "\u2715"
|
|
1697
|
+
}
|
|
1698
|
+
)
|
|
1699
|
+
]
|
|
1700
|
+
}
|
|
1701
|
+
),
|
|
1702
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
1703
|
+
"div",
|
|
1704
|
+
{
|
|
1705
|
+
style: {
|
|
1706
|
+
gridArea: "list",
|
|
1707
|
+
borderRight: `1px solid ${t.border}`,
|
|
1708
|
+
overflow: "auto",
|
|
1709
|
+
background: t.bg
|
|
1710
|
+
},
|
|
1711
|
+
children: [
|
|
1712
|
+
skills.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { padding: 14, color: t.textSubtle, fontSize: 12 }, children: "No skills registered." }),
|
|
1713
|
+
skills.map((s) => {
|
|
1714
|
+
const isActive = s.id === selectedId;
|
|
1715
|
+
const isAgentActive = s.id === activeSkillId;
|
|
1716
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
1717
|
+
"button",
|
|
1718
|
+
{
|
|
1719
|
+
onClick: () => setSelectedId(s.id),
|
|
1720
|
+
style: {
|
|
1721
|
+
display: "block",
|
|
1722
|
+
width: "100%",
|
|
1723
|
+
textAlign: "left",
|
|
1724
|
+
padding: "10px 14px",
|
|
1725
|
+
background: isActive ? t.bgHover : "transparent",
|
|
1726
|
+
border: "none",
|
|
1727
|
+
borderLeft: `3px solid ${isActive ? t.accent : isAgentActive ? t.success : "transparent"}`,
|
|
1728
|
+
borderBottom: `1px solid ${t.border}`,
|
|
1729
|
+
color: t.text,
|
|
1730
|
+
cursor: "pointer",
|
|
1731
|
+
fontFamily: "inherit"
|
|
1732
|
+
},
|
|
1733
|
+
children: [
|
|
1734
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
1735
|
+
"div",
|
|
1736
|
+
{
|
|
1737
|
+
style: {
|
|
1738
|
+
display: "flex",
|
|
1739
|
+
alignItems: "baseline",
|
|
1740
|
+
gap: 6,
|
|
1741
|
+
fontSize: 13
|
|
1742
|
+
},
|
|
1743
|
+
children: [
|
|
1744
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { fontWeight: 600 }, children: s.title ?? s.id }),
|
|
1745
|
+
isAgentActive && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
1746
|
+
"span",
|
|
1747
|
+
{
|
|
1748
|
+
style: {
|
|
1749
|
+
fontSize: 9,
|
|
1750
|
+
padding: "1px 5px",
|
|
1751
|
+
borderRadius: 3,
|
|
1752
|
+
background: `color-mix(in srgb, ${t.success} 25%, transparent)`,
|
|
1753
|
+
color: t.success,
|
|
1754
|
+
fontWeight: 600,
|
|
1755
|
+
textTransform: "uppercase"
|
|
1756
|
+
},
|
|
1757
|
+
children: "active"
|
|
1758
|
+
}
|
|
1759
|
+
)
|
|
1760
|
+
]
|
|
1761
|
+
}
|
|
1762
|
+
),
|
|
1763
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
1764
|
+
"div",
|
|
1765
|
+
{
|
|
1766
|
+
style: {
|
|
1767
|
+
fontSize: 10,
|
|
1768
|
+
color: t.textSubtle,
|
|
1769
|
+
fontFamily: t.fontMono,
|
|
1770
|
+
marginTop: 1
|
|
1771
|
+
},
|
|
1772
|
+
children: [
|
|
1773
|
+
s.id,
|
|
1774
|
+
s.version && ` \xB7 v${s.version}`
|
|
1775
|
+
]
|
|
1776
|
+
}
|
|
1777
|
+
),
|
|
1778
|
+
s.description && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
1779
|
+
"div",
|
|
1780
|
+
{
|
|
1781
|
+
style: {
|
|
1782
|
+
fontSize: 11,
|
|
1783
|
+
color: t.textMuted,
|
|
1784
|
+
marginTop: 4,
|
|
1785
|
+
lineHeight: 1.4,
|
|
1786
|
+
display: "-webkit-box",
|
|
1787
|
+
WebkitLineClamp: 3,
|
|
1788
|
+
WebkitBoxOrient: "vertical",
|
|
1789
|
+
overflow: "hidden"
|
|
1790
|
+
},
|
|
1791
|
+
children: s.description
|
|
1792
|
+
}
|
|
1793
|
+
)
|
|
1794
|
+
]
|
|
1795
|
+
},
|
|
1796
|
+
s.id
|
|
1797
|
+
);
|
|
1798
|
+
})
|
|
1799
|
+
]
|
|
1800
|
+
}
|
|
1801
|
+
),
|
|
1802
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
1803
|
+
"div",
|
|
1804
|
+
{
|
|
1805
|
+
style: {
|
|
1806
|
+
gridArea: "detail",
|
|
1807
|
+
overflow: "auto",
|
|
1808
|
+
padding: "14px 18px",
|
|
1809
|
+
fontSize: 13,
|
|
1810
|
+
lineHeight: 1.6
|
|
1811
|
+
},
|
|
1812
|
+
children: !selected ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { color: t.textSubtle }, children: "Select a skill to see details." }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
|
|
1813
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { display: "flex", alignItems: "baseline", gap: 10, marginBottom: 10 }, children: [
|
|
1814
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h2", { style: { margin: 0, fontSize: 18, color: t.text }, children: selected.title ?? selected.id }),
|
|
1815
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { style: { color: t.textSubtle, fontFamily: t.fontMono, fontSize: 11 }, children: [
|
|
1816
|
+
selected.id,
|
|
1817
|
+
selected.version && ` \xB7 v${selected.version}`
|
|
1818
|
+
] }),
|
|
1819
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { flex: 1 } }),
|
|
1820
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
1821
|
+
"div",
|
|
1822
|
+
{
|
|
1823
|
+
role: "tablist",
|
|
1824
|
+
style: {
|
|
1825
|
+
display: "flex",
|
|
1826
|
+
gap: 1,
|
|
1827
|
+
border: `1px solid ${t.border}`,
|
|
1828
|
+
borderRadius: 4,
|
|
1829
|
+
overflow: "hidden"
|
|
1830
|
+
},
|
|
1831
|
+
children: [
|
|
1832
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
1833
|
+
"button",
|
|
1834
|
+
{
|
|
1835
|
+
onClick: () => setMode("formatted"),
|
|
1836
|
+
style: {
|
|
1837
|
+
padding: "3px 10px",
|
|
1838
|
+
fontSize: 11,
|
|
1839
|
+
background: mode === "formatted" ? t.accent : "transparent",
|
|
1840
|
+
color: mode === "formatted" ? "#fff" : t.textMuted,
|
|
1841
|
+
border: "none",
|
|
1842
|
+
cursor: "pointer",
|
|
1843
|
+
width: "auto",
|
|
1844
|
+
fontWeight: 400
|
|
1845
|
+
},
|
|
1846
|
+
children: "Formatted"
|
|
1847
|
+
}
|
|
1848
|
+
),
|
|
1849
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
1850
|
+
"button",
|
|
1851
|
+
{
|
|
1852
|
+
onClick: () => setMode("json"),
|
|
1853
|
+
style: {
|
|
1854
|
+
padding: "3px 10px",
|
|
1855
|
+
fontSize: 11,
|
|
1856
|
+
background: mode === "json" ? t.accent : "transparent",
|
|
1857
|
+
color: mode === "json" ? "#fff" : t.textMuted,
|
|
1858
|
+
border: "none",
|
|
1859
|
+
cursor: "pointer",
|
|
1860
|
+
width: "auto",
|
|
1861
|
+
fontWeight: 400
|
|
1862
|
+
},
|
|
1863
|
+
children: "Raw JSON"
|
|
1864
|
+
}
|
|
1865
|
+
)
|
|
1866
|
+
]
|
|
1867
|
+
}
|
|
1868
|
+
)
|
|
1869
|
+
] }),
|
|
1870
|
+
mode === "formatted" ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(SkillFormatted, { skill: selected }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(SkillJson, { skill: selected })
|
|
1871
|
+
] })
|
|
1872
|
+
}
|
|
1873
|
+
)
|
|
1874
|
+
]
|
|
1875
|
+
}
|
|
1876
|
+
)
|
|
1877
|
+
}
|
|
1878
|
+
);
|
|
1879
|
+
}
|
|
1880
|
+
function SkillFormatted({ skill }) {
|
|
1881
|
+
const t = useLensTheme();
|
|
1882
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 12 }, children: [
|
|
1883
|
+
skill.description && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("section", { children: [
|
|
1884
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Label2, { t, children: "Description" }),
|
|
1885
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { color: t.text }, children: skill.description })
|
|
1886
|
+
] }),
|
|
1887
|
+
skill.scope && skill.scope.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("section", { children: [
|
|
1888
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Label2, { t, children: "Scope" }),
|
|
1889
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { display: "flex", gap: 6, flexWrap: "wrap" }, children: skill.scope.map((s) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
1890
|
+
"span",
|
|
1891
|
+
{
|
|
1892
|
+
style: {
|
|
1893
|
+
padding: "2px 8px",
|
|
1894
|
+
background: t.bgElev,
|
|
1895
|
+
border: `1px solid ${t.border}`,
|
|
1896
|
+
borderRadius: 3,
|
|
1897
|
+
fontSize: 11,
|
|
1898
|
+
fontFamily: t.fontMono,
|
|
1899
|
+
color: t.textMuted
|
|
1900
|
+
},
|
|
1901
|
+
children: s
|
|
1902
|
+
},
|
|
1903
|
+
s
|
|
1904
|
+
)) })
|
|
1905
|
+
] }),
|
|
1906
|
+
skill.tools && skill.tools.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("section", { children: [
|
|
1907
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Label2, { t, children: [
|
|
1908
|
+
"Tools this skill exposes \xB7 ",
|
|
1909
|
+
skill.tools.length
|
|
1910
|
+
] }),
|
|
1911
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { display: "flex", gap: 6, flexWrap: "wrap" }, children: skill.tools.map((id) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
1912
|
+
"span",
|
|
1913
|
+
{
|
|
1914
|
+
style: {
|
|
1915
|
+
padding: "2px 8px",
|
|
1916
|
+
background: `color-mix(in srgb, ${t.accent} 15%, transparent)`,
|
|
1917
|
+
border: `1px solid ${t.border}`,
|
|
1918
|
+
borderRadius: 3,
|
|
1919
|
+
fontSize: 11,
|
|
1920
|
+
fontFamily: t.fontMono,
|
|
1921
|
+
color: t.accent
|
|
1922
|
+
},
|
|
1923
|
+
children: id
|
|
1924
|
+
},
|
|
1925
|
+
id
|
|
1926
|
+
)) }),
|
|
1927
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { fontSize: 11, color: t.textSubtle, marginTop: 4, fontStyle: "italic" }, children: "Only these tools reach the LLM while this skill is active (autoActivate)." })
|
|
1928
|
+
] }),
|
|
1929
|
+
skill.body && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("section", { children: [
|
|
1930
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Label2, { t, children: "Body (sent to LLM on read_skill)" }),
|
|
1931
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
1932
|
+
"pre",
|
|
1933
|
+
{
|
|
1934
|
+
style: {
|
|
1935
|
+
margin: 0,
|
|
1936
|
+
padding: "10px 12px",
|
|
1937
|
+
background: t.bgElev,
|
|
1938
|
+
border: `1px solid ${t.border}`,
|
|
1939
|
+
borderRadius: 4,
|
|
1940
|
+
fontSize: 12,
|
|
1941
|
+
lineHeight: 1.55,
|
|
1942
|
+
fontFamily: t.fontMono,
|
|
1943
|
+
whiteSpace: "pre-wrap",
|
|
1944
|
+
color: t.text,
|
|
1945
|
+
maxHeight: 480,
|
|
1946
|
+
overflow: "auto"
|
|
1947
|
+
},
|
|
1948
|
+
children: skill.body
|
|
1949
|
+
}
|
|
1950
|
+
)
|
|
1951
|
+
] })
|
|
1952
|
+
] });
|
|
1953
|
+
}
|
|
1954
|
+
function SkillJson({ skill }) {
|
|
1955
|
+
const t = useLensTheme();
|
|
1956
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
1957
|
+
"pre",
|
|
1958
|
+
{
|
|
1959
|
+
style: {
|
|
1960
|
+
margin: 0,
|
|
1961
|
+
padding: "10px 12px",
|
|
1962
|
+
background: t.bgElev,
|
|
1963
|
+
border: `1px solid ${t.border}`,
|
|
1964
|
+
borderRadius: 4,
|
|
1965
|
+
fontSize: 12,
|
|
1966
|
+
lineHeight: 1.55,
|
|
1967
|
+
fontFamily: t.fontMono,
|
|
1968
|
+
whiteSpace: "pre-wrap",
|
|
1969
|
+
color: t.text,
|
|
1970
|
+
maxHeight: "calc(100vh - 200px)",
|
|
1971
|
+
overflow: "auto"
|
|
1972
|
+
},
|
|
1973
|
+
children: safeJsonStringify(skill)
|
|
1974
|
+
}
|
|
1975
|
+
);
|
|
1976
|
+
}
|
|
1977
|
+
function safeJsonStringify(value) {
|
|
1978
|
+
const seen = /* @__PURE__ */ new WeakSet();
|
|
1979
|
+
try {
|
|
1980
|
+
return JSON.stringify(
|
|
1981
|
+
value,
|
|
1982
|
+
(_k, v) => {
|
|
1983
|
+
if (typeof v === "object" && v !== null) {
|
|
1984
|
+
if (seen.has(v)) return "[Circular]";
|
|
1985
|
+
seen.add(v);
|
|
1986
|
+
}
|
|
1987
|
+
if (typeof v === "function") return `[function ${v.name || "anonymous"}]`;
|
|
1988
|
+
return v;
|
|
1989
|
+
},
|
|
1990
|
+
2
|
|
1991
|
+
);
|
|
1992
|
+
} catch (err) {
|
|
1993
|
+
return `[stringify error: ${err instanceof Error ? err.message : String(err)}]`;
|
|
1994
|
+
}
|
|
1995
|
+
}
|
|
1996
|
+
function Label2({
|
|
1997
|
+
t,
|
|
1998
|
+
children
|
|
1999
|
+
}) {
|
|
2000
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
2001
|
+
"div",
|
|
2002
|
+
{
|
|
2003
|
+
style: {
|
|
2004
|
+
fontSize: 10,
|
|
2005
|
+
color: t.textSubtle,
|
|
2006
|
+
textTransform: "uppercase",
|
|
2007
|
+
letterSpacing: "0.08em",
|
|
2008
|
+
fontWeight: 600,
|
|
2009
|
+
marginBottom: 4
|
|
2010
|
+
},
|
|
2011
|
+
children
|
|
2012
|
+
}
|
|
2013
|
+
);
|
|
2014
|
+
}
|
|
2015
|
+
|
|
2016
|
+
// src/panels/StageFlow.tsx
|
|
2017
|
+
var import_react3 = require("react");
|
|
2018
|
+
var import_react4 = require("@xyflow/react");
|
|
2019
|
+
var import_style = require("@xyflow/react/dist/style.css");
|
|
2020
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
2021
|
+
var NODE_POSITIONS = {
|
|
2022
|
+
user: { x: 100, y: 20 },
|
|
2023
|
+
agent: { x: 100, y: 160 },
|
|
2024
|
+
tool: { x: 100, y: 380 },
|
|
2025
|
+
skill: { x: 320, y: 380 }
|
|
2026
|
+
};
|
|
2027
|
+
function pickHandles(from, to) {
|
|
2028
|
+
if (from === "user" && to === "agent") return { sourceHandle: "b-out", targetHandle: "t-in" };
|
|
2029
|
+
if (from === "agent" && to === "user") return { sourceHandle: "t-out", targetHandle: "b-in" };
|
|
2030
|
+
if (from === "agent" && to === "tool") return { sourceHandle: "b-out", targetHandle: "t-in" };
|
|
2031
|
+
if (from === "tool" && to === "agent") return { sourceHandle: "t-out", targetHandle: "b-in" };
|
|
2032
|
+
if (from === "agent" && to === "skill") return { sourceHandle: "r-out", targetHandle: "l-in" };
|
|
2033
|
+
if (from === "skill" && to === "agent") return { sourceHandle: "l-out", targetHandle: "r-in" };
|
|
2034
|
+
return { sourceHandle: "r-out", targetHandle: "l-in" };
|
|
2035
|
+
}
|
|
2036
|
+
var NODE_LABELS = {
|
|
2037
|
+
user: "User",
|
|
2038
|
+
agent: "Agent",
|
|
2039
|
+
tool: "Tool",
|
|
2040
|
+
skill: "Skill"
|
|
2041
|
+
};
|
|
2042
|
+
var NODE_SUBLABELS = {
|
|
2043
|
+
user: "You",
|
|
2044
|
+
agent: "The LLM",
|
|
2045
|
+
tool: "Data source / action",
|
|
2046
|
+
// "Adds context + tools" is what the user actually observes when a
|
|
2047
|
+
// skill activates — the skill body lands in System Prompt and its
|
|
2048
|
+
// tool list surfaces in Tools. That's the whole effect; no need for
|
|
2049
|
+
// jargon like "bracket over a primitive."
|
|
2050
|
+
skill: "Adds context + tools"
|
|
2051
|
+
};
|
|
2052
|
+
function StageFlow({
|
|
2053
|
+
stages,
|
|
2054
|
+
focusIndex,
|
|
2055
|
+
onEdgeClick,
|
|
2056
|
+
height = 460,
|
|
2057
|
+
activeSkillId
|
|
2058
|
+
}) {
|
|
2059
|
+
const t = useLensTheme();
|
|
2060
|
+
const focus = focusIndex !== void 0 && focusIndex >= 0 ? focusIndex : stages.length - 1;
|
|
2061
|
+
const visible = (0, import_react3.useMemo)(() => stages.slice(0, focus + 1), [stages, focus]);
|
|
2062
|
+
const activeStage = visible[visible.length - 1];
|
|
2063
|
+
const touched = (0, import_react3.useMemo)(() => {
|
|
2064
|
+
const set = /* @__PURE__ */ new Set();
|
|
2065
|
+
for (const s of visible) {
|
|
2066
|
+
set.add(s.from);
|
|
2067
|
+
set.add(s.to);
|
|
2068
|
+
if (s.alsoLights) set.add(s.alsoLights);
|
|
2069
|
+
}
|
|
2070
|
+
return set;
|
|
2071
|
+
}, [visible]);
|
|
2072
|
+
const activeNodes = (0, import_react3.useMemo)(() => {
|
|
2073
|
+
const s = /* @__PURE__ */ new Set();
|
|
2074
|
+
if (activeStage) {
|
|
2075
|
+
s.add(activeStage.to);
|
|
2076
|
+
if (activeStage.alsoLights) s.add(activeStage.alsoLights);
|
|
2077
|
+
}
|
|
2078
|
+
return s;
|
|
2079
|
+
}, [activeStage]);
|
|
2080
|
+
const edges = (0, import_react3.useMemo)(() => {
|
|
2081
|
+
const byKey = /* @__PURE__ */ new Map();
|
|
2082
|
+
visible.forEach((s) => {
|
|
2083
|
+
byKey.set(`${s.from}\u2192${s.to}`, { from: s.from, to: s.to, lastStage: s });
|
|
2084
|
+
});
|
|
2085
|
+
return [...byKey.values()].map(({ from, to, lastStage }) => {
|
|
2086
|
+
const isActive = activeStage !== void 0 && from === activeStage.from && to === activeStage.to;
|
|
2087
|
+
const { sourceHandle, targetHandle } = pickHandles(from, to);
|
|
2088
|
+
const isLoop = to === "agent" && (from === "tool" || from === "skill");
|
|
2089
|
+
return {
|
|
2090
|
+
id: `${from}\u2192${to}`,
|
|
2091
|
+
source: from,
|
|
2092
|
+
target: to,
|
|
2093
|
+
sourceHandle,
|
|
2094
|
+
targetHandle,
|
|
2095
|
+
type: "labelled",
|
|
2096
|
+
// Only loop edges get the marching-ants animation.
|
|
2097
|
+
animated: isLoop,
|
|
2098
|
+
data: {
|
|
2099
|
+
primitive: lastStage.primitive,
|
|
2100
|
+
active: isActive,
|
|
2101
|
+
isLoop,
|
|
2102
|
+
stage: lastStage
|
|
2103
|
+
}
|
|
2104
|
+
};
|
|
2105
|
+
});
|
|
2106
|
+
}, [visible, activeStage]);
|
|
2107
|
+
const nodes = (0, import_react3.useMemo)(() => {
|
|
2108
|
+
return Object.keys(NODE_POSITIONS).filter((id) => {
|
|
2109
|
+
if (id === "skill") return touched.has("skill");
|
|
2110
|
+
return true;
|
|
2111
|
+
}).map((id) => ({
|
|
2112
|
+
id,
|
|
2113
|
+
type: "lens",
|
|
2114
|
+
position: NODE_POSITIONS[id],
|
|
2115
|
+
data: {
|
|
2116
|
+
id,
|
|
2117
|
+
active: activeNodes.has(id),
|
|
2118
|
+
touched: touched.has(id),
|
|
2119
|
+
// Which of the Agent's three ports actually MUTATED this step.
|
|
2120
|
+
// Multiple can be true at once (read_skill touches all three).
|
|
2121
|
+
...id === "agent" && activeStage ? { activeMutations: activeStage.mutations } : {},
|
|
2122
|
+
// Skill annotation on the Agent node — tells the user which
|
|
2123
|
+
// skill is governing the current System Prompt + Tools. Pure
|
|
2124
|
+
// context signal; doesn't affect layout.
|
|
2125
|
+
...id === "agent" && activeSkillId ? { activeSkillId } : {},
|
|
2126
|
+
// Tool node shows the SPECIFIC tool name that's currently
|
|
2127
|
+
// being called — debugging without this is guesswork ("we
|
|
2128
|
+
// called a tool — but which one?"). Only surfaces when the
|
|
2129
|
+
// active stage actually references a tool name.
|
|
2130
|
+
...id === "tool" && activeStage?.toolName && (activeStage.from === "tool" || activeStage.to === "tool") ? {
|
|
2131
|
+
activeLabel: activeStage.toolName,
|
|
2132
|
+
...activeStage.parallelCount ? { parallelCount: activeStage.parallelCount } : {}
|
|
2133
|
+
} : {}
|
|
2134
|
+
},
|
|
2135
|
+
draggable: false
|
|
2136
|
+
}));
|
|
2137
|
+
}, [activeNodes, touched, activeStage, activeSkillId]);
|
|
2138
|
+
const nodeTypes = (0, import_react3.useMemo)(() => ({ lens: LensNode }), []);
|
|
2139
|
+
const edgeTypes = (0, import_react3.useMemo)(() => ({ labelled: LensEdge(onEdgeClick) }), [onEdgeClick]);
|
|
2140
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
2141
|
+
"div",
|
|
2142
|
+
{
|
|
2143
|
+
"data-fp-lens": "stage-flow",
|
|
2144
|
+
style: {
|
|
2145
|
+
height,
|
|
2146
|
+
background: t.bg,
|
|
2147
|
+
borderBottom: `1px solid ${t.border}`
|
|
2148
|
+
},
|
|
2149
|
+
children: [
|
|
2150
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(EdgeMarkerDefs, {}),
|
|
2151
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2152
|
+
import_react4.ReactFlow,
|
|
2153
|
+
{
|
|
2154
|
+
nodes,
|
|
2155
|
+
edges,
|
|
2156
|
+
nodeTypes,
|
|
2157
|
+
edgeTypes,
|
|
2158
|
+
fitView: true,
|
|
2159
|
+
fitViewOptions: { padding: 0.15 },
|
|
2160
|
+
proOptions: { hideAttribution: true },
|
|
2161
|
+
nodesDraggable: false,
|
|
2162
|
+
nodesConnectable: false,
|
|
2163
|
+
elementsSelectable: false,
|
|
2164
|
+
panOnDrag: false,
|
|
2165
|
+
zoomOnScroll: false,
|
|
2166
|
+
zoomOnPinch: false,
|
|
2167
|
+
zoomOnDoubleClick: false,
|
|
2168
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2169
|
+
import_react4.Background,
|
|
2170
|
+
{
|
|
2171
|
+
variant: import_react4.BackgroundVariant.Dots,
|
|
2172
|
+
gap: 18,
|
|
2173
|
+
size: 1,
|
|
2174
|
+
color: t.border
|
|
2175
|
+
}
|
|
2176
|
+
)
|
|
2177
|
+
}
|
|
2178
|
+
)
|
|
2179
|
+
]
|
|
2180
|
+
}
|
|
2181
|
+
);
|
|
2182
|
+
}
|
|
2183
|
+
function EdgeMarkerDefs() {
|
|
2184
|
+
const t = useLensTheme();
|
|
2185
|
+
const active = t.accent;
|
|
2186
|
+
const loop = `color-mix(in srgb, ${t.accent} 55%, ${t.border})`;
|
|
2187
|
+
const dim = t.border;
|
|
2188
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2189
|
+
"svg",
|
|
2190
|
+
{
|
|
2191
|
+
"aria-hidden": "true",
|
|
2192
|
+
style: { position: "absolute", width: 0, height: 0, pointerEvents: "none" },
|
|
2193
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("defs", { children: [
|
|
2194
|
+
{ id: "lens-arrow-active", fill: active },
|
|
2195
|
+
{ id: "lens-arrow-loop", fill: loop },
|
|
2196
|
+
{ id: "lens-arrow-dim", fill: dim }
|
|
2197
|
+
].map((m) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2198
|
+
"marker",
|
|
2199
|
+
{
|
|
2200
|
+
id: m.id,
|
|
2201
|
+
viewBox: "0 0 10 10",
|
|
2202
|
+
refX: "9",
|
|
2203
|
+
refY: "5",
|
|
2204
|
+
markerWidth: "6",
|
|
2205
|
+
markerHeight: "6",
|
|
2206
|
+
orient: "auto-start-reverse",
|
|
2207
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "M 0 0 L 10 5 L 0 10 z", fill: m.fill })
|
|
2208
|
+
},
|
|
2209
|
+
m.id
|
|
2210
|
+
)) })
|
|
2211
|
+
}
|
|
2212
|
+
);
|
|
2213
|
+
}
|
|
2214
|
+
var NODE_KEYFRAMES_ID = "fp-lens-node-keyframes";
|
|
2215
|
+
var NODE_KEYFRAMES_CSS = `
|
|
2216
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
2217
|
+
@keyframes fp-lens-pulse {
|
|
2218
|
+
0%, 100% { opacity: 0.4; transform: scale(1); }
|
|
2219
|
+
50% { opacity: 0.12; transform: scale(1.08); }
|
|
2220
|
+
}
|
|
2221
|
+
}
|
|
2222
|
+
@media (prefers-reduced-motion: reduce) {
|
|
2223
|
+
@keyframes fp-lens-pulse { 0%, 100% { opacity: 0.3; } }
|
|
2224
|
+
}
|
|
2225
|
+
`;
|
|
2226
|
+
function injectNodeKeyframes() {
|
|
2227
|
+
if (typeof document === "undefined") return;
|
|
2228
|
+
if (document.getElementById(NODE_KEYFRAMES_ID)) return;
|
|
2229
|
+
const el = document.createElement("style");
|
|
2230
|
+
el.id = NODE_KEYFRAMES_ID;
|
|
2231
|
+
el.textContent = NODE_KEYFRAMES_CSS;
|
|
2232
|
+
document.head.appendChild(el);
|
|
2233
|
+
}
|
|
2234
|
+
function LensNode({ data }) {
|
|
2235
|
+
const t = useLensTheme();
|
|
2236
|
+
const d = data;
|
|
2237
|
+
injectNodeKeyframes();
|
|
2238
|
+
const isActive = d.active;
|
|
2239
|
+
const isDone = !d.active && d.touched;
|
|
2240
|
+
const bg = isActive ? t.accent : isDone ? t.bgElev : t.bg;
|
|
2241
|
+
const border = isActive ? t.accent : isDone ? t.border : t.border;
|
|
2242
|
+
const textColor = isActive ? "#ffffff" : isDone ? t.text : t.textSubtle;
|
|
2243
|
+
const shadow = isActive ? `0 0 18px color-mix(in srgb, ${t.accent} 42%, transparent)` : isDone ? `0 2px 8px rgba(0,0,0,0.18)` : `0 1px 3px rgba(0,0,0,0.08)`;
|
|
2244
|
+
const label = NODE_LABELS[d.id];
|
|
2245
|
+
const sub = isActive && d.activeLabel ? d.activeLabel : NODE_SUBLABELS[d.id];
|
|
2246
|
+
const isAgent = d.id === "agent";
|
|
2247
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { position: "relative", display: "inline-block" }, children: [
|
|
2248
|
+
isActive && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2249
|
+
"div",
|
|
2250
|
+
{
|
|
2251
|
+
style: {
|
|
2252
|
+
position: "absolute",
|
|
2253
|
+
inset: -6,
|
|
2254
|
+
borderRadius: 14,
|
|
2255
|
+
border: `2px solid ${t.accent}`,
|
|
2256
|
+
opacity: 0.35,
|
|
2257
|
+
pointerEvents: "none",
|
|
2258
|
+
animation: "fp-lens-pulse 1.6s ease-out infinite"
|
|
2259
|
+
}
|
|
2260
|
+
}
|
|
2261
|
+
),
|
|
2262
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
2263
|
+
"div",
|
|
2264
|
+
{
|
|
2265
|
+
style: {
|
|
2266
|
+
width: isAgent ? 200 : 150,
|
|
2267
|
+
padding: "12px 16px",
|
|
2268
|
+
borderRadius: 10,
|
|
2269
|
+
background: bg,
|
|
2270
|
+
border: `2px solid ${border}`,
|
|
2271
|
+
color: textColor,
|
|
2272
|
+
fontFamily: t.fontSans,
|
|
2273
|
+
textAlign: "center",
|
|
2274
|
+
boxShadow: shadow,
|
|
2275
|
+
transition: "background 220ms ease, border-color 220ms ease, box-shadow 220ms ease, color 220ms ease"
|
|
2276
|
+
},
|
|
2277
|
+
children: [
|
|
2278
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", alignItems: "center", justifyContent: "center", gap: 6 }, children: [
|
|
2279
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(NodeIcon, { id: d.id, color: textColor }),
|
|
2280
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: { fontSize: 13, fontWeight: 600 }, children: label })
|
|
2281
|
+
] }),
|
|
2282
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2283
|
+
"div",
|
|
2284
|
+
{
|
|
2285
|
+
style: {
|
|
2286
|
+
fontSize: isActive && d.activeLabel ? 11 : 10,
|
|
2287
|
+
color: isActive ? "rgba(255,255,255,0.95)" : t.textSubtle,
|
|
2288
|
+
marginTop: 2,
|
|
2289
|
+
fontWeight: isActive && d.activeLabel ? 600 : 400,
|
|
2290
|
+
fontFamily: isActive && d.activeLabel ? t.fontMono : t.fontSans,
|
|
2291
|
+
maxWidth: isAgent ? 180 : 130,
|
|
2292
|
+
overflow: "hidden",
|
|
2293
|
+
textOverflow: "ellipsis",
|
|
2294
|
+
whiteSpace: "nowrap",
|
|
2295
|
+
margin: "2px auto 0"
|
|
2296
|
+
},
|
|
2297
|
+
title: sub,
|
|
2298
|
+
children: sub
|
|
2299
|
+
}
|
|
2300
|
+
),
|
|
2301
|
+
d.id === "tool" && isActive && (d.parallelCount ?? 0) > 1 && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
2302
|
+
"div",
|
|
2303
|
+
{
|
|
2304
|
+
title: `This tool is one of ${d.parallelCount} called in parallel this round`,
|
|
2305
|
+
style: {
|
|
2306
|
+
marginTop: 4,
|
|
2307
|
+
alignSelf: "center",
|
|
2308
|
+
display: "inline-block",
|
|
2309
|
+
padding: "1px 7px",
|
|
2310
|
+
borderRadius: 999,
|
|
2311
|
+
background: "rgba(255,255,255,0.25)",
|
|
2312
|
+
color: "#ffffff",
|
|
2313
|
+
fontSize: 9,
|
|
2314
|
+
fontWeight: 700,
|
|
2315
|
+
letterSpacing: "0.08em",
|
|
2316
|
+
textTransform: "uppercase"
|
|
2317
|
+
},
|
|
2318
|
+
children: [
|
|
2319
|
+
"\u26A1 Parallel \xB7 ",
|
|
2320
|
+
d.parallelCount
|
|
2321
|
+
]
|
|
2322
|
+
}
|
|
2323
|
+
),
|
|
2324
|
+
isAgent && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
2325
|
+
d.activeSkillId && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
2326
|
+
"div",
|
|
2327
|
+
{
|
|
2328
|
+
title: `System Prompt + Tools are currently governed by the ${d.activeSkillId} skill`,
|
|
2329
|
+
style: {
|
|
2330
|
+
marginTop: 8,
|
|
2331
|
+
padding: "3px 9px",
|
|
2332
|
+
borderRadius: 999,
|
|
2333
|
+
background: isActive ? "rgba(255,255,255,0.18)" : t.bgElev,
|
|
2334
|
+
border: `1px solid ${isActive ? "rgba(255,255,255,0.35)" : t.border}`,
|
|
2335
|
+
color: isActive ? "#ffffff" : t.accent,
|
|
2336
|
+
fontSize: 10,
|
|
2337
|
+
fontFamily: t.fontMono,
|
|
2338
|
+
fontWeight: 600,
|
|
2339
|
+
whiteSpace: "nowrap",
|
|
2340
|
+
maxWidth: 180,
|
|
2341
|
+
overflow: "hidden",
|
|
2342
|
+
textOverflow: "ellipsis",
|
|
2343
|
+
display: "inline-block"
|
|
2344
|
+
},
|
|
2345
|
+
children: [
|
|
2346
|
+
"\u{1F4DA} ",
|
|
2347
|
+
d.activeSkillId
|
|
2348
|
+
]
|
|
2349
|
+
}
|
|
2350
|
+
),
|
|
2351
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2352
|
+
AgentPorts,
|
|
2353
|
+
{
|
|
2354
|
+
active: d.active,
|
|
2355
|
+
mutations: d.activeMutations,
|
|
2356
|
+
filledCard: isActive
|
|
2357
|
+
}
|
|
2358
|
+
)
|
|
2359
|
+
] }),
|
|
2360
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react4.Handle, { type: "source", position: import_react4.Position.Top, id: "t-out", style: handleStyle(-14, 0) }),
|
|
2361
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react4.Handle, { type: "target", position: import_react4.Position.Top, id: "t-in", style: handleStyle(14, 0) }),
|
|
2362
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react4.Handle, { type: "source", position: import_react4.Position.Bottom, id: "b-out", style: handleStyle(14, 0) }),
|
|
2363
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react4.Handle, { type: "target", position: import_react4.Position.Bottom, id: "b-in", style: handleStyle(-14, 0) }),
|
|
2364
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react4.Handle, { type: "source", position: import_react4.Position.Left, id: "l-out", style: handleStyle(0, 10) }),
|
|
2365
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react4.Handle, { type: "target", position: import_react4.Position.Left, id: "l-in", style: handleStyle(0, -10) }),
|
|
2366
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react4.Handle, { type: "source", position: import_react4.Position.Right, id: "r-out", style: handleStyle(0, -10) }),
|
|
2367
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react4.Handle, { type: "target", position: import_react4.Position.Right, id: "r-in", style: handleStyle(0, 10) })
|
|
2368
|
+
]
|
|
2369
|
+
}
|
|
2370
|
+
)
|
|
2371
|
+
] });
|
|
2372
|
+
}
|
|
2373
|
+
function NodeIcon({ id, color }) {
|
|
2374
|
+
const size = 16;
|
|
2375
|
+
const props = {
|
|
2376
|
+
width: size,
|
|
2377
|
+
height: size,
|
|
2378
|
+
viewBox: `0 0 ${size} ${size}`,
|
|
2379
|
+
fill: "none",
|
|
2380
|
+
style: { flexShrink: 0 }
|
|
2381
|
+
};
|
|
2382
|
+
if (id === "user") {
|
|
2383
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("svg", { ...props, children: [
|
|
2384
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("circle", { cx: "8", cy: "5", r: "2.5", stroke: color, strokeWidth: "1.5" }),
|
|
2385
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "M3.5 14C3.5 11 5.5 9 8 9S12.5 11 12.5 14", stroke: color, strokeWidth: "1.5", strokeLinecap: "round" })
|
|
2386
|
+
] });
|
|
2387
|
+
}
|
|
2388
|
+
if (id === "agent") {
|
|
2389
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("svg", { ...props, children: [
|
|
2390
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("circle", { cx: "8", cy: "8", r: "6", stroke: color, strokeWidth: "1.5" }),
|
|
2391
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "M5.5 8C5.5 6.5 6.5 5 8 5S10.5 6.5 10.5 8", stroke: color, strokeWidth: "1.2", strokeLinecap: "round" }),
|
|
2392
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("circle", { cx: "8", cy: "9.5", r: "1", fill: color }),
|
|
2393
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("line", { x1: "8", y1: "2", x2: "8", y2: "3.5", stroke: color, strokeWidth: "1", strokeLinecap: "round" }),
|
|
2394
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("line", { x1: "12.5", y1: "4", x2: "11.2", y2: "5", stroke: color, strokeWidth: "1", strokeLinecap: "round" }),
|
|
2395
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("line", { x1: "3.5", y1: "4", x2: "4.8", y2: "5", stroke: color, strokeWidth: "1", strokeLinecap: "round" })
|
|
2396
|
+
] });
|
|
2397
|
+
}
|
|
2398
|
+
if (id === "tool") {
|
|
2399
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("svg", { ...props, children: [
|
|
2400
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("circle", { cx: "8", cy: "8", r: "3", stroke: color, strokeWidth: "1.5" }),
|
|
2401
|
+
[0, 45, 90, 135, 180, 225, 270, 315].map((angle) => {
|
|
2402
|
+
const rad = angle * Math.PI / 180;
|
|
2403
|
+
const x1 = 8 + Math.cos(rad) * 4.5;
|
|
2404
|
+
const y1 = 8 + Math.sin(rad) * 4.5;
|
|
2405
|
+
const x2 = 8 + Math.cos(rad) * 6;
|
|
2406
|
+
const y2 = 8 + Math.sin(rad) * 6;
|
|
2407
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2408
|
+
"line",
|
|
2409
|
+
{
|
|
2410
|
+
x1,
|
|
2411
|
+
y1,
|
|
2412
|
+
x2,
|
|
2413
|
+
y2,
|
|
2414
|
+
stroke: color,
|
|
2415
|
+
strokeWidth: "1.5",
|
|
2416
|
+
strokeLinecap: "round"
|
|
2417
|
+
},
|
|
2418
|
+
angle
|
|
2419
|
+
);
|
|
2420
|
+
})
|
|
2421
|
+
] });
|
|
2422
|
+
}
|
|
2423
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("svg", { ...props, children: [
|
|
2424
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "M3 4h7a2 2 0 0 1 2 2v7a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V4z", stroke: color, strokeWidth: "1.4", strokeLinejoin: "round" }),
|
|
2425
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "M5.5 7h4M5.5 9.5h4", stroke: color, strokeWidth: "1.2", strokeLinecap: "round" })
|
|
2426
|
+
] });
|
|
2427
|
+
}
|
|
2428
|
+
function handleStyle(dx, dy) {
|
|
2429
|
+
return {
|
|
2430
|
+
...HANDLE_STYLE,
|
|
2431
|
+
transform: `translate(${dx}px, ${dy}px)`
|
|
2432
|
+
};
|
|
2433
|
+
}
|
|
2434
|
+
function AgentPorts({
|
|
2435
|
+
active,
|
|
2436
|
+
mutations,
|
|
2437
|
+
filledCard
|
|
2438
|
+
}) {
|
|
2439
|
+
const t = useLensTheme();
|
|
2440
|
+
const litSP = active && mutations?.systemPrompt === true;
|
|
2441
|
+
const litMsg = active && mutations?.messages === true;
|
|
2442
|
+
const litTools = active && mutations?.tools === true;
|
|
2443
|
+
const spBadge = mutations?.systemPromptDeltaChars !== void 0 ? `+${mutations.systemPromptDeltaChars.toLocaleString()} chars` : null;
|
|
2444
|
+
const toolsBadge = (() => {
|
|
2445
|
+
const added = mutations?.toolsAdded ?? 0;
|
|
2446
|
+
const removed = mutations?.toolsRemoved ?? 0;
|
|
2447
|
+
if (added === 0 && removed === 0) return null;
|
|
2448
|
+
const bits = [];
|
|
2449
|
+
if (added > 0) bits.push(`+${added}`);
|
|
2450
|
+
if (removed > 0) bits.push(`-${removed}`);
|
|
2451
|
+
return bits.join(" / ");
|
|
2452
|
+
})();
|
|
2453
|
+
const ports = [
|
|
2454
|
+
{
|
|
2455
|
+
key: "system-prompt",
|
|
2456
|
+
label: "System Prompt",
|
|
2457
|
+
hint: "Instructions Neo runs on",
|
|
2458
|
+
lit: litSP,
|
|
2459
|
+
badge: litSP ? spBadge : null
|
|
2460
|
+
},
|
|
2461
|
+
{
|
|
2462
|
+
key: "message",
|
|
2463
|
+
label: "Messages",
|
|
2464
|
+
hint: "Conversation so far",
|
|
2465
|
+
lit: litMsg,
|
|
2466
|
+
badge: null
|
|
2467
|
+
},
|
|
2468
|
+
{
|
|
2469
|
+
key: "tool",
|
|
2470
|
+
label: "Tools",
|
|
2471
|
+
hint: "What Neo can call",
|
|
2472
|
+
lit: litTools,
|
|
2473
|
+
badge: litTools ? toolsBadge : null
|
|
2474
|
+
}
|
|
2475
|
+
];
|
|
2476
|
+
const boxBg = filledCard ? "rgba(255,255,255,0.12)" : t.bg;
|
|
2477
|
+
const boxBorder = filledCard ? "rgba(255,255,255,0.25)" : t.border;
|
|
2478
|
+
const portIdle = filledCard ? "rgba(255,255,255,0.7)" : t.textMuted;
|
|
2479
|
+
const portLitBg = filledCard ? "rgba(255,255,255,0.25)" : `color-mix(in srgb, ${t.accent} 30%, transparent)`;
|
|
2480
|
+
const portLitColor = filledCard ? "#ffffff" : t.accent;
|
|
2481
|
+
const portLitBorder = filledCard ? "#ffffff" : t.accent;
|
|
2482
|
+
const portIdleBorder = filledCard ? "rgba(255,255,255,0.3)" : t.border;
|
|
2483
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2484
|
+
"div",
|
|
2485
|
+
{
|
|
2486
|
+
style: {
|
|
2487
|
+
display: "flex",
|
|
2488
|
+
flexDirection: "column",
|
|
2489
|
+
gap: 3,
|
|
2490
|
+
marginTop: 8,
|
|
2491
|
+
padding: 4,
|
|
2492
|
+
background: boxBg,
|
|
2493
|
+
border: `1px solid ${boxBorder}`,
|
|
2494
|
+
borderRadius: 6
|
|
2495
|
+
},
|
|
2496
|
+
children: ports.map((p) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
2497
|
+
"div",
|
|
2498
|
+
{
|
|
2499
|
+
title: p.hint,
|
|
2500
|
+
style: {
|
|
2501
|
+
padding: "2px 8px",
|
|
2502
|
+
borderRadius: 3,
|
|
2503
|
+
background: p.lit ? portLitBg : "transparent",
|
|
2504
|
+
color: p.lit ? portLitColor : portIdle,
|
|
2505
|
+
fontSize: 10,
|
|
2506
|
+
fontWeight: p.lit ? 600 : 500,
|
|
2507
|
+
letterSpacing: "0.02em",
|
|
2508
|
+
textAlign: "left",
|
|
2509
|
+
fontFamily: t.fontSans,
|
|
2510
|
+
display: "flex",
|
|
2511
|
+
alignItems: "center",
|
|
2512
|
+
gap: 6,
|
|
2513
|
+
borderLeft: `2px solid ${p.lit ? portLitBorder : portIdleBorder}`
|
|
2514
|
+
},
|
|
2515
|
+
children: [
|
|
2516
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: { fontSize: 8 }, children: "\u25B8" }),
|
|
2517
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: { flex: 1 }, children: p.label }),
|
|
2518
|
+
p.badge && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2519
|
+
"span",
|
|
2520
|
+
{
|
|
2521
|
+
style: {
|
|
2522
|
+
fontSize: 9,
|
|
2523
|
+
padding: "0 4px",
|
|
2524
|
+
borderRadius: 3,
|
|
2525
|
+
background: filledCard ? "rgba(255,255,255,0.22)" : t.bg,
|
|
2526
|
+
color: p.lit ? portLitColor : portIdle,
|
|
2527
|
+
fontFamily: t.fontMono,
|
|
2528
|
+
fontWeight: 600
|
|
2529
|
+
},
|
|
2530
|
+
children: p.badge
|
|
2531
|
+
}
|
|
2532
|
+
)
|
|
2533
|
+
]
|
|
2534
|
+
},
|
|
2535
|
+
p.key
|
|
2536
|
+
))
|
|
2537
|
+
}
|
|
2538
|
+
);
|
|
2539
|
+
}
|
|
2540
|
+
var HANDLE_STYLE = {
|
|
2541
|
+
opacity: 0,
|
|
2542
|
+
pointerEvents: "none",
|
|
2543
|
+
width: 1,
|
|
2544
|
+
height: 1
|
|
2545
|
+
};
|
|
2546
|
+
function LensEdge(onEdgeClick) {
|
|
2547
|
+
return function LensEdgeInner({
|
|
2548
|
+
id,
|
|
2549
|
+
sourceX,
|
|
2550
|
+
sourceY,
|
|
2551
|
+
targetX,
|
|
2552
|
+
targetY,
|
|
2553
|
+
sourcePosition,
|
|
2554
|
+
targetPosition,
|
|
2555
|
+
data
|
|
2556
|
+
}) {
|
|
2557
|
+
const t = useLensTheme();
|
|
2558
|
+
const d = data;
|
|
2559
|
+
const [edgePath] = (0, import_react4.getSmoothStepPath)({
|
|
2560
|
+
sourceX,
|
|
2561
|
+
sourceY,
|
|
2562
|
+
sourcePosition,
|
|
2563
|
+
targetX,
|
|
2564
|
+
targetY,
|
|
2565
|
+
targetPosition,
|
|
2566
|
+
borderRadius: 10
|
|
2567
|
+
});
|
|
2568
|
+
const stroke = d.active ? t.accent : d.isLoop ? `color-mix(in srgb, ${t.accent} 55%, ${t.border})` : t.border;
|
|
2569
|
+
const strokeWidth = d.active ? 2.25 : d.isLoop ? 1.75 : 1.5;
|
|
2570
|
+
const strokeDasharray = d.isLoop ? "5 4" : void 0;
|
|
2571
|
+
const markerId = d.active ? "lens-arrow-active" : d.isLoop ? "lens-arrow-loop" : "lens-arrow-dim";
|
|
2572
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
2573
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2574
|
+
import_react4.BaseEdge,
|
|
2575
|
+
{
|
|
2576
|
+
id,
|
|
2577
|
+
path: edgePath,
|
|
2578
|
+
style: {
|
|
2579
|
+
stroke,
|
|
2580
|
+
strokeWidth,
|
|
2581
|
+
strokeDasharray,
|
|
2582
|
+
filter: d.active ? `drop-shadow(0 0 6px color-mix(in srgb, ${t.accent} 50%, transparent))` : void 0,
|
|
2583
|
+
cursor: onEdgeClick ? "pointer" : "default"
|
|
2584
|
+
},
|
|
2585
|
+
markerEnd: `url(#${markerId})`
|
|
2586
|
+
}
|
|
2587
|
+
),
|
|
2588
|
+
onEdgeClick && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2589
|
+
"path",
|
|
2590
|
+
{
|
|
2591
|
+
d: edgePath,
|
|
2592
|
+
fill: "none",
|
|
2593
|
+
stroke: "transparent",
|
|
2594
|
+
strokeWidth: 12,
|
|
2595
|
+
style: { cursor: "pointer" },
|
|
2596
|
+
onClick: () => onEdgeClick(d.stage)
|
|
2597
|
+
}
|
|
2598
|
+
)
|
|
2599
|
+
] });
|
|
2600
|
+
};
|
|
2601
|
+
}
|
|
2602
|
+
|
|
2603
|
+
// src/panels/TimeTravel.tsx
|
|
2604
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
2605
|
+
function TimeTravel({
|
|
2606
|
+
stages,
|
|
2607
|
+
focusIndex,
|
|
2608
|
+
onFocusChange,
|
|
2609
|
+
isLive
|
|
2610
|
+
}) {
|
|
2611
|
+
const t = useLensTheme();
|
|
2612
|
+
const max = Math.max(0, stages.length - 1);
|
|
2613
|
+
function step(delta) {
|
|
2614
|
+
const next = Math.min(max, Math.max(0, focusIndex + delta));
|
|
2615
|
+
onFocusChange(next);
|
|
2616
|
+
}
|
|
2617
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
2618
|
+
"div",
|
|
2619
|
+
{
|
|
2620
|
+
"data-fp-lens": "time-travel",
|
|
2621
|
+
style: {
|
|
2622
|
+
// Frosted-glass oval pill, floating clear of the surrounding
|
|
2623
|
+
// surfaces. `color-mix` gives a translucent tint using the
|
|
2624
|
+
// current theme's elevated bg; `backdrop-filter` blurs
|
|
2625
|
+
// whatever's behind (the graph + ask card show through
|
|
2626
|
+
// softly). Margin creates air around the pill so it reads as
|
|
2627
|
+
// a distinct floating control, not a toolbar bar.
|
|
2628
|
+
display: "flex",
|
|
2629
|
+
alignItems: "center",
|
|
2630
|
+
gap: 10,
|
|
2631
|
+
padding: "8px 14px",
|
|
2632
|
+
margin: "10px 14px",
|
|
2633
|
+
background: `color-mix(in srgb, ${t.bgElev} 55%, transparent)`,
|
|
2634
|
+
backdropFilter: "blur(14px) saturate(140%)",
|
|
2635
|
+
WebkitBackdropFilter: "blur(14px) saturate(140%)",
|
|
2636
|
+
border: `1px solid color-mix(in srgb, ${t.border} 70%, transparent)`,
|
|
2637
|
+
borderRadius: 999,
|
|
2638
|
+
boxShadow: "0 4px 16px rgba(0, 0, 0, 0.12), inset 0 1px 0 rgba(255, 255, 255, 0.06)",
|
|
2639
|
+
fontFamily: t.fontSans
|
|
2640
|
+
},
|
|
2641
|
+
children: [
|
|
2642
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
2643
|
+
"button",
|
|
2644
|
+
{
|
|
2645
|
+
onClick: () => step(-1),
|
|
2646
|
+
disabled: focusIndex <= 0 || stages.length === 0,
|
|
2647
|
+
style: btnStyle(t, false),
|
|
2648
|
+
title: "Previous step (\u2190)",
|
|
2649
|
+
children: "\u25C0"
|
|
2650
|
+
}
|
|
2651
|
+
),
|
|
2652
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
2653
|
+
"button",
|
|
2654
|
+
{
|
|
2655
|
+
onClick: () => step(1),
|
|
2656
|
+
disabled: focusIndex >= max || stages.length === 0,
|
|
2657
|
+
style: btnStyle(t, false),
|
|
2658
|
+
title: "Next step (\u2192)",
|
|
2659
|
+
children: "\u25B6"
|
|
2660
|
+
}
|
|
2661
|
+
),
|
|
2662
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
2663
|
+
"button",
|
|
2664
|
+
{
|
|
2665
|
+
onClick: () => onFocusChange(max),
|
|
2666
|
+
disabled: stages.length === 0 || isLive === true,
|
|
2667
|
+
style: btnStyle(t, isLive !== true && stages.length > 0),
|
|
2668
|
+
title: "Jump to latest step",
|
|
2669
|
+
children: "\u27F3 Live"
|
|
2670
|
+
}
|
|
2671
|
+
),
|
|
2672
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
2673
|
+
"input",
|
|
2674
|
+
{
|
|
2675
|
+
type: "range",
|
|
2676
|
+
min: 0,
|
|
2677
|
+
max,
|
|
2678
|
+
value: Math.min(focusIndex, max),
|
|
2679
|
+
onChange: (e) => onFocusChange(Number(e.target.value)),
|
|
2680
|
+
disabled: stages.length <= 1,
|
|
2681
|
+
style: { flex: 1, accentColor: t.accent, minWidth: 120 }
|
|
2682
|
+
}
|
|
2683
|
+
),
|
|
2684
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
2685
|
+
"div",
|
|
2686
|
+
{
|
|
2687
|
+
style: {
|
|
2688
|
+
fontSize: 11,
|
|
2689
|
+
color: t.textMuted,
|
|
2690
|
+
fontFamily: t.fontMono,
|
|
2691
|
+
whiteSpace: "nowrap",
|
|
2692
|
+
minWidth: 80,
|
|
2693
|
+
textAlign: "right"
|
|
2694
|
+
},
|
|
2695
|
+
children: stages.length === 0 ? "no steps yet" : `Step ${focusIndex + 1} / ${stages.length}`
|
|
2696
|
+
}
|
|
2697
|
+
)
|
|
2698
|
+
]
|
|
2699
|
+
}
|
|
2700
|
+
);
|
|
2701
|
+
}
|
|
2702
|
+
function btnStyle(t, highlighted) {
|
|
2703
|
+
return {
|
|
2704
|
+
background: highlighted ? t.accent : `color-mix(in srgb, ${t.bg} 40%, transparent)`,
|
|
2705
|
+
color: highlighted ? "#fff" : t.textMuted,
|
|
2706
|
+
border: `1px solid color-mix(in srgb, ${t.border} 60%, transparent)`,
|
|
2707
|
+
borderRadius: 999,
|
|
2708
|
+
padding: "3px 12px",
|
|
2709
|
+
fontSize: 12,
|
|
2710
|
+
cursor: "pointer",
|
|
2711
|
+
width: "auto",
|
|
2712
|
+
fontWeight: 500,
|
|
2713
|
+
whiteSpace: "nowrap",
|
|
2714
|
+
transition: "background 140ms ease, border-color 140ms ease, color 140ms ease"
|
|
2715
|
+
};
|
|
2716
|
+
}
|
|
2717
|
+
|
|
2718
|
+
// src/panels/AskCard.tsx
|
|
2719
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
2720
|
+
function AskCard({ timeline, focusIndex, stages }) {
|
|
2721
|
+
const t = useLensTheme();
|
|
2722
|
+
const currentStage = stages[focusIndex];
|
|
2723
|
+
const currentTurn = currentStage !== void 0 ? timeline.turns[currentStage.turnIndex] : timeline.turns[0];
|
|
2724
|
+
const currentIter = currentStage?.iterIndex !== void 0 ? currentTurn?.iterations.find((it) => it.index === currentStage.iterIndex) : void 0;
|
|
2725
|
+
const currentTool = currentStage?.toolName && currentIter ? currentIter.toolCalls.find((tc) => tc.name === currentStage.toolName) : void 0;
|
|
2726
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
2727
|
+
"div",
|
|
2728
|
+
{
|
|
2729
|
+
"data-fp-lens": "ask-card",
|
|
2730
|
+
style: {
|
|
2731
|
+
display: "flex",
|
|
2732
|
+
flexDirection: "column",
|
|
2733
|
+
gap: 12,
|
|
2734
|
+
padding: 14,
|
|
2735
|
+
background: t.bg,
|
|
2736
|
+
fontFamily: t.fontSans,
|
|
2737
|
+
color: t.text,
|
|
2738
|
+
overflow: "auto"
|
|
2739
|
+
},
|
|
2740
|
+
children: [
|
|
2741
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("section", { children: [
|
|
2742
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Label3, { t, children: "Your question" }),
|
|
2743
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2744
|
+
"div",
|
|
2745
|
+
{
|
|
2746
|
+
style: {
|
|
2747
|
+
marginTop: 4,
|
|
2748
|
+
padding: "10px 12px",
|
|
2749
|
+
background: `color-mix(in srgb, ${t.accent} 12%, ${t.bgElev})`,
|
|
2750
|
+
border: `1px solid ${t.border}`,
|
|
2751
|
+
borderRadius: 6,
|
|
2752
|
+
fontSize: 13,
|
|
2753
|
+
lineHeight: 1.5
|
|
2754
|
+
},
|
|
2755
|
+
children: currentTurn?.userPrompt ?? "No question yet."
|
|
2756
|
+
}
|
|
2757
|
+
)
|
|
2758
|
+
] }),
|
|
2759
|
+
currentStage && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("section", { children: [
|
|
2760
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Label3, { t, children: [
|
|
2761
|
+
"Step ",
|
|
2762
|
+
focusIndex + 1,
|
|
2763
|
+
" / ",
|
|
2764
|
+
stages.length
|
|
2765
|
+
] }),
|
|
2766
|
+
!(currentTool && currentStage.from === "tool") && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: { marginTop: 4, fontSize: 13, color: t.text, lineHeight: 1.5 }, children: currentStage.label }),
|
|
2767
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
2768
|
+
"div",
|
|
2769
|
+
{
|
|
2770
|
+
style: {
|
|
2771
|
+
marginTop: 8,
|
|
2772
|
+
display: "flex",
|
|
2773
|
+
gap: 6,
|
|
2774
|
+
flexWrap: "wrap",
|
|
2775
|
+
fontSize: 10,
|
|
2776
|
+
color: t.textSubtle
|
|
2777
|
+
},
|
|
2778
|
+
children: [
|
|
2779
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Pill, { t, children: primitivePill(currentStage) }),
|
|
2780
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Pill, { t, children: [
|
|
2781
|
+
friendlyNode(currentStage.from),
|
|
2782
|
+
" \u2192 ",
|
|
2783
|
+
friendlyNode(currentStage.to)
|
|
2784
|
+
] }),
|
|
2785
|
+
currentStage.toolName && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Pill, { t, children: currentStage.toolName })
|
|
2786
|
+
]
|
|
2787
|
+
}
|
|
2788
|
+
)
|
|
2789
|
+
] }),
|
|
2790
|
+
currentStage?.from === "agent" && currentIter?.assistantContent && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("section", { children: [
|
|
2791
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Label3, { t, children: "Agent reasoning" }),
|
|
2792
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2793
|
+
"div",
|
|
2794
|
+
{
|
|
2795
|
+
style: {
|
|
2796
|
+
marginTop: 4,
|
|
2797
|
+
padding: "10px 12px",
|
|
2798
|
+
background: t.bgElev,
|
|
2799
|
+
border: `1px solid ${t.border}`,
|
|
2800
|
+
borderLeft: `3px solid ${t.accent}`,
|
|
2801
|
+
borderRadius: 6,
|
|
2802
|
+
fontSize: 12,
|
|
2803
|
+
lineHeight: 1.55,
|
|
2804
|
+
whiteSpace: "pre-wrap",
|
|
2805
|
+
maxHeight: 220,
|
|
2806
|
+
overflow: "auto"
|
|
2807
|
+
},
|
|
2808
|
+
children: currentIter.assistantContent
|
|
2809
|
+
}
|
|
2810
|
+
)
|
|
2811
|
+
] }),
|
|
2812
|
+
currentTool && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("section", { children: [
|
|
2813
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Label3, { t, children: currentStage?.to === "tool" ? "Arguments" : "Tool returned" }),
|
|
2814
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2815
|
+
"pre",
|
|
2816
|
+
{
|
|
2817
|
+
style: {
|
|
2818
|
+
marginTop: 4,
|
|
2819
|
+
padding: "8px 10px",
|
|
2820
|
+
background: t.bgElev,
|
|
2821
|
+
border: `1px solid ${t.border}`,
|
|
2822
|
+
borderRadius: 6,
|
|
2823
|
+
fontSize: 11,
|
|
2824
|
+
fontFamily: t.fontMono,
|
|
2825
|
+
color: currentTool.error ? t.error : t.text,
|
|
2826
|
+
whiteSpace: "pre-wrap",
|
|
2827
|
+
maxHeight: 180,
|
|
2828
|
+
overflow: "auto",
|
|
2829
|
+
margin: 0
|
|
2830
|
+
},
|
|
2831
|
+
children: currentStage?.to === "tool" ? JSON.stringify(currentTool.arguments, null, 2) : currentTool.result
|
|
2832
|
+
}
|
|
2833
|
+
)
|
|
2834
|
+
] }),
|
|
2835
|
+
timeline.turns.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("section", { children: [
|
|
2836
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Label3, { t, children: "Conversation" }),
|
|
2837
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: { marginTop: 4, fontSize: 12, color: t.textMuted, lineHeight: 1.5 }, children: [
|
|
2838
|
+
timeline.turns.length,
|
|
2839
|
+
" question",
|
|
2840
|
+
timeline.turns.length === 1 ? "" : "s",
|
|
2841
|
+
" so far \xB7",
|
|
2842
|
+
" ",
|
|
2843
|
+
timeline.tools.length,
|
|
2844
|
+
" tool call",
|
|
2845
|
+
timeline.tools.length === 1 ? "" : "s",
|
|
2846
|
+
" total"
|
|
2847
|
+
] })
|
|
2848
|
+
] })
|
|
2849
|
+
]
|
|
2850
|
+
}
|
|
2851
|
+
);
|
|
2852
|
+
}
|
|
2853
|
+
function Label3({
|
|
2854
|
+
t,
|
|
2855
|
+
children
|
|
2856
|
+
}) {
|
|
2857
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2858
|
+
"div",
|
|
2859
|
+
{
|
|
2860
|
+
style: {
|
|
2861
|
+
fontSize: 10,
|
|
2862
|
+
color: t.textSubtle,
|
|
2863
|
+
textTransform: "uppercase",
|
|
2864
|
+
letterSpacing: "0.08em",
|
|
2865
|
+
fontWeight: 600
|
|
2866
|
+
},
|
|
2867
|
+
children
|
|
2868
|
+
}
|
|
2869
|
+
);
|
|
2870
|
+
}
|
|
2871
|
+
function Pill({
|
|
2872
|
+
t,
|
|
2873
|
+
children,
|
|
2874
|
+
warn
|
|
2875
|
+
}) {
|
|
2876
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2877
|
+
"span",
|
|
2878
|
+
{
|
|
2879
|
+
style: {
|
|
2880
|
+
padding: "1px 6px",
|
|
2881
|
+
borderRadius: 3,
|
|
2882
|
+
background: warn ? `color-mix(in srgb, ${t.warning} 20%, transparent)` : t.bgElev,
|
|
2883
|
+
color: warn ? t.warning : t.textMuted,
|
|
2884
|
+
fontWeight: 600,
|
|
2885
|
+
textTransform: "uppercase",
|
|
2886
|
+
letterSpacing: "0.04em"
|
|
2887
|
+
},
|
|
2888
|
+
children
|
|
2889
|
+
}
|
|
2890
|
+
);
|
|
2891
|
+
}
|
|
2892
|
+
function friendlyNode(id) {
|
|
2893
|
+
if (!id) return id;
|
|
2894
|
+
return id.charAt(0).toUpperCase() + id.slice(1);
|
|
2895
|
+
}
|
|
2896
|
+
function primitivePill(stage) {
|
|
2897
|
+
if (stage.primitive === "system-prompt") return "System Prompt";
|
|
2898
|
+
if (stage.primitive === "message") return "Message";
|
|
2899
|
+
if (stage.toolKind === "skill") return "Tool (Skill)";
|
|
2900
|
+
if (stage.toolKind === "ask-human") return "Tool (Ask user)";
|
|
2901
|
+
return "Tool";
|
|
2902
|
+
}
|
|
2903
|
+
|
|
2904
|
+
// src/panels/RunSummary.tsx
|
|
2905
|
+
var import_react5 = require("react");
|
|
2906
|
+
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
2907
|
+
function RunSummary({ timeline }) {
|
|
2908
|
+
const t = useLensTheme();
|
|
2909
|
+
const [open, setOpen] = (0, import_react5.useState)(false);
|
|
2910
|
+
const completedTurns = timeline.turns.filter((turn) => turn.finalContent !== "");
|
|
2911
|
+
if (completedTurns.length === 0) return null;
|
|
2912
|
+
const toolCounts = /* @__PURE__ */ new Map();
|
|
2913
|
+
for (const tc of timeline.tools) {
|
|
2914
|
+
const prev = toolCounts.get(tc.name) ?? { count: 0, totalMs: 0 };
|
|
2915
|
+
toolCounts.set(tc.name, {
|
|
2916
|
+
count: prev.count + 1,
|
|
2917
|
+
totalMs: prev.totalMs + (tc.durationMs ?? 0)
|
|
2918
|
+
});
|
|
2919
|
+
}
|
|
2920
|
+
const toolList = [...toolCounts.entries()].sort((a, b) => b[1].count - a[1].count);
|
|
2921
|
+
const activatedSkills = /* @__PURE__ */ new Set();
|
|
2922
|
+
for (const tc of timeline.tools) {
|
|
2923
|
+
if (tc.name === "read_skill") {
|
|
2924
|
+
const id = tc.arguments?.id;
|
|
2925
|
+
if (typeof id === "string") activatedSkills.add(id);
|
|
2926
|
+
}
|
|
2927
|
+
}
|
|
2928
|
+
const totalIn = timeline.turns.reduce((s, turn) => s + turn.totalInputTokens, 0);
|
|
2929
|
+
const totalOut = timeline.turns.reduce((s, turn) => s + turn.totalOutputTokens, 0);
|
|
2930
|
+
const totalMs = timeline.turns.reduce((s, turn) => s + turn.totalDurationMs, 0);
|
|
2931
|
+
const totalIters = timeline.turns.reduce((s, turn) => s + turn.iterations.length, 0);
|
|
2932
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
2933
|
+
"div",
|
|
2934
|
+
{
|
|
2935
|
+
"data-fp-lens": "run-summary",
|
|
2936
|
+
style: {
|
|
2937
|
+
borderTop: `1px solid ${t.border}`,
|
|
2938
|
+
background: t.bgElev,
|
|
2939
|
+
fontFamily: t.fontSans
|
|
2940
|
+
},
|
|
2941
|
+
children: [
|
|
2942
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
2943
|
+
"button",
|
|
2944
|
+
{
|
|
2945
|
+
onClick: () => setOpen((v) => !v),
|
|
2946
|
+
style: {
|
|
2947
|
+
display: "flex",
|
|
2948
|
+
alignItems: "center",
|
|
2949
|
+
gap: 8,
|
|
2950
|
+
width: "100%",
|
|
2951
|
+
padding: "8px 14px",
|
|
2952
|
+
background: "transparent",
|
|
2953
|
+
border: "none",
|
|
2954
|
+
color: t.textMuted,
|
|
2955
|
+
fontFamily: "inherit",
|
|
2956
|
+
fontSize: 12,
|
|
2957
|
+
cursor: "pointer",
|
|
2958
|
+
textAlign: "left",
|
|
2959
|
+
fontWeight: 400
|
|
2960
|
+
},
|
|
2961
|
+
children: [
|
|
2962
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { style: { fontSize: 10 }, children: open ? "\u25BE" : "\u25B8" }),
|
|
2963
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
2964
|
+
"span",
|
|
2965
|
+
{
|
|
2966
|
+
style: {
|
|
2967
|
+
fontSize: 10,
|
|
2968
|
+
color: t.textSubtle,
|
|
2969
|
+
textTransform: "uppercase",
|
|
2970
|
+
letterSpacing: "0.08em",
|
|
2971
|
+
fontWeight: 600
|
|
2972
|
+
},
|
|
2973
|
+
children: "Run summary"
|
|
2974
|
+
}
|
|
2975
|
+
),
|
|
2976
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { style: { flex: 1 } }),
|
|
2977
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { style: { fontSize: 11, color: t.textMuted }, children: [
|
|
2978
|
+
timeline.tools.length,
|
|
2979
|
+
" tool call",
|
|
2980
|
+
timeline.tools.length === 1 ? "" : "s",
|
|
2981
|
+
" \xB7",
|
|
2982
|
+
" ",
|
|
2983
|
+
activatedSkills.size,
|
|
2984
|
+
" skill",
|
|
2985
|
+
activatedSkills.size === 1 ? "" : "s",
|
|
2986
|
+
" \xB7",
|
|
2987
|
+
" ",
|
|
2988
|
+
totalIn.toLocaleString(),
|
|
2989
|
+
"\u2192",
|
|
2990
|
+
totalOut.toLocaleString(),
|
|
2991
|
+
" tok \xB7",
|
|
2992
|
+
" ",
|
|
2993
|
+
(totalMs / 1e3).toFixed(1),
|
|
2994
|
+
"s"
|
|
2995
|
+
] })
|
|
2996
|
+
]
|
|
2997
|
+
}
|
|
2998
|
+
),
|
|
2999
|
+
open && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
3000
|
+
"div",
|
|
3001
|
+
{
|
|
3002
|
+
style: {
|
|
3003
|
+
padding: "6px 14px 14px",
|
|
3004
|
+
display: "grid",
|
|
3005
|
+
gridTemplateColumns: "1fr 1fr",
|
|
3006
|
+
gap: 14,
|
|
3007
|
+
fontSize: 12,
|
|
3008
|
+
color: t.text
|
|
3009
|
+
},
|
|
3010
|
+
children: [
|
|
3011
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("section", { children: [
|
|
3012
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(Label4, { t, children: [
|
|
3013
|
+
"Tools used \xB7 ",
|
|
3014
|
+
timeline.tools.length
|
|
3015
|
+
] }),
|
|
3016
|
+
toolList.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { color: t.textSubtle, fontSize: 11, fontStyle: "italic" }, children: "None." }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("ul", { style: { margin: 0, padding: 0, listStyle: "none" }, children: toolList.map(([name, stats]) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
3017
|
+
"li",
|
|
3018
|
+
{
|
|
3019
|
+
style: {
|
|
3020
|
+
display: "flex",
|
|
3021
|
+
gap: 8,
|
|
3022
|
+
padding: "3px 0",
|
|
3023
|
+
fontFamily: t.fontMono,
|
|
3024
|
+
fontSize: 11
|
|
3025
|
+
},
|
|
3026
|
+
children: [
|
|
3027
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { style: { color: t.accent, flex: 1 }, children: name }),
|
|
3028
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { style: { color: t.textMuted }, children: [
|
|
3029
|
+
"\xD7",
|
|
3030
|
+
stats.count
|
|
3031
|
+
] }),
|
|
3032
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { style: { color: t.textSubtle, minWidth: 60, textAlign: "right" }, children: stats.totalMs > 0 ? `${Math.round(stats.totalMs)}ms` : "\u2014" })
|
|
3033
|
+
]
|
|
3034
|
+
},
|
|
3035
|
+
name
|
|
3036
|
+
)) })
|
|
3037
|
+
] }),
|
|
3038
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("section", { children: [
|
|
3039
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(Label4, { t, children: [
|
|
3040
|
+
"Skills activated \xB7 ",
|
|
3041
|
+
activatedSkills.size
|
|
3042
|
+
] }),
|
|
3043
|
+
activatedSkills.size === 0 ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { color: t.textSubtle, fontSize: 11, fontStyle: "italic" }, children: "None." }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("ul", { style: { margin: 0, padding: 0, listStyle: "none" }, children: [...activatedSkills].map((id) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
3044
|
+
"li",
|
|
3045
|
+
{
|
|
3046
|
+
style: {
|
|
3047
|
+
padding: "3px 0",
|
|
3048
|
+
fontFamily: t.fontMono,
|
|
3049
|
+
fontSize: 11,
|
|
3050
|
+
color: t.text
|
|
3051
|
+
},
|
|
3052
|
+
children: id
|
|
3053
|
+
},
|
|
3054
|
+
id
|
|
3055
|
+
)) }),
|
|
3056
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { marginTop: 10 }, children: [
|
|
3057
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Label4, { t, children: "Totals" }),
|
|
3058
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
3059
|
+
"div",
|
|
3060
|
+
{
|
|
3061
|
+
style: {
|
|
3062
|
+
display: "grid",
|
|
3063
|
+
gridTemplateColumns: "auto 1fr",
|
|
3064
|
+
gap: "3px 10px",
|
|
3065
|
+
marginTop: 4,
|
|
3066
|
+
fontSize: 11,
|
|
3067
|
+
color: t.textMuted
|
|
3068
|
+
},
|
|
3069
|
+
children: [
|
|
3070
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: "Tokens" }),
|
|
3071
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { style: { color: t.text, fontFamily: t.fontMono }, children: [
|
|
3072
|
+
totalIn.toLocaleString(),
|
|
3073
|
+
" \u2192 ",
|
|
3074
|
+
totalOut.toLocaleString()
|
|
3075
|
+
] }),
|
|
3076
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: "Wall time" }),
|
|
3077
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { style: { color: t.text, fontFamily: t.fontMono }, children: [
|
|
3078
|
+
(totalMs / 1e3).toFixed(2),
|
|
3079
|
+
"s"
|
|
3080
|
+
] }),
|
|
3081
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: "LLM calls" }),
|
|
3082
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { style: { color: t.text, fontFamily: t.fontMono }, children: totalIters }),
|
|
3083
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: "Turns" }),
|
|
3084
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { style: { color: t.text, fontFamily: t.fontMono }, children: completedTurns.length })
|
|
3085
|
+
]
|
|
3086
|
+
}
|
|
3087
|
+
)
|
|
3088
|
+
] })
|
|
3089
|
+
] })
|
|
3090
|
+
]
|
|
3091
|
+
}
|
|
3092
|
+
)
|
|
3093
|
+
]
|
|
3094
|
+
}
|
|
3095
|
+
);
|
|
3096
|
+
}
|
|
3097
|
+
function Label4({
|
|
3098
|
+
t,
|
|
3099
|
+
children
|
|
3100
|
+
}) {
|
|
3101
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
3102
|
+
"div",
|
|
3103
|
+
{
|
|
3104
|
+
style: {
|
|
3105
|
+
fontSize: 10,
|
|
3106
|
+
color: t.textSubtle,
|
|
3107
|
+
textTransform: "uppercase",
|
|
3108
|
+
letterSpacing: "0.08em",
|
|
3109
|
+
fontWeight: 600,
|
|
3110
|
+
marginBottom: 4
|
|
3111
|
+
},
|
|
3112
|
+
children
|
|
3113
|
+
}
|
|
3114
|
+
);
|
|
3115
|
+
}
|
|
3116
|
+
|
|
3117
|
+
// src/adapters/deriveStages.ts
|
|
3118
|
+
function deriveStages(timeline) {
|
|
3119
|
+
const stages = [];
|
|
3120
|
+
let idx = 0;
|
|
3121
|
+
const push = (s) => {
|
|
3122
|
+
stages.push({ ...s, index: idx++ });
|
|
3123
|
+
};
|
|
3124
|
+
let pending = null;
|
|
3125
|
+
const consumePending = (base) => {
|
|
3126
|
+
if (!pending) return base;
|
|
3127
|
+
const merged = { ...base, ...pending };
|
|
3128
|
+
pending = null;
|
|
3129
|
+
return merged;
|
|
3130
|
+
};
|
|
3131
|
+
for (const turn of timeline.turns) {
|
|
3132
|
+
push({
|
|
3133
|
+
from: "user",
|
|
3134
|
+
to: "agent",
|
|
3135
|
+
label: truncate(turn.userPrompt, 60),
|
|
3136
|
+
primitive: "message",
|
|
3137
|
+
turnIndex: turn.index,
|
|
3138
|
+
mutations: consumePending({ messages: true })
|
|
3139
|
+
});
|
|
3140
|
+
for (const iter of turn.iterations) {
|
|
3141
|
+
const parallelCount = iter.toolCalls.length > 1 ? iter.toolCalls.length : void 0;
|
|
3142
|
+
for (const tc of iter.toolCalls) {
|
|
3143
|
+
const kind = classifyTool(tc);
|
|
3144
|
+
if (kind === "skill-management") {
|
|
3145
|
+
push({
|
|
3146
|
+
from: "agent",
|
|
3147
|
+
to: "tool",
|
|
3148
|
+
alsoLights: "skill",
|
|
3149
|
+
label: skillManagementLabel(tc),
|
|
3150
|
+
primitive: "tool",
|
|
3151
|
+
turnIndex: turn.index,
|
|
3152
|
+
iterIndex: iter.index,
|
|
3153
|
+
toolName: tc.name,
|
|
3154
|
+
toolKind: "skill",
|
|
3155
|
+
mutations: consumePending({ messages: true })
|
|
3156
|
+
});
|
|
3157
|
+
const isReadSkill = tc.name === "read_skill";
|
|
3158
|
+
push({
|
|
3159
|
+
from: "tool",
|
|
3160
|
+
to: "agent",
|
|
3161
|
+
alsoLights: "skill",
|
|
3162
|
+
label: isReadSkill ? `Skill body delivered (+${tc.result.length} chars) \u2014 will activate next step` : `Skills list (${countSkills(tc.result)} skills)`,
|
|
3163
|
+
primitive: "tool",
|
|
3164
|
+
turnIndex: turn.index,
|
|
3165
|
+
iterIndex: iter.index,
|
|
3166
|
+
toolName: tc.name,
|
|
3167
|
+
toolKind: "skill",
|
|
3168
|
+
mutations: { messages: true }
|
|
3169
|
+
});
|
|
3170
|
+
if (isReadSkill) {
|
|
3171
|
+
const spDelta = tc.result.length;
|
|
3172
|
+
const activatedSkillId = tc.arguments?.id ?? void 0;
|
|
3173
|
+
pending = {
|
|
3174
|
+
systemPrompt: true,
|
|
3175
|
+
tools: true,
|
|
3176
|
+
systemPromptDeltaChars: spDelta,
|
|
3177
|
+
// Stash the ACTUAL content that just entered the System
|
|
3178
|
+
// Prompt + the skill id that activated. These ride along
|
|
3179
|
+
// `pending` and land on the next outgoing LLM edge where
|
|
3180
|
+
// the mutation is attributed, so the UI can render a
|
|
3181
|
+
// real diff instead of a "not captured" placeholder.
|
|
3182
|
+
systemPromptAdded: tc.result,
|
|
3183
|
+
...activatedSkillId ? { activatedSkillId } : {}
|
|
3184
|
+
};
|
|
3185
|
+
}
|
|
3186
|
+
} else if (kind === "ask-human") {
|
|
3187
|
+
push({
|
|
3188
|
+
from: "agent",
|
|
3189
|
+
to: "user",
|
|
3190
|
+
label: askHumanLabel(tc),
|
|
3191
|
+
primitive: "message",
|
|
3192
|
+
turnIndex: turn.index,
|
|
3193
|
+
iterIndex: iter.index,
|
|
3194
|
+
toolName: tc.name,
|
|
3195
|
+
toolKind: "ask-human",
|
|
3196
|
+
mutations: consumePending({ messages: true })
|
|
3197
|
+
});
|
|
3198
|
+
} else {
|
|
3199
|
+
push({
|
|
3200
|
+
from: "agent",
|
|
3201
|
+
to: "tool",
|
|
3202
|
+
label: `Called ${tc.name}`,
|
|
3203
|
+
primitive: "tool",
|
|
3204
|
+
turnIndex: turn.index,
|
|
3205
|
+
iterIndex: iter.index,
|
|
3206
|
+
toolName: tc.name,
|
|
3207
|
+
...parallelCount ? { parallelCount } : {},
|
|
3208
|
+
mutations: consumePending({ messages: true })
|
|
3209
|
+
});
|
|
3210
|
+
push({
|
|
3211
|
+
from: "tool",
|
|
3212
|
+
to: "agent",
|
|
3213
|
+
label: truncate(tc.result, 80),
|
|
3214
|
+
primitive: "tool",
|
|
3215
|
+
turnIndex: turn.index,
|
|
3216
|
+
iterIndex: iter.index,
|
|
3217
|
+
toolName: tc.name,
|
|
3218
|
+
...parallelCount ? { parallelCount } : {},
|
|
3219
|
+
mutations: { messages: true }
|
|
3220
|
+
});
|
|
3221
|
+
}
|
|
3222
|
+
}
|
|
3223
|
+
}
|
|
3224
|
+
if (turn.finalContent) {
|
|
3225
|
+
const lastIter = turn.iterations[turn.iterations.length - 1];
|
|
3226
|
+
push({
|
|
3227
|
+
from: "agent",
|
|
3228
|
+
to: "user",
|
|
3229
|
+
label: truncate(turn.finalContent, 80),
|
|
3230
|
+
primitive: "message",
|
|
3231
|
+
turnIndex: turn.index,
|
|
3232
|
+
...lastIter ? { iterIndex: lastIter.index } : {},
|
|
3233
|
+
mutations: consumePending({ messages: true })
|
|
3234
|
+
});
|
|
3235
|
+
}
|
|
3236
|
+
}
|
|
3237
|
+
return stages;
|
|
3238
|
+
}
|
|
3239
|
+
function classifyTool(tc) {
|
|
3240
|
+
if (tc.name === "list_skills" || tc.name === "read_skill") return "skill-management";
|
|
3241
|
+
if (tc.name === "ask_human" || tc.name === "ask_user") return "ask-human";
|
|
3242
|
+
return "regular";
|
|
3243
|
+
}
|
|
3244
|
+
function skillManagementLabel(tc) {
|
|
3245
|
+
if (tc.name === "list_skills") return "Asked what skills are available";
|
|
3246
|
+
if (tc.name === "read_skill") {
|
|
3247
|
+
const id = tc.arguments?.id ?? "?";
|
|
3248
|
+
return `Activated the "${id}" skill`;
|
|
3249
|
+
}
|
|
3250
|
+
return `Called ${tc.name}`;
|
|
3251
|
+
}
|
|
3252
|
+
function askHumanLabel(tc) {
|
|
3253
|
+
const q = tc.arguments?.question ?? "";
|
|
3254
|
+
return q ? `Asked user: ${truncate(q, 50)}` : "Asked user for clarification";
|
|
3255
|
+
}
|
|
3256
|
+
function countSkills(result) {
|
|
3257
|
+
try {
|
|
3258
|
+
const parsed = JSON.parse(result);
|
|
3259
|
+
if (Array.isArray(parsed?.skills)) return parsed.skills.length;
|
|
3260
|
+
if (Array.isArray(parsed)) return parsed.length;
|
|
3261
|
+
} catch {
|
|
3262
|
+
}
|
|
3263
|
+
return 0;
|
|
3264
|
+
}
|
|
3265
|
+
function truncate(s, max) {
|
|
3266
|
+
const one = s.replace(/\s+/g, " ").trim();
|
|
3267
|
+
return one.length <= max ? one : one.slice(0, max - 1).trim() + "\u2026";
|
|
3268
|
+
}
|
|
3269
|
+
|
|
3270
|
+
// src/AgentLens.tsx
|
|
3271
|
+
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
3272
|
+
function AgentLens({
|
|
3273
|
+
runtimeSnapshot,
|
|
3274
|
+
timeline: providedTimeline,
|
|
3275
|
+
systemPrompt,
|
|
3276
|
+
onToolCallClick,
|
|
3277
|
+
skills,
|
|
3278
|
+
activeSkillId
|
|
3279
|
+
}) {
|
|
3280
|
+
const t = useLensTheme();
|
|
3281
|
+
const timeline = (0, import_react6.useMemo)(() => {
|
|
3282
|
+
if (providedTimeline) return providedTimeline;
|
|
3283
|
+
if (!runtimeSnapshot) return null;
|
|
3284
|
+
return fromAgentSnapshot(runtimeSnapshot);
|
|
3285
|
+
}, [providedTimeline, runtimeSnapshot]);
|
|
3286
|
+
const [selectedIterKey, setSelectedIterKey] = (0, import_react6.useState)(null);
|
|
3287
|
+
const [skillsOpen, setSkillsOpen] = (0, import_react6.useState)(false);
|
|
3288
|
+
const derivedActiveSkill = activeSkillId ?? (typeof timeline?.finalDecision?.currentSkill === "string" ? timeline.finalDecision.currentSkill : null);
|
|
3289
|
+
(0, import_react6.useEffect)(() => {
|
|
3290
|
+
if (!skillsOpen) return;
|
|
3291
|
+
const onKey = (e) => {
|
|
3292
|
+
if (e.key === "Escape") setSkillsOpen(false);
|
|
3293
|
+
};
|
|
3294
|
+
window.addEventListener("keydown", onKey);
|
|
3295
|
+
return () => window.removeEventListener("keydown", onKey);
|
|
3296
|
+
}, [skillsOpen]);
|
|
3297
|
+
const handleToolClick = (0, import_react6.useCallback)(
|
|
3298
|
+
(inv) => {
|
|
3299
|
+
setSelectedIterKey(`${inv.turnIndex}.${inv.iterationIndex}`);
|
|
3300
|
+
onToolCallClick?.(inv);
|
|
3301
|
+
},
|
|
3302
|
+
[onToolCallClick]
|
|
3303
|
+
);
|
|
3304
|
+
if (!timeline) {
|
|
3305
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
3306
|
+
"div",
|
|
3307
|
+
{
|
|
3308
|
+
"data-fp-lens": "empty",
|
|
3309
|
+
style: {
|
|
3310
|
+
padding: 32,
|
|
3311
|
+
color: t.textMuted,
|
|
3312
|
+
fontFamily: t.fontSans,
|
|
3313
|
+
textAlign: "center",
|
|
3314
|
+
background: t.bg
|
|
3315
|
+
},
|
|
3316
|
+
children: [
|
|
3317
|
+
"No agent run to show yet. Pass ",
|
|
3318
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("code", { children: "runtimeSnapshot" }),
|
|
3319
|
+
" after the agent runs."
|
|
3320
|
+
]
|
|
3321
|
+
}
|
|
3322
|
+
);
|
|
3323
|
+
}
|
|
3324
|
+
const derivedSystemPrompt = systemPrompt ?? (typeof timeline.rawSnapshot?.sharedState?.systemPrompt === "string" ? timeline.rawSnapshot.sharedState.systemPrompt : void 0);
|
|
3325
|
+
const stages = (0, import_react6.useMemo)(() => timeline ? deriveStages(timeline) : [], [timeline]);
|
|
3326
|
+
const [focusIndex, setFocusIndex] = (0, import_react6.useState)(-1);
|
|
3327
|
+
const liveIndex = stages.length - 1;
|
|
3328
|
+
const resolvedFocus = focusIndex === -1 ? liveIndex : Math.min(focusIndex, liveIndex);
|
|
3329
|
+
const isLive = focusIndex === -1;
|
|
3330
|
+
const liveIndexRef = (0, import_react6.useRef)(liveIndex);
|
|
3331
|
+
liveIndexRef.current = liveIndex;
|
|
3332
|
+
const handleFocusChange = (0, import_react6.useCallback)((i) => {
|
|
3333
|
+
setFocusIndex(i >= liveIndexRef.current ? -1 : i);
|
|
3334
|
+
}, []);
|
|
3335
|
+
(0, import_react6.useEffect)(() => {
|
|
3336
|
+
if (stages.length === 0) return;
|
|
3337
|
+
const onKey = (e) => {
|
|
3338
|
+
if (skillsOpen) return;
|
|
3339
|
+
if (e.key !== "ArrowLeft" && e.key !== "ArrowRight") return;
|
|
3340
|
+
const tgt = e.target;
|
|
3341
|
+
const tag = tgt?.tagName;
|
|
3342
|
+
if (tag === "INPUT" || tag === "TEXTAREA" || tag === "SELECT" || tgt?.isContentEditable) return;
|
|
3343
|
+
const delta = e.key === "ArrowLeft" ? -1 : 1;
|
|
3344
|
+
const next = Math.min(
|
|
3345
|
+
liveIndex,
|
|
3346
|
+
Math.max(0, resolvedFocus + delta)
|
|
3347
|
+
);
|
|
3348
|
+
handleFocusChange(next);
|
|
3349
|
+
e.preventDefault();
|
|
3350
|
+
};
|
|
3351
|
+
window.addEventListener("keydown", onKey);
|
|
3352
|
+
return () => window.removeEventListener("keydown", onKey);
|
|
3353
|
+
}, [resolvedFocus, liveIndex, stages.length, skillsOpen]);
|
|
3354
|
+
const handleEdgeClick = (0, import_react6.useCallback)(
|
|
3355
|
+
(stage) => {
|
|
3356
|
+
if (stage.iterIndex === void 0) return;
|
|
3357
|
+
setSelectedIterKey(`${stage.turnIndex}.${stage.iterIndex}`);
|
|
3358
|
+
handleFocusChange(stage.index);
|
|
3359
|
+
},
|
|
3360
|
+
[handleFocusChange]
|
|
3361
|
+
);
|
|
3362
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
3363
|
+
"div",
|
|
3364
|
+
{
|
|
3365
|
+
"data-fp-lens": "shell",
|
|
3366
|
+
style: {
|
|
3367
|
+
display: "grid",
|
|
3368
|
+
// Top: TimeTravel slider (tt) + Skills button trailing on the
|
|
3369
|
+
// right. Middle-left: vertical StageFlow. Middle-right: AskCard
|
|
3370
|
+
// with current question + active step detail. Below: MessagesPanel
|
|
3371
|
+
// full width. Footer: RunSummary (only after first turn completes).
|
|
3372
|
+
gridTemplateColumns: "minmax(320px, 1fr) minmax(220px, 320px)",
|
|
3373
|
+
gridTemplateRows: "auto auto minmax(0, 1fr) auto",
|
|
3374
|
+
gridTemplateAreas: '"tt tt" "graph ask" "messages messages" "summary summary"',
|
|
3375
|
+
// Self-constraining sizing contract — Lens never requires the
|
|
3376
|
+
// host to get their flex chain exactly right.
|
|
3377
|
+
//
|
|
3378
|
+
// • `maxHeight: 100dvh` is the hard cap. Even if NOTHING
|
|
3379
|
+
// upstream delivers a bounded height, the shell can never
|
|
3380
|
+
// exceed the viewport. This is what makes the grid's
|
|
3381
|
+
// `minmax(0, 1fr)` messages row actually resolve to a
|
|
3382
|
+
// bounded number of pixels instead of expanding to content.
|
|
3383
|
+
// • `height: 100%` + `flex: 1 1 0%` let well-constrained
|
|
3384
|
+
// hosts still shrink Lens below the viewport cap when they
|
|
3385
|
+
// want a narrower sidebar.
|
|
3386
|
+
// • `overflow: hidden` clips children that would otherwise
|
|
3387
|
+
// blow past the grid and make scrollHeight == clientHeight
|
|
3388
|
+
// on MessagesPanel (the exact bug this block prevents).
|
|
3389
|
+
// • `minHeight: 0` unblocks grid + flex size resolution.
|
|
3390
|
+
flex: "1 1 0%",
|
|
3391
|
+
minHeight: 0,
|
|
3392
|
+
height: "100%",
|
|
3393
|
+
maxHeight: "100dvh",
|
|
3394
|
+
overflow: "hidden",
|
|
3395
|
+
background: t.bg,
|
|
3396
|
+
color: t.text,
|
|
3397
|
+
fontFamily: t.fontSans
|
|
3398
|
+
},
|
|
3399
|
+
children: [
|
|
3400
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("style", { children: `
|
|
3401
|
+
[data-iter-selected="true"] {
|
|
3402
|
+
outline-color: currentColor !important;
|
|
3403
|
+
background: color-mix(in srgb, currentColor 8%, transparent);
|
|
3404
|
+
}
|
|
3405
|
+
` }),
|
|
3406
|
+
stages.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
|
|
3407
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
3408
|
+
"div",
|
|
3409
|
+
{
|
|
3410
|
+
style: {
|
|
3411
|
+
gridArea: "tt",
|
|
3412
|
+
display: "flex",
|
|
3413
|
+
alignItems: "center"
|
|
3414
|
+
},
|
|
3415
|
+
children: [
|
|
3416
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: { flex: 1, minWidth: 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
3417
|
+
TimeTravel,
|
|
3418
|
+
{
|
|
3419
|
+
stages,
|
|
3420
|
+
focusIndex: resolvedFocus,
|
|
3421
|
+
onFocusChange: handleFocusChange,
|
|
3422
|
+
isLive
|
|
3423
|
+
}
|
|
3424
|
+
) }),
|
|
3425
|
+
skills && skills.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
3426
|
+
"button",
|
|
3427
|
+
{
|
|
3428
|
+
onClick: () => setSkillsOpen(true),
|
|
3429
|
+
title: "See all skills registered with the agent",
|
|
3430
|
+
style: {
|
|
3431
|
+
// Borderless — rides on the same airy feel as the
|
|
3432
|
+
// floating time-travel pill. A faint translucent fill
|
|
3433
|
+
// on hover keeps it discoverable.
|
|
3434
|
+
background: "transparent",
|
|
3435
|
+
border: "none",
|
|
3436
|
+
color: t.textMuted,
|
|
3437
|
+
padding: "0 16px",
|
|
3438
|
+
margin: "0 14px 0 0",
|
|
3439
|
+
fontSize: 12,
|
|
3440
|
+
cursor: "pointer",
|
|
3441
|
+
whiteSpace: "nowrap",
|
|
3442
|
+
display: "flex",
|
|
3443
|
+
alignItems: "center",
|
|
3444
|
+
gap: 6,
|
|
3445
|
+
fontWeight: 400,
|
|
3446
|
+
width: "auto"
|
|
3447
|
+
},
|
|
3448
|
+
children: [
|
|
3449
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { "aria-hidden": "true", children: "\u{1F4DA}" }),
|
|
3450
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { children: [
|
|
3451
|
+
"Skills \xB7 ",
|
|
3452
|
+
skills.length
|
|
3453
|
+
] }),
|
|
3454
|
+
derivedActiveSkill && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
3455
|
+
"span",
|
|
3456
|
+
{
|
|
3457
|
+
style: {
|
|
3458
|
+
fontSize: 9,
|
|
3459
|
+
padding: "1px 5px",
|
|
3460
|
+
borderRadius: 3,
|
|
3461
|
+
background: `color-mix(in srgb, ${t.success} 25%, transparent)`,
|
|
3462
|
+
color: t.success,
|
|
3463
|
+
fontWeight: 600,
|
|
3464
|
+
textTransform: "uppercase"
|
|
3465
|
+
},
|
|
3466
|
+
children: derivedActiveSkill
|
|
3467
|
+
}
|
|
3468
|
+
)
|
|
3469
|
+
]
|
|
3470
|
+
}
|
|
3471
|
+
)
|
|
3472
|
+
]
|
|
3473
|
+
}
|
|
3474
|
+
),
|
|
3475
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
3476
|
+
"div",
|
|
3477
|
+
{
|
|
3478
|
+
style: {
|
|
3479
|
+
gridArea: "graph",
|
|
3480
|
+
minHeight: 0,
|
|
3481
|
+
overflow: "hidden",
|
|
3482
|
+
borderRight: `1px solid ${t.border}`
|
|
3483
|
+
},
|
|
3484
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
3485
|
+
StageFlow,
|
|
3486
|
+
{
|
|
3487
|
+
stages,
|
|
3488
|
+
focusIndex: resolvedFocus,
|
|
3489
|
+
onEdgeClick: handleEdgeClick,
|
|
3490
|
+
activeSkillId: derivedActiveSkill
|
|
3491
|
+
}
|
|
3492
|
+
)
|
|
3493
|
+
}
|
|
3494
|
+
),
|
|
3495
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
3496
|
+
"div",
|
|
3497
|
+
{
|
|
3498
|
+
style: {
|
|
3499
|
+
gridArea: "ask",
|
|
3500
|
+
minHeight: 0,
|
|
3501
|
+
overflow: "hidden",
|
|
3502
|
+
background: t.bg
|
|
3503
|
+
},
|
|
3504
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
3505
|
+
AskCard,
|
|
3506
|
+
{
|
|
3507
|
+
timeline,
|
|
3508
|
+
stages,
|
|
3509
|
+
focusIndex: resolvedFocus
|
|
3510
|
+
}
|
|
3511
|
+
)
|
|
3512
|
+
}
|
|
3513
|
+
)
|
|
3514
|
+
] }),
|
|
3515
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
3516
|
+
"div",
|
|
3517
|
+
{
|
|
3518
|
+
style: {
|
|
3519
|
+
gridArea: "messages",
|
|
3520
|
+
minHeight: 0,
|
|
3521
|
+
overflow: "hidden",
|
|
3522
|
+
// `position: relative` is the containing block for the
|
|
3523
|
+
// absolutely-positioned MessagesPanel inside. This is the
|
|
3524
|
+
// mechanism that forces the panel's height to match this
|
|
3525
|
+
// cell exactly, no matter what the upstream flex/grid
|
|
3526
|
+
// chain does.
|
|
3527
|
+
position: "relative"
|
|
3528
|
+
},
|
|
3529
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
3530
|
+
MessagesPanel,
|
|
3531
|
+
{
|
|
3532
|
+
timeline,
|
|
3533
|
+
onToolCallClick: handleToolClick,
|
|
3534
|
+
selectedIterKey,
|
|
3535
|
+
stages,
|
|
3536
|
+
focusIndex: resolvedFocus,
|
|
3537
|
+
onFocusChange: handleFocusChange,
|
|
3538
|
+
isLive,
|
|
3539
|
+
...derivedSystemPrompt && { systemPrompt: derivedSystemPrompt }
|
|
3540
|
+
}
|
|
3541
|
+
)
|
|
3542
|
+
}
|
|
3543
|
+
),
|
|
3544
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: { gridArea: "summary" }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(RunSummary, { timeline }) }),
|
|
3545
|
+
skillsOpen && skills && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
3546
|
+
SkillsPanel,
|
|
3547
|
+
{
|
|
3548
|
+
skills,
|
|
3549
|
+
activeSkillId: derivedActiveSkill,
|
|
3550
|
+
onClose: () => setSkillsOpen(false)
|
|
3551
|
+
}
|
|
3552
|
+
)
|
|
3553
|
+
]
|
|
3554
|
+
}
|
|
3555
|
+
);
|
|
3556
|
+
}
|
|
3557
|
+
|
|
3558
|
+
// src/panels/IterationStrip.tsx
|
|
3559
|
+
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
3560
|
+
function IterationStrip({ timeline, selectedKey, onSelect }) {
|
|
836
3561
|
const t = useLensTheme();
|
|
837
3562
|
const chips = timeline.turns.flatMap(
|
|
838
3563
|
(turn) => turn.iterations.map((iter, stepIdx) => ({
|
|
@@ -845,7 +3570,7 @@ function IterationStrip({ timeline, selectedKey, onSelect }) {
|
|
|
845
3570
|
toolCount: iter.toolCalls.length
|
|
846
3571
|
}))
|
|
847
3572
|
);
|
|
848
|
-
return /* @__PURE__ */ (0,
|
|
3573
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
849
3574
|
"div",
|
|
850
3575
|
{
|
|
851
3576
|
"data-fp-lens": "iteration-strip",
|
|
@@ -858,12 +3583,12 @@ function IterationStrip({ timeline, selectedKey, onSelect }) {
|
|
|
858
3583
|
background: t.bgElev
|
|
859
3584
|
},
|
|
860
3585
|
children: [
|
|
861
|
-
chips.length === 0 && /* @__PURE__ */ (0,
|
|
3586
|
+
chips.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { style: { color: t.textSubtle, fontSize: 11 }, children: "No iterations yet." }),
|
|
862
3587
|
chips.map((c) => {
|
|
863
3588
|
const active = c.key === selectedKey;
|
|
864
3589
|
const isFinal = c.toolCount === 0;
|
|
865
3590
|
const secs = c.durationMs >= 1e3 ? `${(c.durationMs / 1e3).toFixed(1)}s` : `${Math.round(c.durationMs)}ms`;
|
|
866
|
-
return /* @__PURE__ */ (0,
|
|
3591
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
867
3592
|
"button",
|
|
868
3593
|
{
|
|
869
3594
|
onClick: () => onSelect?.(c.key),
|
|
@@ -884,15 +3609,15 @@ function IterationStrip({ timeline, selectedKey, onSelect }) {
|
|
|
884
3609
|
},
|
|
885
3610
|
title: `Question ${c.turn} \xB7 Step ${c.step} \xB7 ${secs}${c.stopReason ? ` \xB7 stop: ${c.stopReason}` : ""}`,
|
|
886
3611
|
children: [
|
|
887
|
-
/* @__PURE__ */ (0,
|
|
3612
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { style: { fontWeight: 600 }, children: [
|
|
888
3613
|
"Step ",
|
|
889
3614
|
c.step
|
|
890
3615
|
] }),
|
|
891
|
-
/* @__PURE__ */ (0,
|
|
3616
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { style: { opacity: 0.85 }, children: [
|
|
892
3617
|
" \xB7 ",
|
|
893
3618
|
c.label
|
|
894
3619
|
] }),
|
|
895
|
-
isFinal && /* @__PURE__ */ (0,
|
|
3620
|
+
isFinal && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { style: { marginLeft: 6 }, children: "\u2713" })
|
|
896
3621
|
]
|
|
897
3622
|
},
|
|
898
3623
|
c.key
|
|
@@ -911,23 +3636,26 @@ function stepHeadline(iter) {
|
|
|
911
3636
|
const id = tc.arguments?.id;
|
|
912
3637
|
return id ? `Activated ${id}` : "Activating skill";
|
|
913
3638
|
}
|
|
914
|
-
|
|
3639
|
+
if (tc.name === "ask_human" || tc.name === "ask_user") {
|
|
3640
|
+
return "Asked user";
|
|
3641
|
+
}
|
|
3642
|
+
return `Called tool (${tc.name})`;
|
|
915
3643
|
}
|
|
916
3644
|
if (iter.toolCalls.length <= 3) {
|
|
917
|
-
return `Called ${iter.toolCalls.map((tc) => tc.name).join(", ")}`;
|
|
3645
|
+
return `Called ${iter.toolCalls.length} tools (${iter.toolCalls.map((tc) => tc.name).join(", ")})`;
|
|
918
3646
|
}
|
|
919
3647
|
return `Called ${iter.toolCalls.length} tools in parallel`;
|
|
920
3648
|
}
|
|
921
3649
|
|
|
922
3650
|
// src/panels/ToolCallInspector.tsx
|
|
923
|
-
var
|
|
3651
|
+
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
924
3652
|
function ToolCallInspector({
|
|
925
3653
|
timeline,
|
|
926
3654
|
selectedId,
|
|
927
3655
|
onSelect
|
|
928
3656
|
}) {
|
|
929
3657
|
const t = useLensTheme();
|
|
930
|
-
return /* @__PURE__ */ (0,
|
|
3658
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
931
3659
|
"div",
|
|
932
3660
|
{
|
|
933
3661
|
"data-fp-lens": "tool-call-inspector",
|
|
@@ -941,7 +3669,7 @@ function ToolCallInspector({
|
|
|
941
3669
|
overflow: "hidden"
|
|
942
3670
|
},
|
|
943
3671
|
children: [
|
|
944
|
-
/* @__PURE__ */ (0,
|
|
3672
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
945
3673
|
"div",
|
|
946
3674
|
{
|
|
947
3675
|
style: {
|
|
@@ -960,12 +3688,12 @@ function ToolCallInspector({
|
|
|
960
3688
|
]
|
|
961
3689
|
}
|
|
962
3690
|
),
|
|
963
|
-
/* @__PURE__ */ (0,
|
|
964
|
-
timeline.tools.length === 0 && /* @__PURE__ */ (0,
|
|
3691
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: { overflow: "auto", flex: 1 }, children: [
|
|
3692
|
+
timeline.tools.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: { padding: 14, color: t.textSubtle, fontSize: 12 }, children: "Neo hasn't called any tools yet." }),
|
|
965
3693
|
timeline.tools.map((tc) => {
|
|
966
3694
|
const active = tc.id === selectedId;
|
|
967
3695
|
const errored = tc.error === true;
|
|
968
|
-
return /* @__PURE__ */ (0,
|
|
3696
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
969
3697
|
"button",
|
|
970
3698
|
{
|
|
971
3699
|
onClick: () => onSelect?.(tc),
|
|
@@ -985,7 +3713,7 @@ function ToolCallInspector({
|
|
|
985
3713
|
fontFamily: "inherit"
|
|
986
3714
|
},
|
|
987
3715
|
children: [
|
|
988
|
-
/* @__PURE__ */ (0,
|
|
3716
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
989
3717
|
"div",
|
|
990
3718
|
{
|
|
991
3719
|
style: {
|
|
@@ -996,8 +3724,8 @@ function ToolCallInspector({
|
|
|
996
3724
|
fontFamily: t.fontMono
|
|
997
3725
|
},
|
|
998
3726
|
children: [
|
|
999
|
-
/* @__PURE__ */ (0,
|
|
1000
|
-
/* @__PURE__ */ (0,
|
|
3727
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { style: { color: errored ? t.error : t.accent, fontWeight: 600 }, children: tc.name }),
|
|
3728
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
1001
3729
|
"span",
|
|
1002
3730
|
{
|
|
1003
3731
|
style: { color: t.textSubtle, fontSize: 10, marginLeft: "auto" },
|
|
@@ -1013,7 +3741,7 @@ function ToolCallInspector({
|
|
|
1013
3741
|
]
|
|
1014
3742
|
}
|
|
1015
3743
|
),
|
|
1016
|
-
/* @__PURE__ */ (0,
|
|
3744
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1017
3745
|
"div",
|
|
1018
3746
|
{
|
|
1019
3747
|
style: {
|
|
@@ -1049,111 +3777,6 @@ function shortArgs2(args) {
|
|
|
1049
3777
|
}).join(", ");
|
|
1050
3778
|
}
|
|
1051
3779
|
|
|
1052
|
-
// src/AgentLens.tsx
|
|
1053
|
-
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
1054
|
-
function AgentLens({
|
|
1055
|
-
runtimeSnapshot,
|
|
1056
|
-
timeline: providedTimeline,
|
|
1057
|
-
systemPrompt,
|
|
1058
|
-
onToolCallClick
|
|
1059
|
-
}) {
|
|
1060
|
-
const t = useLensTheme();
|
|
1061
|
-
const timeline = (0, import_react2.useMemo)(() => {
|
|
1062
|
-
if (providedTimeline) return providedTimeline;
|
|
1063
|
-
if (!runtimeSnapshot) return null;
|
|
1064
|
-
return fromAgentSnapshot(runtimeSnapshot);
|
|
1065
|
-
}, [providedTimeline, runtimeSnapshot]);
|
|
1066
|
-
const [selectedToolId, setSelectedToolId] = (0, import_react2.useState)(null);
|
|
1067
|
-
const [selectedIterKey, setSelectedIterKey] = (0, import_react2.useState)(null);
|
|
1068
|
-
function handleToolClick(inv) {
|
|
1069
|
-
setSelectedToolId(inv.id);
|
|
1070
|
-
setSelectedIterKey(`${inv.turnIndex}.${inv.iterationIndex}`);
|
|
1071
|
-
onToolCallClick?.(inv);
|
|
1072
|
-
}
|
|
1073
|
-
if (!timeline) {
|
|
1074
|
-
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
1075
|
-
"div",
|
|
1076
|
-
{
|
|
1077
|
-
"data-fp-lens": "empty",
|
|
1078
|
-
style: {
|
|
1079
|
-
padding: 32,
|
|
1080
|
-
color: t.textMuted,
|
|
1081
|
-
fontFamily: t.fontSans,
|
|
1082
|
-
textAlign: "center",
|
|
1083
|
-
background: t.bg
|
|
1084
|
-
},
|
|
1085
|
-
children: [
|
|
1086
|
-
"No agent run to show yet. Pass ",
|
|
1087
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("code", { children: "runtimeSnapshot" }),
|
|
1088
|
-
" after the agent runs."
|
|
1089
|
-
]
|
|
1090
|
-
}
|
|
1091
|
-
);
|
|
1092
|
-
}
|
|
1093
|
-
const derivedSystemPrompt = systemPrompt ?? (typeof timeline.rawSnapshot?.sharedState?.systemPrompt === "string" ? timeline.rawSnapshot.sharedState.systemPrompt : void 0);
|
|
1094
|
-
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
1095
|
-
"div",
|
|
1096
|
-
{
|
|
1097
|
-
"data-fp-lens": "shell",
|
|
1098
|
-
style: {
|
|
1099
|
-
display: "grid",
|
|
1100
|
-
gridTemplateColumns: "1fr 320px",
|
|
1101
|
-
gridTemplateRows: "auto 1fr",
|
|
1102
|
-
gridTemplateAreas: '"strip strip" "messages inspector"',
|
|
1103
|
-
height: "100%",
|
|
1104
|
-
minHeight: 0,
|
|
1105
|
-
background: t.bg,
|
|
1106
|
-
color: t.text,
|
|
1107
|
-
fontFamily: t.fontSans
|
|
1108
|
-
},
|
|
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
|
-
` }),
|
|
1116
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: { gridArea: "strip" }, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1117
|
-
IterationStrip,
|
|
1118
|
-
{
|
|
1119
|
-
timeline,
|
|
1120
|
-
selectedKey: selectedIterKey,
|
|
1121
|
-
onSelect: setSelectedIterKey
|
|
1122
|
-
}
|
|
1123
|
-
) }),
|
|
1124
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: { gridArea: "messages", minHeight: 0, overflow: "hidden" }, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1125
|
-
MessagesPanel,
|
|
1126
|
-
{
|
|
1127
|
-
timeline,
|
|
1128
|
-
onToolCallClick: handleToolClick,
|
|
1129
|
-
selectedIterKey,
|
|
1130
|
-
...derivedSystemPrompt && { systemPrompt: derivedSystemPrompt }
|
|
1131
|
-
}
|
|
1132
|
-
) }),
|
|
1133
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1134
|
-
"div",
|
|
1135
|
-
{
|
|
1136
|
-
style: {
|
|
1137
|
-
gridArea: "inspector",
|
|
1138
|
-
minHeight: 0,
|
|
1139
|
-
overflow: "hidden",
|
|
1140
|
-
borderLeft: `1px solid ${t.border}`
|
|
1141
|
-
},
|
|
1142
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1143
|
-
ToolCallInspector,
|
|
1144
|
-
{
|
|
1145
|
-
timeline,
|
|
1146
|
-
selectedId: selectedToolId,
|
|
1147
|
-
onSelect: handleToolClick
|
|
1148
|
-
}
|
|
1149
|
-
)
|
|
1150
|
-
}
|
|
1151
|
-
)
|
|
1152
|
-
]
|
|
1153
|
-
}
|
|
1154
|
-
);
|
|
1155
|
-
}
|
|
1156
|
-
|
|
1157
3780
|
// src/adapters/LiveTimelineBuilder.ts
|
|
1158
3781
|
var LiveTimelineBuilder = class {
|
|
1159
3782
|
constructor() {
|
|
@@ -1338,48 +3961,48 @@ var LiveTimelineBuilder = class {
|
|
|
1338
3961
|
};
|
|
1339
3962
|
|
|
1340
3963
|
// src/adapters/useLiveTimeline.ts
|
|
1341
|
-
var
|
|
3964
|
+
var import_react7 = require("react");
|
|
1342
3965
|
function useLiveTimeline() {
|
|
1343
|
-
const builderRef = (0,
|
|
3966
|
+
const builderRef = (0, import_react7.useRef)(null);
|
|
1344
3967
|
if (!builderRef.current) builderRef.current = new LiveTimelineBuilder();
|
|
1345
3968
|
const builder = builderRef.current;
|
|
1346
|
-
const [timeline, setTimeline] = (0,
|
|
1347
|
-
const sync = (0,
|
|
3969
|
+
const [timeline, setTimeline] = (0, import_react7.useState)(() => builder.getTimeline());
|
|
3970
|
+
const sync = (0, import_react7.useCallback)(() => {
|
|
1348
3971
|
setTimeline(builder.getTimeline());
|
|
1349
3972
|
}, [builder]);
|
|
1350
|
-
const ingest = (0,
|
|
3973
|
+
const ingest = (0, import_react7.useCallback)(
|
|
1351
3974
|
(event) => {
|
|
1352
3975
|
builder.ingest(event);
|
|
1353
3976
|
sync();
|
|
1354
3977
|
},
|
|
1355
3978
|
[builder, sync]
|
|
1356
3979
|
);
|
|
1357
|
-
const startTurn = (0,
|
|
3980
|
+
const startTurn = (0, import_react7.useCallback)(
|
|
1358
3981
|
(userPrompt) => {
|
|
1359
3982
|
builder.startTurn(userPrompt);
|
|
1360
3983
|
sync();
|
|
1361
3984
|
},
|
|
1362
3985
|
[builder, sync]
|
|
1363
3986
|
);
|
|
1364
|
-
const setSystemPrompt = (0,
|
|
3987
|
+
const setSystemPrompt = (0, import_react7.useCallback)(
|
|
1365
3988
|
(prompt) => {
|
|
1366
3989
|
builder.setSystemPrompt(prompt);
|
|
1367
3990
|
sync();
|
|
1368
3991
|
},
|
|
1369
3992
|
[builder, sync]
|
|
1370
3993
|
);
|
|
1371
|
-
const setFinalDecision = (0,
|
|
3994
|
+
const setFinalDecision = (0, import_react7.useCallback)(
|
|
1372
3995
|
(decision) => {
|
|
1373
3996
|
builder.setFinalDecision(decision);
|
|
1374
3997
|
sync();
|
|
1375
3998
|
},
|
|
1376
3999
|
[builder, sync]
|
|
1377
4000
|
);
|
|
1378
|
-
const reset = (0,
|
|
4001
|
+
const reset = (0, import_react7.useCallback)(() => {
|
|
1379
4002
|
builder.reset();
|
|
1380
4003
|
sync();
|
|
1381
4004
|
}, [builder, sync]);
|
|
1382
|
-
return (0,
|
|
4005
|
+
return (0, import_react7.useMemo)(
|
|
1383
4006
|
() => ({ timeline, ingest, startTurn, setSystemPrompt, setFinalDecision, reset, builder }),
|
|
1384
4007
|
[timeline, ingest, startTurn, setSystemPrompt, setFinalDecision, reset, builder]
|
|
1385
4008
|
);
|
|
@@ -1387,10 +4010,16 @@ function useLiveTimeline() {
|
|
|
1387
4010
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1388
4011
|
0 && (module.exports = {
|
|
1389
4012
|
AgentLens,
|
|
4013
|
+
AskCard,
|
|
1390
4014
|
IterationStrip,
|
|
1391
4015
|
LiveTimelineBuilder,
|
|
1392
4016
|
MessagesPanel,
|
|
4017
|
+
RunSummary,
|
|
4018
|
+
SkillsPanel,
|
|
4019
|
+
StageFlow,
|
|
4020
|
+
TimeTravel,
|
|
1393
4021
|
ToolCallInspector,
|
|
4022
|
+
deriveStages,
|
|
1394
4023
|
fromAgentSnapshot,
|
|
1395
4024
|
resolveLensTheme,
|
|
1396
4025
|
useLensTheme,
|