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

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 (48) hide show
  1. package/dist/assets/{main-C4q5_rtN.js → main-4tyUgNqd.js} +3 -3
  2. package/dist/assets/{main-C4q5_rtN.js.map → main-4tyUgNqd.js.map} +1 -1
  3. package/dist/assets/{main-BNtEiK3o.js → main-Bbs84AcL.js} +77 -63
  4. package/dist/assets/main-Bbs84AcL.js.map +1 -0
  5. package/dist/assets/{main-BOBWcKWW.css → main-CNv6B3RZ.css} +597 -71
  6. package/dist/assets/react-vendor-DxnAFk-d.js +611 -0
  7. package/dist/assets/react-vendor-DxnAFk-d.js.map +1 -0
  8. package/dist/index.html +1 -1
  9. package/package.json +8 -4
  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.map +0 -1
  47. package/dist/assets/react-vendor-pe76PXQl.js +0 -546
  48. package/dist/assets/react-vendor-pe76PXQl.js.map +0 -1
@@ -0,0 +1,141 @@
1
+ import type { ComponentPropsWithRef } from "react";
2
+
3
+ import * as RadixTabs from "@radix-ui/react-tabs";
4
+ import { cn } from "@/lib/utils";
5
+ import * as React from "react";
6
+
7
+ export interface TabItem<T extends string = string> {
8
+ value: T;
9
+ label: string;
10
+ icon?: React.ReactNode;
11
+ disabled?: boolean;
12
+ }
13
+
14
+ export type TabTheme = "underline" | "pill";
15
+
16
+ const BASE_TRIGGER =
17
+ "text-sm font-medium transition-colors duration-200 disabled:opacity-50 disabled:cursor-not-allowed";
18
+
19
+ const THEMES = {
20
+ underline: {
21
+ list: "h-9 flex border-b border-border ",
22
+ trigger: `w-full justify-center px-3 ${BASE_TRIGGER}
23
+ text-muted-foreground hover:text-foreground data-[state=active]:text-foreground
24
+ dark:hover:text-gray-200 dark:data-[state=active]:text-gray-200
25
+ border-b-2 border-transparent data-[state=active]:border-primary
26
+ dark:data-[state=active]:border-muted -mb-[2px]
27
+ hover:border-muted `,
28
+ },
29
+ pill: {
30
+ list: "h-9 inline-flex gap-1 p-1 bg-muted rounded-lg",
31
+ trigger: `px-3 ${BASE_TRIGGER} rounded-md
32
+ text-muted-foreground hover:text-foreground data-[state=active]:text-foreground
33
+ dark:hover:text-gray-200 dark:data-[state=active]:text-gray-200
34
+ hover:bg-accent data-[state=active]:bg-card data-[state=active]:shadow-sm
35
+ dark:hover:bg-gray-700 dark:data-[state=active]:bg-gray-600 dark:data-[state=active]:shadow-none`,
36
+ },
37
+ } as const;
38
+
39
+ export type TabsProps<T extends string = string> = Omit<
40
+ ComponentPropsWithRef<"div">,
41
+ "dir"
42
+ > & {
43
+ /**
44
+ * Array of tab items to display
45
+ */
46
+ items: TabItem<T>[];
47
+
48
+ /**
49
+ * The initially selected tab value (uncontrolled)
50
+ */
51
+ defaultValue?: T;
52
+
53
+ /**
54
+ * The currently selected tab value (controlled)
55
+ */
56
+ value?: T;
57
+
58
+ /**
59
+ * Callback fired when the selected tab changes
60
+ */
61
+ onValueChange?: (value: T) => void;
62
+
63
+ /**
64
+ * Visual theme variant for the tabs
65
+ * @default "underline"
66
+ */
67
+ theme?: TabTheme;
68
+
69
+ /**
70
+ * Optional className for the root container
71
+ */
72
+ className?: string;
73
+
74
+ /**
75
+ * Optional className for the tabs list container
76
+ */
77
+ tabsListClassName?: string;
78
+
79
+ /**
80
+ * Optional className for individual tab triggers
81
+ */
82
+ triggerClassName?: string;
83
+
84
+ /**
85
+ * The direction of the content of the tabs
86
+ */
87
+ dir?: "ltr" | "rtl";
88
+ };
89
+
90
+ export const Tabs = <T extends string = string>({
91
+ items,
92
+ defaultValue,
93
+ value,
94
+ onValueChange,
95
+ theme = "underline",
96
+ className = "",
97
+ tabsListClassName = "",
98
+ triggerClassName = "",
99
+ dir,
100
+ ...rest
101
+ }: TabsProps<T>) => {
102
+ const defaultTab = defaultValue || items[0]?.value;
103
+
104
+ const currentTheme = THEMES[theme];
105
+
106
+ return (
107
+ <RadixTabs.Root
108
+ className={className}
109
+ defaultValue={!value ? defaultTab : undefined}
110
+ value={value}
111
+ onValueChange={onValueChange as (value: string) => void}
112
+ dir={dir}
113
+ {...rest}
114
+ >
115
+ <RadixTabs.List
116
+ className={cn(currentTheme.list, tabsListClassName)}
117
+ aria-label="Navigation tabs"
118
+ >
119
+ {items.map((item: TabItem) => (
120
+ <RadixTabs.Trigger
121
+ key={item.value}
122
+ value={item.value}
123
+ disabled={item.disabled}
124
+ className={cn(
125
+ "flex items-center overflow-hidden",
126
+ currentTheme.trigger,
127
+ triggerClassName,
128
+ )}
129
+ >
130
+ {item.icon && (
131
+ <span className="mr-2 text-muted-foreground group-data-[state=active]:text-current ">
132
+ {item.icon}
133
+ </span>
134
+ )}
135
+ <span className="truncate">{item.label}</span>
136
+ </RadixTabs.Trigger>
137
+ ))}
138
+ </RadixTabs.List>
139
+ </RadixTabs.Root>
140
+ );
141
+ };
@@ -0,0 +1,142 @@
1
+ import { cn } from "@/lib/utils";
2
+ import { X } from "lucide-react";
3
+ import {
4
+ useRef,
5
+ type ChangeEvent,
6
+ type ComponentPropsWithRef,
7
+ type ReactNode,
8
+ type RefObject,
9
+ } from "react";
10
+
11
+ export type TextInputProps = ComponentPropsWithRef<"input"> & {
12
+ /**
13
+ * Callback fired when the input value changes
14
+ */
15
+ onValueChange?: (value: string) => void;
16
+
17
+ /**
18
+ * Icon to display at the start of the input
19
+ */
20
+ startIcon?: ReactNode;
21
+
22
+ /**
23
+ * Callback fired when the clear button is clicked. If this callback is provided,
24
+ * the clear button will be shown.
25
+ */
26
+ onClear?: () => void;
27
+
28
+ /**
29
+ * Ref to the input element
30
+ */
31
+ ref?: RefObject<HTMLInputElement | null>;
32
+
33
+ /**
34
+ * Optional className for the input element
35
+ */
36
+ inputClassName?: string;
37
+
38
+ /**
39
+ * Unique identifier for the input (required)
40
+ */
41
+ id: string;
42
+
43
+ /**
44
+ * Label text for the input
45
+ */
46
+ label?: string;
47
+
48
+ /**
49
+ * Whether to visually hide the label while keeping it for screen readers
50
+ * @default false
51
+ */
52
+ hideLabel?: boolean;
53
+ };
54
+
55
+ const iconBaseClassName =
56
+ "absolute top-1/2 -translate-y-1/2 flex items-center justify-center text-foreground";
57
+
58
+ export const TextInput = ({
59
+ className,
60
+ onChange,
61
+ onValueChange,
62
+ startIcon,
63
+ onClear,
64
+ ref,
65
+ inputClassName,
66
+ label,
67
+ hideLabel = false,
68
+ id,
69
+ ...rest
70
+ }: TextInputProps) => {
71
+ const inputRef = useRef<HTMLInputElement>(null);
72
+
73
+ const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
74
+ onChange?.(e);
75
+ onValueChange?.(e.target.value);
76
+ };
77
+
78
+ const handleClear = () => {
79
+ onClear?.();
80
+
81
+ if (ref) {
82
+ ref.current?.focus();
83
+ return;
84
+ }
85
+
86
+ inputRef.current?.focus();
87
+ };
88
+
89
+ return (
90
+ <div className={cn("w-full", className)}>
91
+ {label && (
92
+ <label
93
+ htmlFor={id}
94
+ className={cn(
95
+ "block text-sm font-medium text-foreground ",
96
+ hideLabel && "sr-only",
97
+ )}
98
+ >
99
+ {label}
100
+ </label>
101
+ )}
102
+ <div
103
+ className={cn(
104
+ "relative flex w-full items-center justify-center",
105
+ label && !hideLabel && "mt-1",
106
+ )}
107
+ >
108
+ <input
109
+ id={id}
110
+ ref={ref || inputRef}
111
+ onChange={handleChange}
112
+ className={cn(
113
+ inputClassName,
114
+ "flex h-7 items-center truncate",
115
+ "w-full px-2",
116
+ !!startIcon && "pl-8",
117
+ !!onClear && "pr-8",
118
+ "rounded border border-border bg-transparent ",
119
+ "text-foreground placeholder:text-muted-foreground ",
120
+ "hover:border-border dark:hover:border-gray-700",
121
+ )}
122
+ {...rest}
123
+ />
124
+ {startIcon && (
125
+ <div className={cn(iconBaseClassName, "left-2")} aria-hidden>
126
+ {startIcon}
127
+ </div>
128
+ )}
129
+ {onClear && rest.value && (
130
+ <button
131
+ className={cn(iconBaseClassName, "right-2")}
132
+ aria-label="Clear input value"
133
+ onClick={handleClear}
134
+ type="button"
135
+ >
136
+ <X className="size-4" />
137
+ </button>
138
+ )}
139
+ </div>
140
+ </div>
141
+ );
142
+ };
@@ -0,0 +1,28 @@
1
+ import type { ComponentPropsWithRef } from "react";
2
+
3
+ import { Badge, type BadgeProps } from "./Badge";
4
+
5
+ export type TimestampBadgeProps = ComponentPropsWithRef<"span"> & {
6
+ timestamp: number;
7
+ size?: BadgeProps["size"];
8
+ };
9
+
10
+ export const TimestampBadge = ({
11
+ timestamp,
12
+ size,
13
+ ...rest
14
+ }: TimestampBadgeProps) => {
15
+ return (
16
+ <Badge
17
+ variant="outline"
18
+ theme="gray"
19
+ size={size}
20
+ {...rest}
21
+ label={formatTimestamp(timestamp)}
22
+ />
23
+ );
24
+ };
25
+
26
+ function formatTimestamp(timestamp: number): string {
27
+ return new Date(timestamp).toLocaleString();
28
+ }
@@ -0,0 +1,26 @@
1
+ import type { ComponentPropsWithRef } from "react";
2
+
3
+ import { Coins } from "lucide-react";
4
+
5
+ import { Badge, type BadgeProps } from "./Badge";
6
+
7
+ export type TokensBadgeProps = ComponentPropsWithRef<"span"> & {
8
+ tokensCount: number;
9
+ size?: BadgeProps["size"];
10
+ };
11
+
12
+ export const TokensBadge = ({
13
+ tokensCount,
14
+ size,
15
+ ...rest
16
+ }: TokensBadgeProps) => {
17
+ return (
18
+ <Badge
19
+ iconStart={<Coins className="size-2.5" />}
20
+ theme="gray"
21
+ size={size}
22
+ {...rest}
23
+ label={tokensCount}
24
+ />
25
+ );
26
+ };
@@ -0,0 +1,80 @@
1
+ import type { TraceRecord } from "@evilmartians/agent-prism-types";
2
+
3
+ import { cn } from "@/lib/utils";
4
+ import { ArrowLeft } from "lucide-react";
5
+
6
+ import { Badge, type BadgeProps } from "../Badge.tsx";
7
+ import { IconButton } from "../IconButton.tsx";
8
+ import { TraceListItem } from "./TraceListItem.tsx";
9
+
10
+ type TraceRecordWithBadges = TraceRecord & {
11
+ badges?: Array<BadgeProps>;
12
+ };
13
+
14
+ type TraceListProps = {
15
+ traces: TraceRecordWithBadges[];
16
+ expanded: boolean;
17
+ onExpandStateChange: (expanded: boolean) => void;
18
+ className?: string;
19
+ onTraceSelect?: (trace: TraceRecord) => void;
20
+ selectedTrace?: TraceRecord;
21
+ };
22
+
23
+ export const TraceList = ({
24
+ traces,
25
+ expanded,
26
+ onExpandStateChange,
27
+ className,
28
+ onTraceSelect,
29
+ selectedTrace,
30
+ }: TraceListProps) => {
31
+ return (
32
+ <div
33
+ className={cn(
34
+ "w-full min-w-0",
35
+ "flex flex-col gap-3",
36
+ expanded ? "w-full" : "w-fit",
37
+ className,
38
+ )}
39
+ >
40
+ <header className="flex min-h-6 items-center justify-between gap-2">
41
+ <div className="flex items-center gap-2">
42
+ <h2
43
+ className={cn(
44
+ "font-semibold text-lg text-foreground",
45
+ !expanded && "hidden",
46
+ )}
47
+ >
48
+ Traces
49
+ </h2>
50
+
51
+ <Badge
52
+ size="5"
53
+ theme="teal"
54
+ aria-label={`Total number of traces: ${traces.length}`}
55
+ label={traces.length}
56
+ />
57
+ </div>
58
+
59
+ </header>
60
+
61
+ {expanded && (
62
+ <ul className="flex flex-col items-center overflow-hidden rounded border border-border ">
63
+ {traces.map((trace) => (
64
+ <li
65
+ className="w-full list-none border-b-border [&:not(:last-child)]:border-b"
66
+ key={trace.id}
67
+ >
68
+ <TraceListItem
69
+ trace={trace}
70
+ onClick={() => onTraceSelect?.(trace)}
71
+ isSelected={selectedTrace?.id === trace.id}
72
+ badges={trace.badges}
73
+ />
74
+ </li>
75
+ ))}
76
+ </ul>
77
+ )}
78
+ </div>
79
+ );
80
+ };
@@ -0,0 +1,79 @@
1
+ import type { TraceRecord } from "@evilmartians/agent-prism-types";
2
+
3
+ import { cn } from "@/lib/utils";
4
+ import { useCallback, type KeyboardEvent } from "react";
5
+
6
+ import { type AvatarProps } from "../Avatar.tsx";
7
+ import { Badge, type BadgeProps } from "../Badge.tsx";
8
+ import { PriceBadge } from "../PriceBadge.tsx";
9
+ import { TimestampBadge } from "../TimestampBadge.tsx";
10
+ import { TokensBadge } from "../TokensBadge.tsx";
11
+ import { TraceListItemHeader } from "./TraceListItemHeader.tsx";
12
+
13
+ interface TraceListItemProps {
14
+ trace: TraceRecord;
15
+ badges?: Array<BadgeProps>;
16
+ avatar?: AvatarProps;
17
+ onClick?: () => void;
18
+ isSelected?: boolean;
19
+ }
20
+
21
+ export const TraceListItem = ({
22
+ trace,
23
+ avatar,
24
+ onClick,
25
+ badges,
26
+ isSelected,
27
+ }: TraceListItemProps) => {
28
+ const handleKeyDown = useCallback(
29
+ (e: KeyboardEvent): void => {
30
+ if (e.key === "Enter" || e.key === " ") {
31
+ e.preventDefault();
32
+ onClick?.();
33
+ }
34
+ },
35
+ [onClick],
36
+ );
37
+
38
+ const { name, agentDescription, totalCost, totalTokens, startTime } = trace;
39
+
40
+ return (
41
+ <div
42
+ className={cn(
43
+ "group w-full",
44
+ "flex flex-col gap-2.5 p-4",
45
+ "cursor-pointer",
46
+ isSelected
47
+ ? "bg-muted"
48
+ : "bg-card",
49
+ )}
50
+ role="button"
51
+ tabIndex={0}
52
+ onClick={onClick}
53
+ onKeyDown={handleKeyDown}
54
+ aria-label={`Select trace ${name}`}
55
+ >
56
+ <TraceListItemHeader trace={trace} avatar={avatar} />
57
+
58
+ <div className="flex flex-wrap items-center gap-2">
59
+ <span className="mr-4 max-w-full truncate text-sm text-muted-foreground ">
60
+ {agentDescription}
61
+ </span>
62
+
63
+ {typeof totalCost === "number" && <PriceBadge cost={totalCost} />}
64
+
65
+ {typeof totalTokens === "number" && (
66
+ <TokensBadge tokensCount={totalTokens} />
67
+ )}
68
+
69
+ {badges?.map((badge, index) => (
70
+ <Badge key={index} theme={badge.theme} size="4" label={badge.label} />
71
+ ))}
72
+
73
+ {typeof startTime === "number" && (
74
+ <TimestampBadge timestamp={startTime} />
75
+ )}
76
+ </div>
77
+ </div>
78
+ );
79
+ };
@@ -0,0 +1,46 @@
1
+ import type { TraceRecord } from "@evilmartians/agent-prism-types";
2
+
3
+ import { formatDuration } from "@evilmartians/agent-prism-data";
4
+
5
+ import { Avatar, type AvatarProps } from "../Avatar.tsx";
6
+ import { Badge } from "../Badge.tsx";
7
+
8
+ interface TraceListItemHeaderProps {
9
+ trace: TraceRecord;
10
+ avatar?: AvatarProps;
11
+ }
12
+
13
+ export const TraceListItemHeader = ({
14
+ trace,
15
+ avatar,
16
+ }: TraceListItemHeaderProps) => {
17
+ return (
18
+ <header className="flex min-w-0 flex-wrap items-center justify-between gap-2">
19
+ <div className="flex min-w-0 items-center gap-1.5 overflow-hidden">
20
+ {avatar && <Avatar size="4" {...avatar} />}
21
+
22
+ <h3 className="font-medium max-w-full truncate text-sm text-foreground">
23
+ {trace.name}
24
+ </h3>
25
+ </div>
26
+
27
+ <div className="flex items-center gap-2">
28
+ <Badge
29
+ size="5"
30
+ theme="gray"
31
+ variant="outline"
32
+ label={
33
+ trace.spansCount === 1 ? "1 span" : `${trace.spansCount} spans`
34
+ }
35
+ />
36
+
37
+ <Badge
38
+ size="5"
39
+ theme="gray"
40
+ variant="outline"
41
+ label={formatDuration(trace.durationMs)}
42
+ />
43
+ </div>
44
+ </header>
45
+ );
46
+ };