@elizaos/client 1.6.1-alpha.4 → 1.6.1-alpha.6

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.
Files changed (50) hide show
  1. package/dist/assets/main-BM2lpId8.js +155 -0
  2. package/dist/assets/main-BM2lpId8.js.map +1 -0
  3. package/dist/assets/{main-BOBWcKWW.css → main-CNv6B3RZ.css} +597 -71
  4. package/dist/assets/{main-C4q5_rtN.js → main-CQAV8tyh.js} +4 -4
  5. package/dist/assets/main-CQAV8tyh.js.map +1 -0
  6. package/dist/assets/react-vendor-C1OK-nqm.js +611 -0
  7. package/dist/assets/react-vendor-C1OK-nqm.js.map +1 -0
  8. package/dist/index.html +1 -1
  9. package/package.json +29 -25
  10. package/src/components/agent-prism/Avatar.tsx +164 -0
  11. package/src/components/agent-prism/Badge.tsx +109 -0
  12. package/src/components/agent-prism/Button.tsx +138 -0
  13. package/src/components/agent-prism/CollapseAndExpandControls.tsx +45 -0
  14. package/src/components/agent-prism/CollapsibleSection.tsx +121 -0
  15. package/src/components/agent-prism/DetailsView/DetailsView.tsx +141 -0
  16. package/src/components/agent-prism/DetailsView/DetailsViewAttributesTab.tsx +45 -0
  17. package/src/components/agent-prism/DetailsView/DetailsViewHeader.tsx +77 -0
  18. package/src/components/agent-prism/DetailsView/DetailsViewHeaderActions.tsx +21 -0
  19. package/src/components/agent-prism/DetailsView/DetailsViewInputOutputTab.tsx +210 -0
  20. package/src/components/agent-prism/DetailsView/DetailsViewMetrics.tsx +53 -0
  21. package/src/components/agent-prism/DetailsView/DetailsViewRawDataTab.tsx +24 -0
  22. package/src/components/agent-prism/IconButton.tsx +75 -0
  23. package/src/components/agent-prism/PriceBadge.tsx +12 -0
  24. package/src/components/agent-prism/SearchInput.tsx +17 -0
  25. package/src/components/agent-prism/SpanCard/SpanCard.tsx +467 -0
  26. package/src/components/agent-prism/SpanCard/SpanCardBadges.tsx +35 -0
  27. package/src/components/agent-prism/SpanCard/SpanCardConnector.tsx +36 -0
  28. package/src/components/agent-prism/SpanCard/SpanCardTimeline.tsx +60 -0
  29. package/src/components/agent-prism/SpanCard/SpanCardToggle.tsx +32 -0
  30. package/src/components/agent-prism/SpanStatus.tsx +79 -0
  31. package/src/components/agent-prism/Tabs.tsx +141 -0
  32. package/src/components/agent-prism/TextInput.tsx +142 -0
  33. package/src/components/agent-prism/TimestampBadge.tsx +28 -0
  34. package/src/components/agent-prism/TokensBadge.tsx +26 -0
  35. package/src/components/agent-prism/TraceList/TraceList.tsx +80 -0
  36. package/src/components/agent-prism/TraceList/TraceListItem.tsx +79 -0
  37. package/src/components/agent-prism/TraceList/TraceListItemHeader.tsx +46 -0
  38. package/src/components/agent-prism/TraceViewer.tsx +476 -0
  39. package/src/components/agent-prism/TreeView.tsx +57 -0
  40. package/src/components/agent-prism/shared.ts +210 -0
  41. package/src/components/agent-runs/AgentRunTimeline.tsx +64 -673
  42. package/src/components/agent-sidebar.tsx +2 -2
  43. package/src/components/chat.tsx +8 -8
  44. package/src/lib/agent-prism-utils.ts +46 -0
  45. package/src/lib/eliza-span-adapter.ts +487 -0
  46. package/dist/assets/main-BNtEiK3o.js +0 -141
  47. package/dist/assets/main-BNtEiK3o.js.map +0 -1
  48. package/dist/assets/main-C4q5_rtN.js.map +0 -1
  49. package/dist/assets/react-vendor-pe76PXQl.js +0 -546
  50. package/dist/assets/react-vendor-pe76PXQl.js.map +0 -1
@@ -0,0 +1,476 @@
1
+ import {
2
+ flattenSpans,
3
+ formatDuration,
4
+ } from "@evilmartians/agent-prism-data";
5
+ import {
6
+ type TraceRecord,
7
+ type TraceSpan,
8
+ } from "@evilmartians/agent-prism-types";
9
+ import { filterSpansRecursively } from "@/lib/agent-prism-utils";
10
+ import { cn } from "@/lib/utils";
11
+ import { ArrowLeft } from "lucide-react";
12
+ import { useCallback, useEffect, useMemo, useState } from "react";
13
+
14
+ import type { BadgeProps } from "./Badge";
15
+ import type { SpanCardViewOptions } from "./SpanCard/SpanCard";
16
+
17
+ import { Button } from "./Button";
18
+ import {
19
+ CollapseAllButton,
20
+ ExpandAllButton,
21
+ } from "./CollapseAndExpandControls";
22
+ import { DetailsView } from "./DetailsView/DetailsView";
23
+ import { SearchInput } from "./SearchInput";
24
+ import { TraceList } from "./TraceList/TraceList";
25
+ import { TraceListItemHeader } from "./TraceList/TraceListItemHeader";
26
+ import { TreeView } from "./TreeView";
27
+ import {
28
+ Select,
29
+ SelectContent,
30
+ SelectItem,
31
+ SelectTrigger,
32
+ SelectValue,
33
+ } from "@/components/ui/select";
34
+ import { Badge } from "./Badge";
35
+ import { PriceBadge } from "./PriceBadge";
36
+ import { TimestampBadge } from "./TimestampBadge";
37
+ import { TokensBadge } from "./TokensBadge";
38
+
39
+ export interface TraceViewerData {
40
+ traceRecord: TraceRecord;
41
+ badges?: Array<BadgeProps>;
42
+ spans: TraceSpan[];
43
+ spanCardViewOptions?: SpanCardViewOptions;
44
+ }
45
+
46
+ export interface TraceViewerProps {
47
+ data: Array<TraceViewerData>;
48
+ spanCardViewOptions?: SpanCardViewOptions;
49
+ }
50
+
51
+ export const TraceViewer = ({ data }: TraceViewerProps) => {
52
+ const [selectedTrace, setSelectedTrace] = useState<
53
+ TraceRecordWithDisplayData | undefined
54
+ >(data[0]?.traceRecord);
55
+ const [selectedTraceSpans, setSelectedTraceSpans] = useState<TraceSpan[]>(
56
+ data[0]?.spans ?? [],
57
+ );
58
+ const [selectedSpan, setSelectedSpan] = useState<TraceSpan | undefined>(
59
+ data[0]?.spans?.[0]?.children?.[0],
60
+ );
61
+ const [searchValue, setSearchValue] = useState("");
62
+
63
+ const [traceListExpanded, setTraceListExpanded] = useState(true);
64
+
65
+ const traceRecords: TraceRecordWithDisplayData[] = useMemo(() => {
66
+ return data.map((item) => ({
67
+ ...item.traceRecord,
68
+ badges: item.badges,
69
+ spanCardViewOptions: item.spanCardViewOptions,
70
+ }));
71
+ }, [data]);
72
+
73
+ const filteredSpans = useMemo(() => {
74
+ if (!searchValue.trim()) {
75
+ return selectedTraceSpans;
76
+ }
77
+
78
+ return filterSpansRecursively(selectedTraceSpans, searchValue);
79
+ }, [selectedTraceSpans, searchValue]);
80
+
81
+ const allIds = useMemo(() => {
82
+ return flattenSpans(selectedTraceSpans).map((span) => span.id);
83
+ }, [selectedTraceSpans]);
84
+
85
+ const [expandedSpansIds, setExpandedSpansIds] = useState<string[]>(allIds);
86
+
87
+ useEffect(() => {
88
+ setExpandedSpansIds(allIds);
89
+ }, [allIds]);
90
+
91
+ const handleExpandAll = useCallback(() => {
92
+ setExpandedSpansIds(allIds);
93
+ }, [allIds]);
94
+
95
+ const handleCollapseAll = useCallback(() => {
96
+ setExpandedSpansIds([]);
97
+ }, []);
98
+
99
+ useEffect(() => {
100
+ setSelectedSpan(selectedTraceSpans[0]);
101
+ }, [selectedTraceSpans]);
102
+
103
+ const handleTraceSelect = useCallback(
104
+ (trace: TraceRecord) => {
105
+ setSelectedTrace(trace);
106
+ setSelectedTraceSpans(
107
+ data.find((item) => item.traceRecord.id === trace.id)?.spans ?? [],
108
+ );
109
+ },
110
+ [data],
111
+ );
112
+
113
+ const props: LayoutProps = {
114
+ traceRecords,
115
+ traceListExpanded,
116
+ setTraceListExpanded,
117
+ selectedTrace,
118
+ setSelectedTrace,
119
+ selectedTraceSpans,
120
+ setSelectedTraceSpans,
121
+ selectedSpan,
122
+ setSelectedSpan,
123
+ searchValue,
124
+ setSearchValue,
125
+ filteredSpans,
126
+ expandedSpansIds,
127
+ setExpandedSpansIds,
128
+ handleExpandAll,
129
+ handleCollapseAll,
130
+ handleTraceSelect,
131
+ };
132
+
133
+ return (
134
+ <div className="h-full w-full p-4 lg:p-8">
135
+ <div className="hidden lg:block">
136
+ <DesktopLayout {...props} />
137
+ </div>
138
+
139
+ <div className="lg:hidden">
140
+ <MobileLayout {...props} />
141
+ </div>
142
+ </div>
143
+ );
144
+ };
145
+
146
+ interface TraceRecordWithDisplayData extends TraceRecord {
147
+ spanCardViewOptions?: SpanCardViewOptions;
148
+ badges?: BadgeProps[];
149
+ }
150
+
151
+ interface LayoutProps {
152
+ traceRecords: TraceRecordWithDisplayData[];
153
+ traceListExpanded: boolean;
154
+ setTraceListExpanded: (expanded: boolean) => void;
155
+ selectedTrace: TraceRecordWithDisplayData | undefined;
156
+ setSelectedTrace: (trace: TraceRecordWithDisplayData | undefined) => void;
157
+ selectedTraceSpans: TraceSpan[];
158
+ setSelectedTraceSpans: (spans: TraceSpan[]) => void;
159
+ selectedSpan: TraceSpan | undefined;
160
+ setSelectedSpan: (span: TraceSpan | undefined) => void;
161
+ searchValue: string;
162
+ setSearchValue: (value: string) => void;
163
+ filteredSpans: TraceSpan[];
164
+ expandedSpansIds: string[];
165
+ setExpandedSpansIds: (ids: string[]) => void;
166
+ handleExpandAll: () => void;
167
+ handleCollapseAll: () => void;
168
+ handleTraceSelect: (trace: TraceRecord) => void;
169
+ }
170
+
171
+ const DesktopLayout = ({
172
+ traceRecords,
173
+ traceListExpanded,
174
+ setTraceListExpanded,
175
+ selectedTrace,
176
+ selectedSpan,
177
+ setSelectedSpan,
178
+ searchValue,
179
+ setSearchValue,
180
+ filteredSpans,
181
+ expandedSpansIds,
182
+ setExpandedSpansIds,
183
+ handleExpandAll,
184
+ handleCollapseAll,
185
+ handleTraceSelect,
186
+ }: LayoutProps) => {
187
+ return (
188
+ <div className="flex flex-col gap-4">
189
+ {selectedTrace ? (
190
+ <div className="flex flex-col gap-4">
191
+ {/* Trace Selector Dropdown */}
192
+ <Select
193
+ value={selectedTrace.id}
194
+ onValueChange={(value) => {
195
+ const trace = traceRecords.find((t) => t.id === value);
196
+ if (trace) handleTraceSelect(trace);
197
+ }}
198
+ >
199
+ <SelectTrigger className="w-full h-auto py-3">
200
+ <SelectValue>
201
+ <div className="flex items-center gap-4 w-full">
202
+ <span className="font-semibold text-base">{selectedTrace.name}</span>
203
+ <div className="flex items-center gap-2 ml-auto">
204
+ {typeof selectedTrace.startTime === "number" && (
205
+ <span className="text-xs text-muted-foreground font-mono">
206
+ {new Date(selectedTrace.startTime).toLocaleTimeString()}
207
+ </span>
208
+ )}
209
+ <Badge
210
+ size="4"
211
+ theme="gray"
212
+ variant="outline"
213
+ label={`${selectedTrace.spansCount} span${selectedTrace.spansCount === 1 ? '' : 's'}`}
214
+ />
215
+ <Badge
216
+ size="4"
217
+ theme="gray"
218
+ variant="outline"
219
+ label={formatDuration(selectedTrace.durationMs)}
220
+ />
221
+ </div>
222
+ </div>
223
+ </SelectValue>
224
+ </SelectTrigger>
225
+ <SelectContent className="w-full max-w-2xl max-h-[400px]">
226
+ {traceRecords.map((trace) => (
227
+ <SelectItem key={trace.id} value={trace.id} className="py-2.5 px-4 cursor-pointer">
228
+ <div className="flex items-center justify-between gap-4 w-full pr-6">
229
+ <div className="flex flex-col gap-1 min-w-0">
230
+ <span className="font-semibold text-base text-foreground">{trace.name}</span>
231
+ {trace.agentDescription && (
232
+ <span className="text-xs text-muted-foreground">
233
+ {trace.agentDescription}
234
+ </span>
235
+ )}
236
+ </div>
237
+ <div className="flex items-center gap-2 flex-shrink-0">
238
+ {typeof trace.startTime === "number" && (
239
+ <span className="text-xs text-muted-foreground font-mono">
240
+ {new Date(trace.startTime).toLocaleTimeString()}
241
+ </span>
242
+ )}
243
+ <Badge
244
+ size="4"
245
+ theme="gray"
246
+ variant="outline"
247
+ label={`${trace.spansCount} span${trace.spansCount === 1 ? '' : 's'}`}
248
+ />
249
+ <Badge
250
+ size="4"
251
+ theme="gray"
252
+ variant="outline"
253
+ label={formatDuration(trace.durationMs)}
254
+ />
255
+ </div>
256
+ </div>
257
+ </SelectItem>
258
+ ))}
259
+ </SelectContent>
260
+ </Select>
261
+
262
+ <div className="rounded-lg border border-border bg-card shadow-sm">
263
+ <div className="flex items-center justify-between gap-2 border-b border-border p-4">
264
+ <SearchInput
265
+ id="span-search-desktop"
266
+ name="search"
267
+ onClear={() => setSearchValue("")}
268
+ value={searchValue}
269
+ onValueChange={setSearchValue}
270
+ className="max-w-60 grow"
271
+ />
272
+
273
+ <div className="flex items-center gap-2">
274
+ <div className="ml-auto flex items-center gap-3">
275
+ <ExpandAllButton onExpandAll={handleExpandAll} />
276
+ <CollapseAllButton onCollapseAll={handleCollapseAll} />
277
+ </div>
278
+ </div>
279
+ </div>
280
+
281
+ {filteredSpans.length === 0 ? (
282
+ <div className="p-3 text-center text-muted-foreground">
283
+ No spans found
284
+ </div>
285
+ ) : (
286
+ <TreeView
287
+ spans={filteredSpans}
288
+ onSpanSelect={setSelectedSpan}
289
+ selectedSpan={selectedSpan}
290
+ expandedSpansIds={expandedSpansIds}
291
+ onExpandSpansIdsChange={setExpandedSpansIds}
292
+ spanCardViewOptions={selectedTrace.spanCardViewOptions}
293
+ />
294
+ )}
295
+ </div>
296
+
297
+ {selectedSpan ? (
298
+ <DetailsView data={selectedSpan} />
299
+ ) : (
300
+ <Placeholder title="Select a span to see the details" />
301
+ )}
302
+ </div>
303
+ ) : (
304
+ <div className="flex flex-col gap-4">
305
+ <Select
306
+ value=""
307
+ onValueChange={(value) => {
308
+ const trace = traceRecords.find((t) => t.id === value);
309
+ if (trace) handleTraceSelect(trace);
310
+ }}
311
+ >
312
+ <SelectTrigger className="w-full">
313
+ <SelectValue placeholder="Select a trace to view details..." />
314
+ </SelectTrigger>
315
+ <SelectContent className="w-full max-w-2xl max-h-[400px]">
316
+ {traceRecords.map((trace) => (
317
+ <SelectItem key={trace.id} value={trace.id} className="py-2.5 px-4 cursor-pointer">
318
+ <div className="flex items-center justify-between gap-4 w-full pr-6">
319
+ <div className="flex flex-col gap-1 min-w-0">
320
+ <span className="font-semibold text-base text-foreground">{trace.name}</span>
321
+ {trace.agentDescription && (
322
+ <span className="text-xs text-muted-foreground">
323
+ {trace.agentDescription}
324
+ </span>
325
+ )}
326
+ </div>
327
+ <div className="flex items-center gap-2 flex-shrink-0">
328
+ {typeof trace.startTime === "number" && (
329
+ <span className="text-xs text-muted-foreground font-mono">
330
+ {new Date(trace.startTime).toLocaleTimeString()}
331
+ </span>
332
+ )}
333
+ <Badge
334
+ size="4"
335
+ theme="gray"
336
+ variant="outline"
337
+ label={`${trace.spansCount} span${trace.spansCount === 1 ? '' : 's'}`}
338
+ />
339
+ <Badge
340
+ size="4"
341
+ theme="gray"
342
+ variant="outline"
343
+ label={formatDuration(trace.durationMs)}
344
+ />
345
+ </div>
346
+ </div>
347
+ </SelectItem>
348
+ ))}
349
+ </SelectContent>
350
+ </Select>
351
+ <Placeholder title="Select a trace to see the details" />
352
+ </div>
353
+ )}
354
+ </div>
355
+ );
356
+ };
357
+
358
+ const MobileLayout = ({
359
+ traceRecords,
360
+ traceListExpanded,
361
+ setTraceListExpanded,
362
+ selectedTrace,
363
+ setSelectedTrace,
364
+ selectedTraceSpans,
365
+ setSelectedTraceSpans,
366
+ selectedSpan,
367
+ setSelectedSpan,
368
+ searchValue,
369
+ setSearchValue,
370
+ filteredSpans,
371
+ expandedSpansIds,
372
+ setExpandedSpansIds,
373
+ handleExpandAll,
374
+ handleCollapseAll,
375
+ handleTraceSelect,
376
+ }: LayoutProps) => {
377
+ if (!selectedTrace) {
378
+ return (
379
+ <TraceList
380
+ traces={traceRecords}
381
+ expanded={traceListExpanded}
382
+ onExpandStateChange={setTraceListExpanded}
383
+ onTraceSelect={handleTraceSelect}
384
+ selectedTrace={selectedTrace}
385
+ />
386
+ );
387
+ }
388
+
389
+ if (selectedTrace && selectedTraceSpans.length && !selectedSpan) {
390
+ return (
391
+ <div className="flex flex-col gap-4">
392
+ <Button
393
+ onClick={() => {
394
+ setSelectedTrace(undefined);
395
+ setSelectedTraceSpans([]);
396
+ }}
397
+ iconStart={<ArrowLeft className="size-3" />}
398
+ variant="ghost"
399
+ className="self-start"
400
+ >
401
+ Traces list
402
+ </Button>
403
+
404
+ <TraceListItemHeader trace={selectedTrace} />
405
+
406
+ <div className="rounded border border-border bg-card">
407
+ <div className="flex items-center justify-between gap-2 border-b border-border p-3">
408
+ <SearchInput
409
+ id="span-search-mobile"
410
+ name="search"
411
+ onClear={() => setSearchValue("")}
412
+ value={searchValue}
413
+ onValueChange={setSearchValue}
414
+ className="max-w-60 grow"
415
+ />
416
+
417
+ <div className="flex items-center gap-2">
418
+ <div className="ml-auto flex items-center gap-3">
419
+ <ExpandAllButton onExpandAll={handleExpandAll} />
420
+ <CollapseAllButton onCollapseAll={handleCollapseAll} />
421
+ </div>
422
+ </div>
423
+ </div>
424
+
425
+ {filteredSpans.length === 0 ? (
426
+ <div className="p-3 text-center text-muted-foreground">
427
+ No spans found
428
+ </div>
429
+ ) : (
430
+ <TreeView
431
+ spans={filteredSpans}
432
+ spanCardViewOptions={selectedTrace.spanCardViewOptions}
433
+ onSpanSelect={setSelectedSpan}
434
+ selectedSpan={selectedSpan}
435
+ expandedSpansIds={expandedSpansIds}
436
+ onExpandSpansIdsChange={setExpandedSpansIds}
437
+ />
438
+ )}
439
+ </div>
440
+ </div>
441
+ );
442
+ }
443
+
444
+ if (selectedTrace && selectedTraceSpans.length && selectedSpan) {
445
+ return (
446
+ <div className="flex flex-col gap-4">
447
+ <Button
448
+ onClick={() => {
449
+ setSelectedSpan(undefined);
450
+ }}
451
+ iconStart={<ArrowLeft className="size-3" />}
452
+ variant="ghost"
453
+ className="self-start"
454
+ >
455
+ Tree View
456
+ </Button>
457
+
458
+ <DetailsView data={selectedSpan} />
459
+ </div>
460
+ );
461
+ }
462
+
463
+ return null;
464
+ };
465
+
466
+ interface PlaceholderProps {
467
+ title: string;
468
+ }
469
+
470
+ const Placeholder = ({ title }: PlaceholderProps) => {
471
+ return (
472
+ <p className="hidden items-center justify-center rounded-lg bg-muted p-4 text-center text-muted-foreground lg:flex">
473
+ {title}
474
+ </p>
475
+ );
476
+ };
@@ -0,0 +1,57 @@
1
+ import type { TraceSpan } from "@evilmartians/agent-prism-types";
2
+
3
+ import { findTimeRange, flattenSpans } from "@evilmartians/agent-prism-data";
4
+ import { cn } from "@/lib/utils";
5
+ import { type FC } from "react";
6
+
7
+ import { SpanCard, type SpanCardViewOptions } from "./SpanCard/SpanCard";
8
+
9
+ interface TreeViewProps {
10
+ spans: TraceSpan[];
11
+ className?: string;
12
+ selectedSpan?: TraceSpan;
13
+ onSpanSelect?: (span: TraceSpan) => void;
14
+ expandedSpansIds: string[];
15
+ onExpandSpansIdsChange: (ids: string[]) => void;
16
+ spanCardViewOptions?: SpanCardViewOptions;
17
+ }
18
+
19
+ export const TreeView: FC<TreeViewProps> = ({
20
+ spans,
21
+ onSpanSelect,
22
+ className = "",
23
+ selectedSpan,
24
+ expandedSpansIds,
25
+ onExpandSpansIdsChange,
26
+ spanCardViewOptions,
27
+ }) => {
28
+ const allCards = flattenSpans(spans);
29
+
30
+ const { minStart, maxEnd } = findTimeRange(allCards);
31
+
32
+ return (
33
+ <div className="w-full min-w-0 p-4">
34
+ <ul
35
+ className={cn(className, "overflow-x-auto space-y-1")}
36
+ role="tree"
37
+ aria-label="Hierarchical card list"
38
+ >
39
+ {spans.map((span, idx) => (
40
+ <SpanCard
41
+ key={span.id}
42
+ data={span}
43
+ level={0}
44
+ selectedSpan={selectedSpan}
45
+ onSpanSelect={onSpanSelect}
46
+ minStart={minStart}
47
+ maxEnd={maxEnd}
48
+ isLastChild={idx === spans.length - 1}
49
+ expandedSpansIds={expandedSpansIds}
50
+ onExpandSpansIdsChange={onExpandSpansIdsChange}
51
+ viewOptions={spanCardViewOptions}
52
+ />
53
+ ))}
54
+ </ul>
55
+ </div>
56
+ );
57
+ };