@truefoundry/agent-ui-sdk 0.0.1
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/README.md +634 -0
- package/dist/index.d.ts +718 -0
- package/dist/index.js +2736 -0
- package/dist/index.js.map +1 -0
- package/package.json +83 -0
- package/src/atoms/AskUserPrompt.tsx +102 -0
- package/src/atoms/AttachmentCard.tsx +92 -0
- package/src/atoms/AttachmentPickerButton.tsx +19 -0
- package/src/atoms/AttachmentPreviewDialog.tsx +34 -0
- package/src/atoms/BranchIndicator.tsx +41 -0
- package/src/atoms/CodeBlockHeader.tsx +44 -0
- package/src/atoms/ComposerShell.tsx +112 -0
- package/src/atoms/Markdown.test.tsx +28 -0
- package/src/atoms/Markdown.tsx +288 -0
- package/src/atoms/McpAuthPrompt.tsx +60 -0
- package/src/atoms/MessageActionBar.tsx +60 -0
- package/src/atoms/MessageBubble.tsx +80 -0
- package/src/atoms/MessageErrorBanner.tsx +26 -0
- package/src/atoms/MessageIndicator.tsx +23 -0
- package/src/atoms/OpenUIBlock.test.tsx +37 -0
- package/src/atoms/OpenUIBlock.tsx +50 -0
- package/src/atoms/ReasoningCard.tsx +52 -0
- package/src/atoms/SandboxArtifactList.tsx +63 -0
- package/src/atoms/ScrollToBottomButton.tsx +34 -0
- package/src/atoms/Skeletons.tsx +32 -0
- package/src/atoms/ThreadListMisc.tsx +76 -0
- package/src/atoms/ThreadListRow.tsx +81 -0
- package/src/atoms/ThreadShell.tsx +93 -0
- package/src/atoms/Toast.tsx +60 -0
- package/src/atoms/ToolApprovalBar.tsx +92 -0
- package/src/atoms/ToolCallCard.tsx +186 -0
- package/src/atoms/ToolGroupCard.tsx +52 -0
- package/src/atoms/UserMessageActionBar.tsx +62 -0
- package/src/atoms/WelcomeScreen.tsx +22 -0
- package/src/atoms/lib/cn.ts +6 -0
- package/src/atoms/primitives/Avatar.tsx +57 -0
- package/src/atoms/primitives/Button.tsx +73 -0
- package/src/atoms/primitives/Collapsible.tsx +32 -0
- package/src/atoms/primitives/Dialog.tsx +152 -0
- package/src/atoms/primitives/IconButton.tsx +43 -0
- package/src/atoms/primitives/Skeleton.tsx +17 -0
- package/src/atoms/primitives/Tooltip.tsx +58 -0
- package/src/containers/AskUserContainer.tsx +49 -0
- package/src/containers/AssistantMessageContainer.test.tsx +56 -0
- package/src/containers/AssistantMessageContainer.tsx +128 -0
- package/src/containers/AssistantTextContainer.test.tsx +111 -0
- package/src/containers/AssistantTextContainer.tsx +54 -0
- package/src/containers/AttachmentsContainer.tsx +83 -0
- package/src/containers/ComposerContainer.tsx +66 -0
- package/src/containers/ErrorToasterContainer.tsx +76 -0
- package/src/containers/McpAuthContainer.test.tsx +100 -0
- package/src/containers/McpAuthContainer.tsx +22 -0
- package/src/containers/MessageImageContainer.tsx +37 -0
- package/src/containers/ReasoningContainer.tsx +32 -0
- package/src/containers/RuntimeHarness.tsx +39 -0
- package/src/containers/Thread.tsx +9 -0
- package/src/containers/ThreadContainer.test.tsx +52 -0
- package/src/containers/ThreadContainer.tsx +87 -0
- package/src/containers/ThreadListContainer.tsx +63 -0
- package/src/containers/ToolCallContainer.test.tsx +135 -0
- package/src/containers/ToolCallContainer.tsx +167 -0
- package/src/containers/ToolGroupContainer.test.tsx +56 -0
- package/src/containers/ToolGroupContainer.tsx +24 -0
- package/src/containers/UserEditComposerContainer.test.tsx +52 -0
- package/src/containers/UserEditComposerContainer.tsx +86 -0
- package/src/containers/UserMessageContainer.test.tsx +99 -0
- package/src/containers/UserMessageContainer.tsx +26 -0
- package/src/containers/nestedApprovalBridge.ts +20 -0
- package/src/containers/useAttachmentPreviewSrc.ts +42 -0
- package/src/hooks/useComposerBusyState.test.ts +78 -0
- package/src/hooks/useComposerBusyState.ts +69 -0
- package/src/index.ts +193 -0
- package/src/openui.css +3 -0
- package/src/testSetup.ts +42 -0
- package/src/theme/SlotsProvider.test.tsx +64 -0
- package/src/theme/SlotsProvider.tsx +41 -0
- package/src/theme/defaultSlots.ts +131 -0
- package/src/theme/tokens.ts +98 -0
- package/src/theme/useClassDarkMode.ts +24 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,2736 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/theme/SlotsProvider.tsx
|
|
4
|
+
import { createContext, useContext, useMemo as useMemo2 } from "react";
|
|
5
|
+
|
|
6
|
+
// src/atoms/primitives/Avatar.tsx
|
|
7
|
+
import { Avatar as AvatarPrimitive } from "radix-ui";
|
|
8
|
+
|
|
9
|
+
// src/atoms/lib/cn.ts
|
|
10
|
+
import { clsx } from "clsx";
|
|
11
|
+
import { twMerge } from "tailwind-merge";
|
|
12
|
+
function cn(...inputs) {
|
|
13
|
+
return twMerge(clsx(inputs));
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// src/atoms/primitives/Avatar.tsx
|
|
17
|
+
import { jsx } from "react/jsx-runtime";
|
|
18
|
+
function Avatar({ className, size = "default", ...props }) {
|
|
19
|
+
return /* @__PURE__ */ jsx(
|
|
20
|
+
AvatarPrimitive.Root,
|
|
21
|
+
{
|
|
22
|
+
"data-slot": "avatar",
|
|
23
|
+
"data-size": size,
|
|
24
|
+
className: cn(
|
|
25
|
+
"group/avatar relative flex size-8 shrink-0 rounded-full select-none after:absolute after:inset-0 after:rounded-full after:border after:border-border after:mix-blend-darken data-[size=lg]:size-10 data-[size=sm]:size-6 dark:after:mix-blend-lighten",
|
|
26
|
+
className
|
|
27
|
+
),
|
|
28
|
+
...props
|
|
29
|
+
}
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
function AvatarImage({ className, ...props }) {
|
|
33
|
+
return /* @__PURE__ */ jsx(
|
|
34
|
+
AvatarPrimitive.Image,
|
|
35
|
+
{
|
|
36
|
+
"data-slot": "avatar-image",
|
|
37
|
+
className: cn("aspect-square size-full rounded-full object-cover", className),
|
|
38
|
+
...props
|
|
39
|
+
}
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
function AvatarFallback({ className, ...props }) {
|
|
43
|
+
return /* @__PURE__ */ jsx(
|
|
44
|
+
AvatarPrimitive.Fallback,
|
|
45
|
+
{
|
|
46
|
+
"data-slot": "avatar-fallback",
|
|
47
|
+
className: cn(
|
|
48
|
+
"flex size-full items-center justify-center rounded-full bg-muted text-sm text-muted-foreground group-data-[size=sm]/avatar:text-xs",
|
|
49
|
+
className
|
|
50
|
+
),
|
|
51
|
+
...props
|
|
52
|
+
}
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// src/atoms/primitives/Button.tsx
|
|
57
|
+
import { cva } from "class-variance-authority";
|
|
58
|
+
import { Slot } from "radix-ui";
|
|
59
|
+
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
60
|
+
var buttonVariants = cva(
|
|
61
|
+
"group/button inline-flex shrink-0 items-center justify-center rounded-lg border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
62
|
+
{
|
|
63
|
+
variants: {
|
|
64
|
+
variant: {
|
|
65
|
+
default: "bg-primary text-primary-foreground hover:bg-primary/80",
|
|
66
|
+
outline: "border-border bg-background hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50",
|
|
67
|
+
secondary: "bg-secondary text-secondary-foreground hover:bg-[color-mix(in_oklch,var(--secondary),var(--foreground)_5%)] aria-expanded:bg-secondary aria-expanded:text-secondary-foreground",
|
|
68
|
+
ghost: "hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50",
|
|
69
|
+
destructive: "bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40",
|
|
70
|
+
link: "text-primary underline-offset-4 hover:underline"
|
|
71
|
+
},
|
|
72
|
+
size: {
|
|
73
|
+
default: "h-8 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",
|
|
74
|
+
xs: "h-6 gap-1 rounded-[min(var(--radius-md),10px)] px-2 text-xs in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3",
|
|
75
|
+
sm: "h-7 gap-1 rounded-[min(var(--radius-md),12px)] px-2.5 text-[0.8rem] in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5",
|
|
76
|
+
lg: "h-9 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",
|
|
77
|
+
icon: "size-8",
|
|
78
|
+
"icon-xs": "size-6 rounded-[min(var(--radius-md),10px)] in-data-[slot=button-group]:rounded-lg [&_svg:not([class*='size-'])]:size-3",
|
|
79
|
+
"icon-sm": "size-7 rounded-[min(var(--radius-md),12px)] in-data-[slot=button-group]:rounded-lg",
|
|
80
|
+
"icon-lg": "size-9"
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
defaultVariants: {
|
|
84
|
+
variant: "default",
|
|
85
|
+
size: "default"
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
);
|
|
89
|
+
function Button({
|
|
90
|
+
className,
|
|
91
|
+
variant = "default",
|
|
92
|
+
size = "default",
|
|
93
|
+
asChild = false,
|
|
94
|
+
...props
|
|
95
|
+
}) {
|
|
96
|
+
const Comp = asChild ? Slot.Root : "button";
|
|
97
|
+
return /* @__PURE__ */ jsx2(
|
|
98
|
+
Comp,
|
|
99
|
+
{
|
|
100
|
+
"data-slot": "button",
|
|
101
|
+
"data-variant": variant,
|
|
102
|
+
"data-size": size,
|
|
103
|
+
className: cn(buttonVariants({ variant, size, className })),
|
|
104
|
+
...props
|
|
105
|
+
}
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// src/atoms/primitives/Collapsible.tsx
|
|
110
|
+
import { Collapsible as CollapsiblePrimitive } from "radix-ui";
|
|
111
|
+
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
112
|
+
function Collapsible(props) {
|
|
113
|
+
return /* @__PURE__ */ jsx3(CollapsiblePrimitive.Root, { "data-slot": "collapsible", ...props });
|
|
114
|
+
}
|
|
115
|
+
function CollapsibleTrigger(props) {
|
|
116
|
+
return /* @__PURE__ */ jsx3(CollapsiblePrimitive.CollapsibleTrigger, { "data-slot": "collapsible-trigger", ...props });
|
|
117
|
+
}
|
|
118
|
+
function CollapsibleContent(props) {
|
|
119
|
+
return /* @__PURE__ */ jsx3(CollapsiblePrimitive.CollapsibleContent, { "data-slot": "collapsible-content", ...props });
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// src/atoms/primitives/Dialog.tsx
|
|
123
|
+
import { Dialog as DialogPrimitive } from "radix-ui";
|
|
124
|
+
import { XIcon } from "lucide-react";
|
|
125
|
+
import { jsx as jsx4, jsxs } from "react/jsx-runtime";
|
|
126
|
+
function Dialog(props) {
|
|
127
|
+
return /* @__PURE__ */ jsx4(DialogPrimitive.Root, { "data-slot": "dialog", ...props });
|
|
128
|
+
}
|
|
129
|
+
function DialogTrigger(props) {
|
|
130
|
+
return /* @__PURE__ */ jsx4(DialogPrimitive.Trigger, { "data-slot": "dialog-trigger", ...props });
|
|
131
|
+
}
|
|
132
|
+
function DialogPortal(props) {
|
|
133
|
+
return /* @__PURE__ */ jsx4(DialogPrimitive.Portal, { "data-slot": "dialog-portal", ...props });
|
|
134
|
+
}
|
|
135
|
+
function DialogClose(props) {
|
|
136
|
+
return /* @__PURE__ */ jsx4(DialogPrimitive.Close, { "data-slot": "dialog-close", ...props });
|
|
137
|
+
}
|
|
138
|
+
function DialogOverlay({ className, ...props }) {
|
|
139
|
+
return /* @__PURE__ */ jsx4(
|
|
140
|
+
DialogPrimitive.Overlay,
|
|
141
|
+
{
|
|
142
|
+
"data-slot": "dialog-overlay",
|
|
143
|
+
className: cn(
|
|
144
|
+
"fixed inset-0 isolate z-50 bg-black/10 duration-100 supports-backdrop-filter:backdrop-blur-xs data-open:animate-in data-open:fade-in-0 data-closed:animate-out data-closed:fade-out-0",
|
|
145
|
+
className
|
|
146
|
+
),
|
|
147
|
+
...props
|
|
148
|
+
}
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
function DialogContent({
|
|
152
|
+
className,
|
|
153
|
+
children,
|
|
154
|
+
showCloseButton = true,
|
|
155
|
+
...props
|
|
156
|
+
}) {
|
|
157
|
+
return /* @__PURE__ */ jsxs(DialogPortal, { children: [
|
|
158
|
+
/* @__PURE__ */ jsx4(DialogOverlay, {}),
|
|
159
|
+
/* @__PURE__ */ jsxs(
|
|
160
|
+
DialogPrimitive.Content,
|
|
161
|
+
{
|
|
162
|
+
"data-slot": "dialog-content",
|
|
163
|
+
className: cn(
|
|
164
|
+
"fixed top-1/2 left-1/2 z-50 grid w-full max-w-[calc(100%-2rem)] -translate-x-1/2 -translate-y-1/2 gap-4 rounded-xl bg-popover p-4 text-sm text-popover-foreground ring-1 ring-foreground/10 duration-100 outline-none sm:max-w-sm data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95",
|
|
165
|
+
className
|
|
166
|
+
),
|
|
167
|
+
...props,
|
|
168
|
+
children: [
|
|
169
|
+
children,
|
|
170
|
+
showCloseButton && /* @__PURE__ */ jsx4(DialogPrimitive.Close, { "data-slot": "dialog-close", asChild: true, children: /* @__PURE__ */ jsxs(Button, { variant: "ghost", className: "absolute top-2 right-2", size: "icon-sm", children: [
|
|
171
|
+
/* @__PURE__ */ jsx4(XIcon, {}),
|
|
172
|
+
/* @__PURE__ */ jsx4("span", { className: "sr-only", children: "Close" })
|
|
173
|
+
] }) })
|
|
174
|
+
]
|
|
175
|
+
}
|
|
176
|
+
)
|
|
177
|
+
] });
|
|
178
|
+
}
|
|
179
|
+
function DialogHeader({ className, ...props }) {
|
|
180
|
+
return /* @__PURE__ */ jsx4("div", { "data-slot": "dialog-header", className: cn("flex flex-col gap-2", className), ...props });
|
|
181
|
+
}
|
|
182
|
+
function DialogFooter({ className, showCloseButton = false, children, ...props }) {
|
|
183
|
+
return /* @__PURE__ */ jsxs(
|
|
184
|
+
"div",
|
|
185
|
+
{
|
|
186
|
+
"data-slot": "dialog-footer",
|
|
187
|
+
className: cn(
|
|
188
|
+
"-mx-4 -mb-4 flex flex-col-reverse gap-2 rounded-b-xl border-t bg-muted/50 p-4 sm:flex-row sm:justify-end",
|
|
189
|
+
className
|
|
190
|
+
),
|
|
191
|
+
...props,
|
|
192
|
+
children: [
|
|
193
|
+
children,
|
|
194
|
+
showCloseButton && /* @__PURE__ */ jsx4(DialogPrimitive.Close, { asChild: true, children: /* @__PURE__ */ jsx4(Button, { variant: "outline", children: "Close" }) })
|
|
195
|
+
]
|
|
196
|
+
}
|
|
197
|
+
);
|
|
198
|
+
}
|
|
199
|
+
function DialogTitle({ className, ...props }) {
|
|
200
|
+
return /* @__PURE__ */ jsx4(
|
|
201
|
+
DialogPrimitive.Title,
|
|
202
|
+
{
|
|
203
|
+
"data-slot": "dialog-title",
|
|
204
|
+
className: cn("font-heading text-base leading-none font-medium", className),
|
|
205
|
+
...props
|
|
206
|
+
}
|
|
207
|
+
);
|
|
208
|
+
}
|
|
209
|
+
function DialogDescription({ className, ...props }) {
|
|
210
|
+
return /* @__PURE__ */ jsx4(
|
|
211
|
+
DialogPrimitive.Description,
|
|
212
|
+
{
|
|
213
|
+
"data-slot": "dialog-description",
|
|
214
|
+
className: cn(
|
|
215
|
+
"text-sm text-muted-foreground *:[a]:underline *:[a]:underline-offset-3 *:[a]:hover:text-foreground",
|
|
216
|
+
className
|
|
217
|
+
),
|
|
218
|
+
...props
|
|
219
|
+
}
|
|
220
|
+
);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// src/atoms/primitives/IconButton.tsx
|
|
224
|
+
import { forwardRef } from "react";
|
|
225
|
+
import { Slot as Slot2 } from "radix-ui";
|
|
226
|
+
|
|
227
|
+
// src/atoms/primitives/Tooltip.tsx
|
|
228
|
+
import { Tooltip as TooltipPrimitive } from "radix-ui";
|
|
229
|
+
import { jsx as jsx5, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
230
|
+
function TooltipProvider({ delayDuration = 0, ...props }) {
|
|
231
|
+
return /* @__PURE__ */ jsx5(
|
|
232
|
+
TooltipPrimitive.Provider,
|
|
233
|
+
{
|
|
234
|
+
"data-slot": "tooltip-provider",
|
|
235
|
+
delayDuration,
|
|
236
|
+
...props
|
|
237
|
+
}
|
|
238
|
+
);
|
|
239
|
+
}
|
|
240
|
+
function Tooltip(props) {
|
|
241
|
+
return /* @__PURE__ */ jsx5(TooltipPrimitive.Root, { "data-slot": "tooltip", ...props });
|
|
242
|
+
}
|
|
243
|
+
function TooltipTrigger(props) {
|
|
244
|
+
return /* @__PURE__ */ jsx5(TooltipPrimitive.Trigger, { "data-slot": "tooltip-trigger", ...props });
|
|
245
|
+
}
|
|
246
|
+
function TooltipContent({ className, sideOffset = 0, children, ...props }) {
|
|
247
|
+
return /* @__PURE__ */ jsx5(TooltipPrimitive.Portal, { children: /* @__PURE__ */ jsxs2(
|
|
248
|
+
TooltipPrimitive.Content,
|
|
249
|
+
{
|
|
250
|
+
"data-slot": "tooltip-content",
|
|
251
|
+
sideOffset,
|
|
252
|
+
className: cn(
|
|
253
|
+
"z-50 inline-flex w-fit max-w-xs origin-(--radix-tooltip-content-transform-origin) items-center gap-1.5 rounded-md bg-foreground px-3 py-1.5 text-xs text-background has-data-[slot=kbd]:pr-1.5 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 **:data-[slot=kbd]:relative **:data-[slot=kbd]:isolate **:data-[slot=kbd]:z-50 **:data-[slot=kbd]:rounded-sm data-[state=delayed-open]:animate-in data-[state=delayed-open]:fade-in-0 data-[state=delayed-open]:zoom-in-95 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95",
|
|
254
|
+
className
|
|
255
|
+
),
|
|
256
|
+
...props,
|
|
257
|
+
children: [
|
|
258
|
+
children,
|
|
259
|
+
/* @__PURE__ */ jsx5(TooltipPrimitive.Arrow, { className: "z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px] bg-foreground fill-foreground" })
|
|
260
|
+
]
|
|
261
|
+
}
|
|
262
|
+
) });
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// src/atoms/primitives/IconButton.tsx
|
|
266
|
+
import { jsx as jsx6, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
267
|
+
var IconButton = forwardRef(
|
|
268
|
+
({ children, tooltip, side = "bottom", className, ...rest }, ref) => {
|
|
269
|
+
return /* @__PURE__ */ jsx6(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ jsxs3(Tooltip, { children: [
|
|
270
|
+
/* @__PURE__ */ jsx6(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxs3(
|
|
271
|
+
Button,
|
|
272
|
+
{
|
|
273
|
+
variant: "ghost",
|
|
274
|
+
size: "icon",
|
|
275
|
+
...rest,
|
|
276
|
+
className: cn("aui-button-icon size-6 p-1 active:scale-90", className),
|
|
277
|
+
ref,
|
|
278
|
+
children: [
|
|
279
|
+
/* @__PURE__ */ jsx6(Slot2.Slottable, { children }),
|
|
280
|
+
/* @__PURE__ */ jsx6("span", { className: "aui-sr-only sr-only", children: tooltip })
|
|
281
|
+
]
|
|
282
|
+
}
|
|
283
|
+
) }),
|
|
284
|
+
/* @__PURE__ */ jsx6(TooltipContent, { side, children: tooltip })
|
|
285
|
+
] }) });
|
|
286
|
+
}
|
|
287
|
+
);
|
|
288
|
+
IconButton.displayName = "IconButton";
|
|
289
|
+
|
|
290
|
+
// src/atoms/primitives/Skeleton.tsx
|
|
291
|
+
import { jsx as jsx7 } from "react/jsx-runtime";
|
|
292
|
+
function Skeleton({ className, ...props }) {
|
|
293
|
+
return /* @__PURE__ */ jsx7("div", { "data-slot": "skeleton", className: cn("animate-pulse rounded-md bg-muted", className), ...props });
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
// src/atoms/BranchIndicator.tsx
|
|
297
|
+
import { ChevronLeftIcon, ChevronRightIcon } from "lucide-react";
|
|
298
|
+
import { jsx as jsx8, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
299
|
+
function BranchIndicator({ index, count, onPrevious, onNext, className }) {
|
|
300
|
+
if (count <= 1) return null;
|
|
301
|
+
return /* @__PURE__ */ jsxs4(
|
|
302
|
+
"div",
|
|
303
|
+
{
|
|
304
|
+
className: cn(
|
|
305
|
+
"aui-branch-picker-root text-muted-foreground -ms-2 me-2 inline-flex items-center text-xs",
|
|
306
|
+
className
|
|
307
|
+
),
|
|
308
|
+
children: [
|
|
309
|
+
/* @__PURE__ */ jsx8(IconButton, { tooltip: "Previous", onClick: onPrevious, children: /* @__PURE__ */ jsx8(ChevronLeftIcon, {}) }),
|
|
310
|
+
/* @__PURE__ */ jsxs4("span", { className: "aui-branch-picker-state font-medium", children: [
|
|
311
|
+
index,
|
|
312
|
+
" / ",
|
|
313
|
+
count
|
|
314
|
+
] }),
|
|
315
|
+
/* @__PURE__ */ jsx8(IconButton, { tooltip: "Next", onClick: onNext, children: /* @__PURE__ */ jsx8(ChevronRightIcon, {}) })
|
|
316
|
+
]
|
|
317
|
+
}
|
|
318
|
+
);
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
// src/atoms/CodeBlockHeader.tsx
|
|
322
|
+
import { useState } from "react";
|
|
323
|
+
import { CheckIcon, CopyIcon } from "lucide-react";
|
|
324
|
+
import { jsx as jsx9, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
325
|
+
function CodeBlockHeader({ language, code }) {
|
|
326
|
+
const [isCopied, setIsCopied] = useState(false);
|
|
327
|
+
const onCopy = () => {
|
|
328
|
+
if (!code || isCopied || typeof navigator === "undefined" || !navigator.clipboard) {
|
|
329
|
+
return;
|
|
330
|
+
}
|
|
331
|
+
navigator.clipboard.writeText(code).then(
|
|
332
|
+
() => {
|
|
333
|
+
setIsCopied(true);
|
|
334
|
+
setTimeout(() => setIsCopied(false), 3e3);
|
|
335
|
+
},
|
|
336
|
+
() => {
|
|
337
|
+
}
|
|
338
|
+
);
|
|
339
|
+
};
|
|
340
|
+
return /* @__PURE__ */ jsxs5("div", { className: "aui-code-header-root border-border/50 bg-muted/50 mt-3 flex items-center justify-between rounded-t-xl border border-b-0 px-3.5 py-1.5 text-xs", children: [
|
|
341
|
+
/* @__PURE__ */ jsx9("span", { className: "aui-code-header-language text-muted-foreground font-medium lowercase", children: language }),
|
|
342
|
+
/* @__PURE__ */ jsxs5(IconButton, { tooltip: "Copy", onClick: onCopy, children: [
|
|
343
|
+
!isCopied && /* @__PURE__ */ jsx9(CopyIcon, { className: "animate-in zoom-in-75 fade-in duration-150" }),
|
|
344
|
+
isCopied && /* @__PURE__ */ jsx9(CheckIcon, { className: "animate-in zoom-in-50 fade-in duration-200 ease-out" })
|
|
345
|
+
] })
|
|
346
|
+
] });
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
// src/atoms/Markdown.tsx
|
|
350
|
+
import { Children, isValidElement, useMemo } from "react";
|
|
351
|
+
import ReactMarkdown from "react-markdown";
|
|
352
|
+
import remarkGfm from "remark-gfm";
|
|
353
|
+
|
|
354
|
+
// src/atoms/OpenUIBlock.tsx
|
|
355
|
+
import { memo, useId } from "react";
|
|
356
|
+
import { Renderer } from "@openuidev/react-lang";
|
|
357
|
+
import { ThemeProvider } from "@openuidev/react-ui";
|
|
358
|
+
import { openuiLibrary } from "@openuidev/react-ui/genui-lib";
|
|
359
|
+
|
|
360
|
+
// src/theme/useClassDarkMode.ts
|
|
361
|
+
import { useSyncExternalStore } from "react";
|
|
362
|
+
function getThemeMode() {
|
|
363
|
+
if (typeof document === "undefined") {
|
|
364
|
+
return "light";
|
|
365
|
+
}
|
|
366
|
+
return document.documentElement.classList.contains("dark") ? "dark" : "light";
|
|
367
|
+
}
|
|
368
|
+
function subscribe(onStoreChange) {
|
|
369
|
+
const observer = new MutationObserver(onStoreChange);
|
|
370
|
+
observer.observe(document.documentElement, {
|
|
371
|
+
attributes: true,
|
|
372
|
+
attributeFilter: ["class"]
|
|
373
|
+
});
|
|
374
|
+
return () => observer.disconnect();
|
|
375
|
+
}
|
|
376
|
+
function useClassDarkMode() {
|
|
377
|
+
return useSyncExternalStore(subscribe, getThemeMode, () => "light");
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
// src/atoms/OpenUIBlock.tsx
|
|
381
|
+
import { jsx as jsx10 } from "react/jsx-runtime";
|
|
382
|
+
var OpenUIBlock = memo(
|
|
383
|
+
function OpenUIBlock2({ source, isStreaming, className, mode: modeProp }) {
|
|
384
|
+
const detectedMode = useClassDarkMode();
|
|
385
|
+
const mode = modeProp ?? detectedMode;
|
|
386
|
+
const scopeClass = `aui-openui-theme-${useId().replace(/:/g, "")}`;
|
|
387
|
+
return /* @__PURE__ */ jsx10(ThemeProvider, { mode, cssSelector: `.${scopeClass}`, children: /* @__PURE__ */ jsx10(
|
|
388
|
+
"div",
|
|
389
|
+
{
|
|
390
|
+
"data-slot": "openui-block",
|
|
391
|
+
className: cn("aui-openui-block my-3", scopeClass, className),
|
|
392
|
+
style: { contain: "layout paint" },
|
|
393
|
+
children: /* @__PURE__ */ jsx10(
|
|
394
|
+
Renderer,
|
|
395
|
+
{
|
|
396
|
+
response: source,
|
|
397
|
+
library: openuiLibrary,
|
|
398
|
+
isStreaming: !!isStreaming
|
|
399
|
+
}
|
|
400
|
+
)
|
|
401
|
+
}
|
|
402
|
+
) });
|
|
403
|
+
},
|
|
404
|
+
(prev, next) => prev.source === next.source && !!prev.isStreaming === !!next.isStreaming && prev.mode === next.mode
|
|
405
|
+
);
|
|
406
|
+
|
|
407
|
+
// src/atoms/SandboxArtifactList.tsx
|
|
408
|
+
import { useState as useState2 } from "react";
|
|
409
|
+
import { DownloadIcon, FileIcon, LoaderIcon } from "lucide-react";
|
|
410
|
+
import { jsx as jsx11, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
411
|
+
function SandboxArtifactList({ artifacts, onDownload, className }) {
|
|
412
|
+
const [downloadingPath, setDownloadingPath] = useState2(null);
|
|
413
|
+
const handleClick = async (path) => {
|
|
414
|
+
if (downloadingPath != null) return;
|
|
415
|
+
setDownloadingPath(path);
|
|
416
|
+
try {
|
|
417
|
+
await onDownload?.(path);
|
|
418
|
+
} finally {
|
|
419
|
+
setDownloadingPath(null);
|
|
420
|
+
}
|
|
421
|
+
};
|
|
422
|
+
return /* @__PURE__ */ jsx11(
|
|
423
|
+
"div",
|
|
424
|
+
{
|
|
425
|
+
"data-slot": "aui_sandbox-artifact-list",
|
|
426
|
+
className: cn("aui-sandbox-artifact-list my-3 flex w-fit max-w-full flex-wrap items-stretch text-sm", className),
|
|
427
|
+
children: artifacts.map((artifact, index) => {
|
|
428
|
+
const isDownloading = downloadingPath === artifact.path;
|
|
429
|
+
return /* @__PURE__ */ jsxs6(
|
|
430
|
+
"button",
|
|
431
|
+
{
|
|
432
|
+
type: "button",
|
|
433
|
+
className: cn(
|
|
434
|
+
"aui-sandbox-artifact-button text-muted-foreground hover:text-foreground flex min-w-0 items-center gap-1.5 py-1 pr-2 pl-2 transition-colors disabled:pointer-events-none disabled:opacity-70",
|
|
435
|
+
index > 0 && "border-border/60 ml-1 border-l pl-3"
|
|
436
|
+
),
|
|
437
|
+
disabled: isDownloading,
|
|
438
|
+
onClick: () => handleClick(artifact.path),
|
|
439
|
+
children: [
|
|
440
|
+
/* @__PURE__ */ jsx11(FileIcon, { className: "size-4 shrink-0", "aria-hidden": true }),
|
|
441
|
+
/* @__PURE__ */ jsx11("span", { className: "max-w-40 truncate", children: artifact.label }),
|
|
442
|
+
isDownloading ? /* @__PURE__ */ jsx11(LoaderIcon, { className: "size-3.5 shrink-0 animate-spin [animation-duration:0.6s]", "aria-hidden": true }) : /* @__PURE__ */ jsx11(DownloadIcon, { className: "size-3.5 shrink-0", "aria-hidden": true })
|
|
443
|
+
]
|
|
444
|
+
},
|
|
445
|
+
artifact.path
|
|
446
|
+
);
|
|
447
|
+
})
|
|
448
|
+
}
|
|
449
|
+
);
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
// src/atoms/Markdown.tsx
|
|
453
|
+
import { Fragment, jsx as jsx12, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
454
|
+
function extractCodeText(node) {
|
|
455
|
+
if (typeof node === "string") return node;
|
|
456
|
+
if (typeof node === "number") return String(node);
|
|
457
|
+
if (Array.isArray(node)) return node.map(extractCodeText).join("");
|
|
458
|
+
if (isValidElement(node)) {
|
|
459
|
+
return extractCodeText(node.props.children);
|
|
460
|
+
}
|
|
461
|
+
return "";
|
|
462
|
+
}
|
|
463
|
+
var SANDBOX_ARTIFACT_TOKEN = "sandbox_artifact";
|
|
464
|
+
function parseSandboxArtifactCodeBlock(code) {
|
|
465
|
+
const links = [];
|
|
466
|
+
for (const match of code.matchAll(/\[([^\]]+)\]\(([^)]+)\)/g)) {
|
|
467
|
+
links.push({ label: match[1], path: match[2] });
|
|
468
|
+
}
|
|
469
|
+
return links.length > 0 ? links : null;
|
|
470
|
+
}
|
|
471
|
+
function parseSandboxArtifactParagraph(children) {
|
|
472
|
+
const items = Children.toArray(children);
|
|
473
|
+
if (items.length === 0) return null;
|
|
474
|
+
const first = items[0];
|
|
475
|
+
if (typeof first !== "string") return null;
|
|
476
|
+
const stripped = first.replace(/^\s*/, "");
|
|
477
|
+
if (!stripped.startsWith(SANDBOX_ARTIFACT_TOKEN)) return null;
|
|
478
|
+
if (!/^\s*$/.test(stripped.slice(SANDBOX_ARTIFACT_TOKEN.length))) return null;
|
|
479
|
+
const links = [];
|
|
480
|
+
for (let i = 1; i < items.length; i++) {
|
|
481
|
+
const item = items[i];
|
|
482
|
+
if (typeof item === "string") {
|
|
483
|
+
const trimmed = item.trim();
|
|
484
|
+
if (trimmed === "" || trimmed === SANDBOX_ARTIFACT_TOKEN) continue;
|
|
485
|
+
return null;
|
|
486
|
+
}
|
|
487
|
+
if (isValidElement(item) && typeof item.props.href === "string") {
|
|
488
|
+
links.push({
|
|
489
|
+
label: extractCodeText(item.props.children),
|
|
490
|
+
path: item.props.href
|
|
491
|
+
});
|
|
492
|
+
continue;
|
|
493
|
+
}
|
|
494
|
+
return null;
|
|
495
|
+
}
|
|
496
|
+
return links.length > 0 ? links : null;
|
|
497
|
+
}
|
|
498
|
+
function createMarkdownComponents(isStreaming, onDownloadArtifact) {
|
|
499
|
+
return {
|
|
500
|
+
h1: ({ className, ...props }) => /* @__PURE__ */ jsx12(
|
|
501
|
+
"h1",
|
|
502
|
+
{
|
|
503
|
+
className: cn(
|
|
504
|
+
"aui-md-h1 mt-5 mb-2 scroll-m-20 text-xl font-semibold first:mt-0 last:mb-0",
|
|
505
|
+
className
|
|
506
|
+
),
|
|
507
|
+
...props
|
|
508
|
+
}
|
|
509
|
+
),
|
|
510
|
+
h2: ({ className, ...props }) => /* @__PURE__ */ jsx12(
|
|
511
|
+
"h2",
|
|
512
|
+
{
|
|
513
|
+
className: cn(
|
|
514
|
+
"aui-md-h2 mt-5 mb-2 scroll-m-20 text-lg font-semibold first:mt-0 last:mb-0",
|
|
515
|
+
className
|
|
516
|
+
),
|
|
517
|
+
...props
|
|
518
|
+
}
|
|
519
|
+
),
|
|
520
|
+
h3: ({ className, ...props }) => /* @__PURE__ */ jsx12(
|
|
521
|
+
"h3",
|
|
522
|
+
{
|
|
523
|
+
className: cn(
|
|
524
|
+
"aui-md-h3 mt-4 mb-1.5 scroll-m-20 text-base font-semibold first:mt-0 last:mb-0",
|
|
525
|
+
className
|
|
526
|
+
),
|
|
527
|
+
...props
|
|
528
|
+
}
|
|
529
|
+
),
|
|
530
|
+
h4: ({ className, ...props }) => /* @__PURE__ */ jsx12(
|
|
531
|
+
"h4",
|
|
532
|
+
{
|
|
533
|
+
className: cn(
|
|
534
|
+
"aui-md-h4 mt-3.5 mb-1 scroll-m-20 text-base font-medium first:mt-0 last:mb-0",
|
|
535
|
+
className
|
|
536
|
+
),
|
|
537
|
+
...props
|
|
538
|
+
}
|
|
539
|
+
),
|
|
540
|
+
h5: ({ className, ...props }) => /* @__PURE__ */ jsx12(
|
|
541
|
+
"h5",
|
|
542
|
+
{
|
|
543
|
+
className: cn("aui-md-h5 mt-3 mb-1 text-sm font-semibold first:mt-0 last:mb-0", className),
|
|
544
|
+
...props
|
|
545
|
+
}
|
|
546
|
+
),
|
|
547
|
+
h6: ({ className, ...props }) => /* @__PURE__ */ jsx12(
|
|
548
|
+
"h6",
|
|
549
|
+
{
|
|
550
|
+
className: cn("aui-md-h6 mt-3 mb-1 text-sm font-medium first:mt-0 last:mb-0", className),
|
|
551
|
+
...props
|
|
552
|
+
}
|
|
553
|
+
),
|
|
554
|
+
p: ({ className, children, ...props }) => {
|
|
555
|
+
const artifacts = parseSandboxArtifactParagraph(children);
|
|
556
|
+
if (artifacts != null) {
|
|
557
|
+
return /* @__PURE__ */ jsx12(SandboxArtifactList, { artifacts, onDownload: onDownloadArtifact });
|
|
558
|
+
}
|
|
559
|
+
return /* @__PURE__ */ jsx12("p", { className: cn("aui-md-p my-3 leading-relaxed first:mt-0 last:mb-0", className), ...props, children });
|
|
560
|
+
},
|
|
561
|
+
a: ({ className, ...props }) => /* @__PURE__ */ jsx12(
|
|
562
|
+
"a",
|
|
563
|
+
{
|
|
564
|
+
className: cn(
|
|
565
|
+
"aui-md-a text-primary hover:text-primary/80 underline underline-offset-2",
|
|
566
|
+
className
|
|
567
|
+
),
|
|
568
|
+
target: "_blank",
|
|
569
|
+
rel: "noopener noreferrer",
|
|
570
|
+
...props
|
|
571
|
+
}
|
|
572
|
+
),
|
|
573
|
+
blockquote: ({ className, ...props }) => /* @__PURE__ */ jsx12(
|
|
574
|
+
"blockquote",
|
|
575
|
+
{
|
|
576
|
+
className: cn(
|
|
577
|
+
"aui-md-blockquote border-muted-foreground/30 text-muted-foreground my-3 border-s-2 ps-4",
|
|
578
|
+
className
|
|
579
|
+
),
|
|
580
|
+
...props
|
|
581
|
+
}
|
|
582
|
+
),
|
|
583
|
+
ul: ({ className, ...props }) => /* @__PURE__ */ jsx12(
|
|
584
|
+
"ul",
|
|
585
|
+
{
|
|
586
|
+
className: cn(
|
|
587
|
+
"aui-md-ul marker:text-muted-foreground my-3 ms-5 list-disc [&>li]:mt-1",
|
|
588
|
+
className
|
|
589
|
+
),
|
|
590
|
+
...props
|
|
591
|
+
}
|
|
592
|
+
),
|
|
593
|
+
ol: ({ className, ...props }) => /* @__PURE__ */ jsx12(
|
|
594
|
+
"ol",
|
|
595
|
+
{
|
|
596
|
+
className: cn(
|
|
597
|
+
"aui-md-ol marker:text-muted-foreground my-3 ms-5 list-decimal [&>li]:mt-1",
|
|
598
|
+
className
|
|
599
|
+
),
|
|
600
|
+
...props
|
|
601
|
+
}
|
|
602
|
+
),
|
|
603
|
+
hr: ({ className, ...props }) => /* @__PURE__ */ jsx12("hr", { className: cn("aui-md-hr border-muted-foreground/20 my-3", className), ...props }),
|
|
604
|
+
table: ({ className, ...props }) => /* @__PURE__ */ jsx12(
|
|
605
|
+
"table",
|
|
606
|
+
{
|
|
607
|
+
className: cn(
|
|
608
|
+
"aui-md-table my-3 w-full border-separate border-spacing-0 overflow-y-auto",
|
|
609
|
+
className
|
|
610
|
+
),
|
|
611
|
+
...props
|
|
612
|
+
}
|
|
613
|
+
),
|
|
614
|
+
th: ({ className, ...props }) => /* @__PURE__ */ jsx12(
|
|
615
|
+
"th",
|
|
616
|
+
{
|
|
617
|
+
className: cn(
|
|
618
|
+
"aui-md-th bg-muted px-3 py-1.5 text-start font-medium first:rounded-ss-lg last:rounded-se-lg [[align=center]]:text-center [[align=right]]:text-right",
|
|
619
|
+
className
|
|
620
|
+
),
|
|
621
|
+
...props
|
|
622
|
+
}
|
|
623
|
+
),
|
|
624
|
+
td: ({ className, ...props }) => /* @__PURE__ */ jsx12(
|
|
625
|
+
"td",
|
|
626
|
+
{
|
|
627
|
+
className: cn(
|
|
628
|
+
"aui-md-td border-muted-foreground/20 border-s border-b px-3 py-1.5 text-start last:border-e [[align=center]]:text-center [[align=right]]:text-right",
|
|
629
|
+
className
|
|
630
|
+
),
|
|
631
|
+
...props
|
|
632
|
+
}
|
|
633
|
+
),
|
|
634
|
+
tr: ({ className, ...props }) => /* @__PURE__ */ jsx12(
|
|
635
|
+
"tr",
|
|
636
|
+
{
|
|
637
|
+
className: cn(
|
|
638
|
+
"aui-md-tr m-0 border-b p-0 first:border-t [&:last-child>td:first-child]:rounded-es-lg [&:last-child>td:last-child]:rounded-ee-lg",
|
|
639
|
+
className
|
|
640
|
+
),
|
|
641
|
+
...props
|
|
642
|
+
}
|
|
643
|
+
),
|
|
644
|
+
li: ({ className, ...props }) => /* @__PURE__ */ jsx12("li", { className: cn("aui-md-li leading-relaxed", className), ...props }),
|
|
645
|
+
strong: ({ className, ...props }) => /* @__PURE__ */ jsx12("strong", { className: cn("aui-md-strong font-semibold", className), ...props }),
|
|
646
|
+
sup: ({ className, ...props }) => /* @__PURE__ */ jsx12("sup", { className: cn("aui-md-sup [&>a]:text-xs [&>a]:no-underline", className), ...props }),
|
|
647
|
+
pre: ({ className, children, ...props }) => {
|
|
648
|
+
const codeElement = isValidElement(children) ? children : void 0;
|
|
649
|
+
const codeClassName = codeElement?.props?.className ?? "";
|
|
650
|
+
const language = /language-(\S+)/.exec(codeClassName)?.[1] ?? "text";
|
|
651
|
+
const code = extractCodeText(children);
|
|
652
|
+
if (language === "openui") {
|
|
653
|
+
return /* @__PURE__ */ jsx12(OpenUIBlock, { source: code, isStreaming });
|
|
654
|
+
}
|
|
655
|
+
if (language === "sandbox_artifact" || language === "sandbox_artifacts") {
|
|
656
|
+
const artifacts = parseSandboxArtifactCodeBlock(code);
|
|
657
|
+
if (artifacts != null) {
|
|
658
|
+
return /* @__PURE__ */ jsx12(SandboxArtifactList, { artifacts, onDownload: onDownloadArtifact });
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
return /* @__PURE__ */ jsxs7(Fragment, { children: [
|
|
662
|
+
/* @__PURE__ */ jsx12(CodeBlockHeader, { language, code }),
|
|
663
|
+
/* @__PURE__ */ jsx12(
|
|
664
|
+
"pre",
|
|
665
|
+
{
|
|
666
|
+
className: cn(
|
|
667
|
+
"aui-md-pre border-border/50 bg-muted/30 overflow-x-auto rounded-t-none rounded-b-xl border border-t-0 p-3.5 text-[13px] leading-relaxed",
|
|
668
|
+
className
|
|
669
|
+
),
|
|
670
|
+
...props,
|
|
671
|
+
children
|
|
672
|
+
}
|
|
673
|
+
)
|
|
674
|
+
] });
|
|
675
|
+
},
|
|
676
|
+
code: ({ className, ...props }) => {
|
|
677
|
+
const isCodeBlock = /language-/.test(className ?? "");
|
|
678
|
+
return /* @__PURE__ */ jsx12(
|
|
679
|
+
"code",
|
|
680
|
+
{
|
|
681
|
+
className: cn(
|
|
682
|
+
!isCodeBlock && "aui-md-inline-code bg-muted rounded-md px-1.5 py-0.5 font-mono text-[0.85em]",
|
|
683
|
+
className
|
|
684
|
+
),
|
|
685
|
+
...props
|
|
686
|
+
}
|
|
687
|
+
);
|
|
688
|
+
}
|
|
689
|
+
};
|
|
690
|
+
}
|
|
691
|
+
function Markdown({ content, className, isStreaming, onDownloadArtifact }) {
|
|
692
|
+
const components = useMemo(
|
|
693
|
+
() => createMarkdownComponents(isStreaming, onDownloadArtifact),
|
|
694
|
+
[isStreaming, onDownloadArtifact]
|
|
695
|
+
);
|
|
696
|
+
return /* @__PURE__ */ jsx12("div", { className: cn("aui-md", className), children: /* @__PURE__ */ jsx12(ReactMarkdown, { remarkPlugins: [remarkGfm], components, children: content }) });
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
// src/atoms/MessageActionBar.tsx
|
|
700
|
+
import { CheckIcon as CheckIcon2, CopyIcon as CopyIcon2, DownloadIcon as DownloadIcon2, MoreHorizontalIcon } from "lucide-react";
|
|
701
|
+
import { DropdownMenu } from "radix-ui";
|
|
702
|
+
import { jsx as jsx13, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
703
|
+
function MessageActionBar({ isCopied, onCopy, onExportMarkdown, className }) {
|
|
704
|
+
return /* @__PURE__ */ jsxs8(
|
|
705
|
+
"div",
|
|
706
|
+
{
|
|
707
|
+
className: cn(
|
|
708
|
+
"aui-assistant-action-bar-root text-muted-foreground animate-in fade-in flex gap-1 duration-200",
|
|
709
|
+
className
|
|
710
|
+
),
|
|
711
|
+
children: [
|
|
712
|
+
/* @__PURE__ */ jsx13(IconButton, { tooltip: "Copy", onClick: onCopy, children: isCopied ? /* @__PURE__ */ jsx13(CheckIcon2, { className: "animate-in zoom-in-50 fade-in duration-200 ease-out" }) : /* @__PURE__ */ jsx13(CopyIcon2, { className: "animate-in zoom-in-75 fade-in duration-150" }) }),
|
|
713
|
+
/* @__PURE__ */ jsxs8(DropdownMenu.Root, { children: [
|
|
714
|
+
/* @__PURE__ */ jsx13(DropdownMenu.Trigger, { asChild: true, children: /* @__PURE__ */ jsx13(IconButton, { tooltip: "More", className: "data-[state=open]:bg-accent", children: /* @__PURE__ */ jsx13(MoreHorizontalIcon, {}) }) }),
|
|
715
|
+
/* @__PURE__ */ jsx13(DropdownMenu.Portal, { children: /* @__PURE__ */ jsx13(
|
|
716
|
+
DropdownMenu.Content,
|
|
717
|
+
{
|
|
718
|
+
side: "bottom",
|
|
719
|
+
align: "start",
|
|
720
|
+
sideOffset: 6,
|
|
721
|
+
className: "aui-action-bar-more-content bg-popover/95 text-popover-foreground data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95 data-[state=open]:animate-in data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=closed]:animate-out data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 min-w-[8rem] overflow-hidden rounded-xl border p-1.5 shadow-lg backdrop-blur-sm",
|
|
722
|
+
children: /* @__PURE__ */ jsxs8(
|
|
723
|
+
DropdownMenu.Item,
|
|
724
|
+
{
|
|
725
|
+
onSelect: onExportMarkdown,
|
|
726
|
+
className: "aui-action-bar-more-item hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground flex cursor-pointer items-center gap-2 rounded-lg px-2.5 py-1.5 text-sm outline-none select-none",
|
|
727
|
+
children: [
|
|
728
|
+
/* @__PURE__ */ jsx13(DownloadIcon2, { className: "size-4" }),
|
|
729
|
+
"Export as Markdown"
|
|
730
|
+
]
|
|
731
|
+
}
|
|
732
|
+
)
|
|
733
|
+
}
|
|
734
|
+
) })
|
|
735
|
+
] })
|
|
736
|
+
]
|
|
737
|
+
}
|
|
738
|
+
);
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
// src/atoms/UserMessageActionBar.tsx
|
|
742
|
+
import { ActionBarPrimitive, useAui, useAuiState } from "@assistant-ui/react";
|
|
743
|
+
import { useActionBarCopy } from "@assistant-ui/core/react";
|
|
744
|
+
import { CheckIcon as CheckIcon3, CopyIcon as CopyIcon3, PencilIcon, RotateCcwIcon } from "lucide-react";
|
|
745
|
+
import { trueFoundryExtras } from "@truefoundry/assistant-ui-runtime";
|
|
746
|
+
import { jsx as jsx14, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
747
|
+
function parseTurnIdFromMessageId(messageId) {
|
|
748
|
+
return messageId.replace(/-user$/, "");
|
|
749
|
+
}
|
|
750
|
+
function UserMessageActionBar({ className }) {
|
|
751
|
+
const IconButton2 = useSlot("IconButton");
|
|
752
|
+
const aui = useAui();
|
|
753
|
+
const messageId = useAuiState((s) => s.message.id);
|
|
754
|
+
const turnId = parseTurnIdFromMessageId(messageId);
|
|
755
|
+
const { isCopied } = useActionBarCopy();
|
|
756
|
+
return /* @__PURE__ */ jsxs9(
|
|
757
|
+
ActionBarPrimitive.Root,
|
|
758
|
+
{
|
|
759
|
+
hideWhenRunning: true,
|
|
760
|
+
className: cn(
|
|
761
|
+
"aui-user-action-bar-root text-muted-foreground animate-in fade-in flex gap-1 duration-200",
|
|
762
|
+
className
|
|
763
|
+
),
|
|
764
|
+
children: [
|
|
765
|
+
/* @__PURE__ */ jsx14(ActionBarPrimitive.Edit, { asChild: true, children: /* @__PURE__ */ jsx14(IconButton2, { tooltip: "Edit", children: /* @__PURE__ */ jsx14(PencilIcon, {}) }) }),
|
|
766
|
+
/* @__PURE__ */ jsx14(
|
|
767
|
+
IconButton2,
|
|
768
|
+
{
|
|
769
|
+
tooltip: "Reset",
|
|
770
|
+
onClick: () => void trueFoundryExtras.get(aui).resetFromTurn(turnId),
|
|
771
|
+
children: /* @__PURE__ */ jsx14(RotateCcwIcon, {})
|
|
772
|
+
}
|
|
773
|
+
),
|
|
774
|
+
/* @__PURE__ */ jsx14(ActionBarPrimitive.Copy, { asChild: true, children: /* @__PURE__ */ jsx14(IconButton2, { tooltip: "Copy", children: isCopied ? /* @__PURE__ */ jsx14(CheckIcon3, { className: "animate-in zoom-in-50 fade-in duration-200 ease-out" }) : /* @__PURE__ */ jsx14(CopyIcon3, { className: "animate-in zoom-in-75 fade-in duration-150" }) }) })
|
|
775
|
+
]
|
|
776
|
+
}
|
|
777
|
+
);
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
// src/atoms/MessageBubble.tsx
|
|
781
|
+
import { jsx as jsx15, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
782
|
+
function MessageBubble(props) {
|
|
783
|
+
if (props.variant === "assistant") {
|
|
784
|
+
const { children: children2, error, branchIndicator: branchIndicator2, actionBar: actionBar2, className: className2 } = props;
|
|
785
|
+
return /* @__PURE__ */ jsxs10(
|
|
786
|
+
"div",
|
|
787
|
+
{
|
|
788
|
+
"data-slot": "aui_assistant-message-root",
|
|
789
|
+
className: cn("fade-in slide-in-from-bottom-1 animate-in relative duration-150", className2),
|
|
790
|
+
children: [
|
|
791
|
+
/* @__PURE__ */ jsxs10(
|
|
792
|
+
"div",
|
|
793
|
+
{
|
|
794
|
+
"data-slot": "aui_assistant-message-content",
|
|
795
|
+
className: "text-foreground flex flex-col gap-3 px-2 leading-relaxed wrap-break-word [contain-intrinsic-size:auto_24px] [content-visibility:auto]",
|
|
796
|
+
children: [
|
|
797
|
+
children2,
|
|
798
|
+
error
|
|
799
|
+
]
|
|
800
|
+
}
|
|
801
|
+
),
|
|
802
|
+
/* @__PURE__ */ jsxs10("div", { "data-slot": "aui_assistant-message-footer", className: "ms-2 -mb-7.5 min-h-7.5 pt-1.5 flex items-center", children: [
|
|
803
|
+
branchIndicator2,
|
|
804
|
+
actionBar2
|
|
805
|
+
] })
|
|
806
|
+
]
|
|
807
|
+
}
|
|
808
|
+
);
|
|
809
|
+
}
|
|
810
|
+
const { children, attachments, branchIndicator, actionBar, className } = props;
|
|
811
|
+
return /* @__PURE__ */ jsxs10(
|
|
812
|
+
"div",
|
|
813
|
+
{
|
|
814
|
+
"data-slot": "aui_user-message-root",
|
|
815
|
+
className: cn(
|
|
816
|
+
"fade-in slide-in-from-bottom-1 animate-in grid auto-rows-auto grid-cols-[minmax(72px,1fr)_auto] content-start gap-y-2 px-2 duration-150 [contain-intrinsic-size:auto_60px] [content-visibility:auto] [&:where(>*)]:col-start-2",
|
|
817
|
+
className
|
|
818
|
+
),
|
|
819
|
+
children: [
|
|
820
|
+
attachments,
|
|
821
|
+
/* @__PURE__ */ jsx15("div", { className: "aui-user-message-content-wrapper relative col-start-2 min-w-0", children: /* @__PURE__ */ jsx15("div", { className: "aui-user-message-content bg-muted text-foreground rounded-xl px-4 py-2 wrap-break-word empty:hidden", children }) }),
|
|
822
|
+
(branchIndicator != null || actionBar != null) && /* @__PURE__ */ jsxs10(
|
|
823
|
+
"div",
|
|
824
|
+
{
|
|
825
|
+
"data-slot": "aui_user-message-footer",
|
|
826
|
+
className: "col-span-full col-start-1 row-start-3 -me-1 flex items-center justify-end gap-1",
|
|
827
|
+
children: [
|
|
828
|
+
branchIndicator,
|
|
829
|
+
actionBar
|
|
830
|
+
]
|
|
831
|
+
}
|
|
832
|
+
)
|
|
833
|
+
]
|
|
834
|
+
}
|
|
835
|
+
);
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
// src/atoms/MessageErrorBanner.tsx
|
|
839
|
+
import { jsx as jsx16 } from "react/jsx-runtime";
|
|
840
|
+
function MessageErrorBanner({ message, className }) {
|
|
841
|
+
return /* @__PURE__ */ jsx16(
|
|
842
|
+
"div",
|
|
843
|
+
{
|
|
844
|
+
role: "alert",
|
|
845
|
+
className: cn(
|
|
846
|
+
"aui-message-error-root border-destructive bg-destructive/10 text-destructive dark:bg-destructive/5 mt-2 rounded-md border p-3 text-sm dark:text-red-200",
|
|
847
|
+
className
|
|
848
|
+
),
|
|
849
|
+
children: /* @__PURE__ */ jsx16("span", { className: "aui-message-error-message line-clamp-2", children: message })
|
|
850
|
+
}
|
|
851
|
+
);
|
|
852
|
+
}
|
|
853
|
+
|
|
854
|
+
// src/atoms/MessageIndicator.tsx
|
|
855
|
+
import { jsx as jsx17 } from "react/jsx-runtime";
|
|
856
|
+
function MessageIndicator({ className }) {
|
|
857
|
+
return /* @__PURE__ */ jsx17(
|
|
858
|
+
"span",
|
|
859
|
+
{
|
|
860
|
+
"data-slot": "aui_assistant-message-indicator",
|
|
861
|
+
className: cn("animate-pulse font-sans", className),
|
|
862
|
+
"aria-label": "Assistant is working",
|
|
863
|
+
children: "\u25CF"
|
|
864
|
+
}
|
|
865
|
+
);
|
|
866
|
+
}
|
|
867
|
+
|
|
868
|
+
// src/atoms/ScrollToBottomButton.tsx
|
|
869
|
+
import { forwardRef as forwardRef2 } from "react";
|
|
870
|
+
import { ArrowDownIcon } from "lucide-react";
|
|
871
|
+
import { jsx as jsx18 } from "react/jsx-runtime";
|
|
872
|
+
var ScrollToBottomButton = forwardRef2(
|
|
873
|
+
({ className, ...rest }, ref) => {
|
|
874
|
+
return /* @__PURE__ */ jsx18(
|
|
875
|
+
IconButton,
|
|
876
|
+
{
|
|
877
|
+
ref,
|
|
878
|
+
tooltip: "Scroll to bottom",
|
|
879
|
+
variant: "outline",
|
|
880
|
+
className: cn(
|
|
881
|
+
"aui-thread-scroll-to-bottom dark:border-border dark:bg-background dark:hover:bg-accent absolute -top-14 z-10 self-center rounded-full p-4 disabled:invisible",
|
|
882
|
+
className
|
|
883
|
+
),
|
|
884
|
+
...rest,
|
|
885
|
+
children: /* @__PURE__ */ jsx18(ArrowDownIcon, {})
|
|
886
|
+
}
|
|
887
|
+
);
|
|
888
|
+
}
|
|
889
|
+
);
|
|
890
|
+
ScrollToBottomButton.displayName = "ScrollToBottomButton";
|
|
891
|
+
|
|
892
|
+
// src/atoms/Skeletons.tsx
|
|
893
|
+
import { jsx as jsx19, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
894
|
+
function MessageListSkeleton({ className }) {
|
|
895
|
+
return /* @__PURE__ */ jsxs11(
|
|
896
|
+
"div",
|
|
897
|
+
{
|
|
898
|
+
role: "status",
|
|
899
|
+
"aria-label": "Loading conversation",
|
|
900
|
+
"data-slot": "aui_thread-history-skeleton",
|
|
901
|
+
className: cn("mb-14 flex flex-col gap-y-6", className),
|
|
902
|
+
children: [
|
|
903
|
+
/* @__PURE__ */ jsx19("div", { className: "flex justify-end", children: /* @__PURE__ */ jsx19(Skeleton, { className: "h-10 w-[min(85%,20rem)] rounded-xl" }) }),
|
|
904
|
+
/* @__PURE__ */ jsxs11("div", { className: "flex flex-col gap-2 px-2", children: [
|
|
905
|
+
/* @__PURE__ */ jsx19(Skeleton, { className: "h-4 w-full max-w-md" }),
|
|
906
|
+
/* @__PURE__ */ jsx19(Skeleton, { className: "h-4 w-full max-w-sm" }),
|
|
907
|
+
/* @__PURE__ */ jsx19(Skeleton, { className: "h-4 w-2/3 max-w-xs" })
|
|
908
|
+
] })
|
|
909
|
+
]
|
|
910
|
+
}
|
|
911
|
+
);
|
|
912
|
+
}
|
|
913
|
+
|
|
914
|
+
// src/atoms/ThreadShell.tsx
|
|
915
|
+
import { forwardRef as forwardRef3 } from "react";
|
|
916
|
+
import { jsx as jsx20 } from "react/jsx-runtime";
|
|
917
|
+
var THREAD_CSS_VARS = {
|
|
918
|
+
["--thread-max-width"]: "44rem",
|
|
919
|
+
["--composer-bg"]: "color-mix(in oklab, var(--color-muted) 30%, var(--color-background))",
|
|
920
|
+
["--composer-radius"]: "1.5rem",
|
|
921
|
+
["--composer-padding"]: "8px"
|
|
922
|
+
};
|
|
923
|
+
var ThreadRootShell = forwardRef3(
|
|
924
|
+
({ className, style, ...rest }, ref) => /* @__PURE__ */ jsx20(
|
|
925
|
+
"div",
|
|
926
|
+
{
|
|
927
|
+
ref,
|
|
928
|
+
className: cn(
|
|
929
|
+
"aui-root aui-thread-root bg-background @container flex h-full min-h-0 flex-col overflow-hidden",
|
|
930
|
+
className
|
|
931
|
+
),
|
|
932
|
+
style: { ...THREAD_CSS_VARS, ...style },
|
|
933
|
+
...rest
|
|
934
|
+
}
|
|
935
|
+
)
|
|
936
|
+
);
|
|
937
|
+
ThreadRootShell.displayName = "ThreadRootShell";
|
|
938
|
+
var ThreadViewportShell = forwardRef3(
|
|
939
|
+
({ className, isEmpty, children, ...rest }, ref) => /* @__PURE__ */ jsx20(
|
|
940
|
+
"div",
|
|
941
|
+
{
|
|
942
|
+
ref,
|
|
943
|
+
"data-slot": "aui_thread-viewport",
|
|
944
|
+
className: cn("relative flex min-h-0 flex-1 flex-col overflow-x-auto overflow-y-auto scroll-smooth", className),
|
|
945
|
+
...rest,
|
|
946
|
+
children: /* @__PURE__ */ jsx20(
|
|
947
|
+
"div",
|
|
948
|
+
{
|
|
949
|
+
className: cn(
|
|
950
|
+
"mx-auto flex w-full max-w-(--thread-max-width) flex-col px-4 pt-4 pb-4",
|
|
951
|
+
isEmpty && "min-h-full justify-center"
|
|
952
|
+
),
|
|
953
|
+
children
|
|
954
|
+
}
|
|
955
|
+
)
|
|
956
|
+
}
|
|
957
|
+
)
|
|
958
|
+
);
|
|
959
|
+
ThreadViewportShell.displayName = "ThreadViewportShell";
|
|
960
|
+
var ThreadComposerAreaShell = forwardRef3(
|
|
961
|
+
({ className, isEmpty, ...rest }, ref) => /* @__PURE__ */ jsx20(
|
|
962
|
+
"div",
|
|
963
|
+
{
|
|
964
|
+
ref,
|
|
965
|
+
"data-slot": "aui_thread-composer",
|
|
966
|
+
className: cn(
|
|
967
|
+
"aui-thread-composer bg-background relative mx-auto flex w-full max-w-(--thread-max-width) shrink-0 flex-col gap-4 px-4 pb-4 md:pb-6",
|
|
968
|
+
!isEmpty && "rounded-t-(--composer-radius)",
|
|
969
|
+
className
|
|
970
|
+
),
|
|
971
|
+
...rest
|
|
972
|
+
}
|
|
973
|
+
)
|
|
974
|
+
);
|
|
975
|
+
ThreadComposerAreaShell.displayName = "ThreadComposerAreaShell";
|
|
976
|
+
var MessageGroup = forwardRef3(({ className, ...rest }, ref) => /* @__PURE__ */ jsx20(
|
|
977
|
+
"div",
|
|
978
|
+
{
|
|
979
|
+
ref,
|
|
980
|
+
"data-slot": "aui_message-group",
|
|
981
|
+
className: cn("flex flex-col gap-y-6 empty:hidden", className),
|
|
982
|
+
...rest
|
|
983
|
+
}
|
|
984
|
+
));
|
|
985
|
+
MessageGroup.displayName = "MessageGroup";
|
|
986
|
+
|
|
987
|
+
// src/atoms/AskUserPrompt.tsx
|
|
988
|
+
import { jsx as jsx21, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
989
|
+
var OTHER_OPTION_ID = "__other";
|
|
990
|
+
function AskUserPrompt({
|
|
991
|
+
question,
|
|
992
|
+
options,
|
|
993
|
+
allowOther,
|
|
994
|
+
selectedOptionId,
|
|
995
|
+
otherValue,
|
|
996
|
+
disabled,
|
|
997
|
+
onSelectOption,
|
|
998
|
+
onOtherValueChange,
|
|
999
|
+
onSubmit,
|
|
1000
|
+
className
|
|
1001
|
+
}) {
|
|
1002
|
+
const canSubmit = selectedOptionId != null && selectedOptionId !== OTHER_OPTION_ID ? true : selectedOptionId === OTHER_OPTION_ID && otherValue.trim().length > 0;
|
|
1003
|
+
return /* @__PURE__ */ jsxs12(
|
|
1004
|
+
"div",
|
|
1005
|
+
{
|
|
1006
|
+
"data-slot": "aui_ask-user-prompt",
|
|
1007
|
+
className: cn(
|
|
1008
|
+
"border-border/60 flex w-full flex-col gap-3 rounded-[var(--composer-radius,1.5rem)] border bg-[var(--composer-bg,var(--muted))] p-[var(--composer-padding,8px)]",
|
|
1009
|
+
className
|
|
1010
|
+
),
|
|
1011
|
+
children: [
|
|
1012
|
+
/* @__PURE__ */ jsx21("p", { className: "text-foreground px-2.5 text-sm font-medium", children: question }),
|
|
1013
|
+
/* @__PURE__ */ jsxs12("div", { className: "flex flex-col gap-1.5 px-2.5", children: [
|
|
1014
|
+
options.map((option) => /* @__PURE__ */ jsxs12("label", { className: "flex items-center gap-2 text-sm", children: [
|
|
1015
|
+
/* @__PURE__ */ jsx21(
|
|
1016
|
+
"input",
|
|
1017
|
+
{
|
|
1018
|
+
type: "radio",
|
|
1019
|
+
name: "ask-user-option",
|
|
1020
|
+
checked: selectedOptionId === option.id,
|
|
1021
|
+
disabled,
|
|
1022
|
+
onChange: () => onSelectOption(option.id)
|
|
1023
|
+
}
|
|
1024
|
+
),
|
|
1025
|
+
option.label
|
|
1026
|
+
] }, option.id)),
|
|
1027
|
+
allowOther && /* @__PURE__ */ jsxs12("label", { className: "flex items-center gap-2 text-sm", children: [
|
|
1028
|
+
/* @__PURE__ */ jsx21(
|
|
1029
|
+
"input",
|
|
1030
|
+
{
|
|
1031
|
+
type: "radio",
|
|
1032
|
+
name: "ask-user-option",
|
|
1033
|
+
checked: selectedOptionId === OTHER_OPTION_ID,
|
|
1034
|
+
disabled,
|
|
1035
|
+
onChange: () => onSelectOption(OTHER_OPTION_ID)
|
|
1036
|
+
}
|
|
1037
|
+
),
|
|
1038
|
+
/* @__PURE__ */ jsx21(
|
|
1039
|
+
"input",
|
|
1040
|
+
{
|
|
1041
|
+
type: "text",
|
|
1042
|
+
value: otherValue,
|
|
1043
|
+
placeholder: "Type your answer...",
|
|
1044
|
+
disabled,
|
|
1045
|
+
onFocus: () => onSelectOption(OTHER_OPTION_ID),
|
|
1046
|
+
onChange: (event) => {
|
|
1047
|
+
onSelectOption(OTHER_OPTION_ID);
|
|
1048
|
+
onOtherValueChange(event.target.value);
|
|
1049
|
+
},
|
|
1050
|
+
"aria-label": "Other answer",
|
|
1051
|
+
className: "border-border/60 flex-1 rounded-md border bg-transparent px-2 py-1 text-sm outline-none"
|
|
1052
|
+
}
|
|
1053
|
+
)
|
|
1054
|
+
] })
|
|
1055
|
+
] }),
|
|
1056
|
+
/* @__PURE__ */ jsx21("div", { className: "flex justify-end px-2.5", children: /* @__PURE__ */ jsx21(
|
|
1057
|
+
Button,
|
|
1058
|
+
{
|
|
1059
|
+
type: "button",
|
|
1060
|
+
className: "rounded-full px-4",
|
|
1061
|
+
disabled: disabled || !canSubmit,
|
|
1062
|
+
onClick: onSubmit,
|
|
1063
|
+
children: "Submit"
|
|
1064
|
+
}
|
|
1065
|
+
) })
|
|
1066
|
+
]
|
|
1067
|
+
}
|
|
1068
|
+
);
|
|
1069
|
+
}
|
|
1070
|
+
|
|
1071
|
+
// src/atoms/AttachmentCard.tsx
|
|
1072
|
+
import { FileTextIcon, XIcon as XIcon2 } from "lucide-react";
|
|
1073
|
+
import { jsx as jsx22, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
1074
|
+
var USER_MESSAGE_ATTACHMENT_PREVIEW_REM = 12;
|
|
1075
|
+
function AttachmentCard({
|
|
1076
|
+
name,
|
|
1077
|
+
previewSrc,
|
|
1078
|
+
isImage = false,
|
|
1079
|
+
size = "chip",
|
|
1080
|
+
previewRem,
|
|
1081
|
+
onRemove,
|
|
1082
|
+
className
|
|
1083
|
+
}) {
|
|
1084
|
+
if (size === "preview" && isImage && previewSrc) {
|
|
1085
|
+
const previewSize = previewRem != null ? { width: `${previewRem}rem`, height: `${previewRem}rem` } : void 0;
|
|
1086
|
+
return /* @__PURE__ */ jsx22(
|
|
1087
|
+
"div",
|
|
1088
|
+
{
|
|
1089
|
+
"data-slot": "aui_attachment-preview",
|
|
1090
|
+
style: previewSize,
|
|
1091
|
+
className: cn(
|
|
1092
|
+
"aui-attachment-preview relative shrink-0 cursor-pointer overflow-hidden rounded-lg border",
|
|
1093
|
+
previewRem == null && "size-24",
|
|
1094
|
+
className
|
|
1095
|
+
),
|
|
1096
|
+
children: /* @__PURE__ */ jsx22("img", { src: previewSrc, alt: name, className: "h-full w-full object-cover" })
|
|
1097
|
+
}
|
|
1098
|
+
);
|
|
1099
|
+
}
|
|
1100
|
+
return /* @__PURE__ */ jsxs13(
|
|
1101
|
+
"div",
|
|
1102
|
+
{
|
|
1103
|
+
"data-slot": "aui_attachment-chip",
|
|
1104
|
+
style: previewRem != null ? { maxWidth: `${previewRem}rem` } : void 0,
|
|
1105
|
+
className: cn(
|
|
1106
|
+
"aui-attachment-chip bg-muted flex max-w-full shrink-0 items-center gap-2 rounded-lg border px-2 py-1.5",
|
|
1107
|
+
className
|
|
1108
|
+
),
|
|
1109
|
+
children: [
|
|
1110
|
+
/* @__PURE__ */ jsx22("div", { className: "bg-background flex size-7 shrink-0 items-center justify-center overflow-hidden rounded-md border", children: isImage && previewSrc ? /* @__PURE__ */ jsxs13(Avatar, { className: "size-7 rounded-none", children: [
|
|
1111
|
+
/* @__PURE__ */ jsx22(AvatarImage, { src: previewSrc, alt: name, className: "object-cover" }),
|
|
1112
|
+
/* @__PURE__ */ jsx22(AvatarFallback, { children: /* @__PURE__ */ jsx22(FileTextIcon, { className: "text-muted-foreground size-4" }) })
|
|
1113
|
+
] }) : /* @__PURE__ */ jsx22(FileTextIcon, { className: "text-muted-foreground size-4" }) }),
|
|
1114
|
+
/* @__PURE__ */ jsx22("span", { className: "text-foreground min-w-0 truncate text-sm", children: name }),
|
|
1115
|
+
onRemove && /* @__PURE__ */ jsx22(
|
|
1116
|
+
IconButton,
|
|
1117
|
+
{
|
|
1118
|
+
tooltip: "Remove file",
|
|
1119
|
+
side: "top",
|
|
1120
|
+
className: "size-6 shrink-0 rounded-full [&_svg]:size-3",
|
|
1121
|
+
onClick: onRemove,
|
|
1122
|
+
children: /* @__PURE__ */ jsx22(XIcon2, {})
|
|
1123
|
+
}
|
|
1124
|
+
)
|
|
1125
|
+
]
|
|
1126
|
+
}
|
|
1127
|
+
);
|
|
1128
|
+
}
|
|
1129
|
+
|
|
1130
|
+
// src/atoms/AttachmentPickerButton.tsx
|
|
1131
|
+
import { PlusIcon } from "lucide-react";
|
|
1132
|
+
import { jsx as jsx23 } from "react/jsx-runtime";
|
|
1133
|
+
function AttachmentPickerButton(props) {
|
|
1134
|
+
return /* @__PURE__ */ jsx23(IconButton, { tooltip: "Add Attachment", variant: "ghost", className: "size-7 rounded-full p-1", ...props, children: /* @__PURE__ */ jsx23(PlusIcon, { className: "size-4.5" }) });
|
|
1135
|
+
}
|
|
1136
|
+
|
|
1137
|
+
// src/atoms/AttachmentPreviewDialog.tsx
|
|
1138
|
+
import { Fragment as Fragment2, jsx as jsx24, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
1139
|
+
function AttachmentPreviewDialog({ previewSrc, children }) {
|
|
1140
|
+
if (!previewSrc) return /* @__PURE__ */ jsx24(Fragment2, { children });
|
|
1141
|
+
return /* @__PURE__ */ jsxs14(Dialog, { children: [
|
|
1142
|
+
/* @__PURE__ */ jsx24(DialogTrigger, { asChild: true, children }),
|
|
1143
|
+
/* @__PURE__ */ jsxs14(DialogContent, { className: "p-2 sm:max-w-3xl", children: [
|
|
1144
|
+
/* @__PURE__ */ jsx24(DialogTitle, { className: "sr-only", children: "Image Attachment Preview" }),
|
|
1145
|
+
/* @__PURE__ */ jsx24("div", { className: "bg-background relative mx-auto flex max-h-[80dvh] w-full items-center justify-center overflow-hidden", children: /* @__PURE__ */ jsx24(
|
|
1146
|
+
"img",
|
|
1147
|
+
{
|
|
1148
|
+
src: previewSrc,
|
|
1149
|
+
alt: "Attachment preview",
|
|
1150
|
+
className: "block h-auto max-h-[80vh] w-auto max-w-full object-contain"
|
|
1151
|
+
}
|
|
1152
|
+
) })
|
|
1153
|
+
] })
|
|
1154
|
+
] });
|
|
1155
|
+
}
|
|
1156
|
+
|
|
1157
|
+
// src/atoms/ComposerShell.tsx
|
|
1158
|
+
import { ArrowUpIcon, LoaderIcon as LoaderIcon2, PlusIcon as PlusIcon2 } from "lucide-react";
|
|
1159
|
+
import { jsx as jsx25, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
1160
|
+
function ComposerShell({
|
|
1161
|
+
value,
|
|
1162
|
+
placeholder,
|
|
1163
|
+
disabled,
|
|
1164
|
+
isRunning = false,
|
|
1165
|
+
attachments,
|
|
1166
|
+
modelLabel,
|
|
1167
|
+
modelIcon,
|
|
1168
|
+
connectorStatusLabel,
|
|
1169
|
+
onValueChange,
|
|
1170
|
+
onSubmit,
|
|
1171
|
+
onCancel,
|
|
1172
|
+
onAttach,
|
|
1173
|
+
className
|
|
1174
|
+
}) {
|
|
1175
|
+
return /* @__PURE__ */ jsxs15(
|
|
1176
|
+
"div",
|
|
1177
|
+
{
|
|
1178
|
+
"data-slot": "aui_composer-shell",
|
|
1179
|
+
className: cn(
|
|
1180
|
+
"border-border/60 focus-within:border-ring focus-within:ring-ring/20 flex w-full flex-col gap-2 rounded-[var(--composer-radius,1.5rem)] border bg-[var(--composer-bg,var(--muted))] p-[var(--composer-padding,8px)] shadow-sm transition-colors focus-within:ring-3",
|
|
1181
|
+
className
|
|
1182
|
+
),
|
|
1183
|
+
children: [
|
|
1184
|
+
attachments,
|
|
1185
|
+
/* @__PURE__ */ jsx25(
|
|
1186
|
+
"textarea",
|
|
1187
|
+
{
|
|
1188
|
+
value,
|
|
1189
|
+
placeholder,
|
|
1190
|
+
disabled,
|
|
1191
|
+
rows: 1,
|
|
1192
|
+
"aria-label": "Message input",
|
|
1193
|
+
onChange: (event) => onValueChange(event.target.value),
|
|
1194
|
+
onKeyDown: (event) => {
|
|
1195
|
+
if (event.key === "Enter" && !event.shiftKey) {
|
|
1196
|
+
event.preventDefault();
|
|
1197
|
+
onSubmit();
|
|
1198
|
+
}
|
|
1199
|
+
},
|
|
1200
|
+
className: "placeholder:text-muted-foreground/80 max-h-32 min-h-10 w-full resize-none rounded-lg bg-transparent px-2.5 py-1 text-base outline-none"
|
|
1201
|
+
}
|
|
1202
|
+
),
|
|
1203
|
+
/* @__PURE__ */ jsxs15("div", { className: "flex items-center justify-between px-1", children: [
|
|
1204
|
+
/* @__PURE__ */ jsxs15("div", { className: "flex items-center gap-2", children: [
|
|
1205
|
+
onAttach && /* @__PURE__ */ jsx25(IconButton, { tooltip: "Attach", onClick: onAttach, children: /* @__PURE__ */ jsx25(PlusIcon2, {}) }),
|
|
1206
|
+
connectorStatusLabel && /* @__PURE__ */ jsx25("span", { className: "text-muted-foreground text-xs", children: connectorStatusLabel })
|
|
1207
|
+
] }),
|
|
1208
|
+
/* @__PURE__ */ jsxs15("div", { className: "flex items-center gap-2", children: [
|
|
1209
|
+
modelLabel && /* @__PURE__ */ jsxs15("span", { className: "bg-muted text-muted-foreground flex items-center gap-1 rounded-full px-2 py-0.5 text-xs", children: [
|
|
1210
|
+
modelIcon,
|
|
1211
|
+
modelLabel
|
|
1212
|
+
] }),
|
|
1213
|
+
isRunning ? /* @__PURE__ */ jsxs15(
|
|
1214
|
+
Button,
|
|
1215
|
+
{
|
|
1216
|
+
variant: "default",
|
|
1217
|
+
size: "sm",
|
|
1218
|
+
className: "gap-1.5 rounded-full",
|
|
1219
|
+
disabled: !onCancel,
|
|
1220
|
+
onClick: onCancel,
|
|
1221
|
+
children: [
|
|
1222
|
+
/* @__PURE__ */ jsx25(LoaderIcon2, { className: "size-3.5 animate-spin [animation-duration:0.6s]" }),
|
|
1223
|
+
"Cancel"
|
|
1224
|
+
]
|
|
1225
|
+
}
|
|
1226
|
+
) : /* @__PURE__ */ jsx25(
|
|
1227
|
+
IconButton,
|
|
1228
|
+
{
|
|
1229
|
+
tooltip: "Send message",
|
|
1230
|
+
variant: "default",
|
|
1231
|
+
disabled: disabled || value.trim().length === 0,
|
|
1232
|
+
onClick: onSubmit,
|
|
1233
|
+
children: /* @__PURE__ */ jsx25(ArrowUpIcon, {})
|
|
1234
|
+
}
|
|
1235
|
+
)
|
|
1236
|
+
] })
|
|
1237
|
+
] })
|
|
1238
|
+
]
|
|
1239
|
+
}
|
|
1240
|
+
);
|
|
1241
|
+
}
|
|
1242
|
+
|
|
1243
|
+
// src/atoms/McpAuthPrompt.tsx
|
|
1244
|
+
import { ExternalLinkIcon } from "lucide-react";
|
|
1245
|
+
import { jsx as jsx26, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
1246
|
+
function McpAuthPrompt({ servers, disabled, onContinue, className }) {
|
|
1247
|
+
return /* @__PURE__ */ jsxs16("div", { "data-slot": "aui_mcp-auth-continue-composer", className: cn("flex w-full flex-col gap-3", className), children: [
|
|
1248
|
+
/* @__PURE__ */ jsxs16("div", { className: "border-primary/20 bg-background overflow-hidden rounded-2xl border", children: [
|
|
1249
|
+
/* @__PURE__ */ jsx26("div", { className: "bg-primary/10 border-primary/20 border-b px-4 py-2.5", children: /* @__PURE__ */ jsx26("p", { className: "text-primary text-sm font-semibold", children: "MCP Authentication Required" }) }),
|
|
1250
|
+
/* @__PURE__ */ jsx26("ul", { className: "divide-border/60 divide-y", children: servers.map((server) => /* @__PURE__ */ jsxs16(
|
|
1251
|
+
"li",
|
|
1252
|
+
{
|
|
1253
|
+
className: "flex items-center justify-between gap-3 px-4 py-2.5",
|
|
1254
|
+
children: [
|
|
1255
|
+
/* @__PURE__ */ jsxs16("p", { className: "text-sm", children: [
|
|
1256
|
+
/* @__PURE__ */ jsx26("span", { className: "text-muted-foreground", children: "MCP Server Name" }),
|
|
1257
|
+
/* @__PURE__ */ jsx26("span", { className: "text-muted-foreground mx-1.5", children: ":" }),
|
|
1258
|
+
/* @__PURE__ */ jsx26("span", { className: "font-semibold", children: server.name })
|
|
1259
|
+
] }),
|
|
1260
|
+
/* @__PURE__ */ jsx26(
|
|
1261
|
+
Button,
|
|
1262
|
+
{
|
|
1263
|
+
asChild: true,
|
|
1264
|
+
size: "sm",
|
|
1265
|
+
className: "bg-foreground text-background hover:bg-foreground/80 rounded-full",
|
|
1266
|
+
children: /* @__PURE__ */ jsxs16("a", { href: server.authUrl, target: "_blank", rel: "noopener noreferrer", children: [
|
|
1267
|
+
"Connect",
|
|
1268
|
+
/* @__PURE__ */ jsx26(ExternalLinkIcon, { className: "size-3.5" })
|
|
1269
|
+
] })
|
|
1270
|
+
}
|
|
1271
|
+
)
|
|
1272
|
+
]
|
|
1273
|
+
},
|
|
1274
|
+
server.id
|
|
1275
|
+
)) })
|
|
1276
|
+
] }),
|
|
1277
|
+
/* @__PURE__ */ jsx26("div", { className: "flex justify-end px-2.5", children: /* @__PURE__ */ jsx26(Button, { type: "button", className: "rounded-full px-4", disabled, onClick: onContinue, children: "Continue" }) })
|
|
1278
|
+
] });
|
|
1279
|
+
}
|
|
1280
|
+
|
|
1281
|
+
// src/atoms/ReasoningCard.tsx
|
|
1282
|
+
import { BrainIcon, ChevronDownIcon } from "lucide-react";
|
|
1283
|
+
import { jsx as jsx27, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
1284
|
+
function ReasoningCard({ streaming, expanded, onToggle, children, className }) {
|
|
1285
|
+
return /* @__PURE__ */ jsxs17(
|
|
1286
|
+
Collapsible,
|
|
1287
|
+
{
|
|
1288
|
+
"data-slot": "reasoning-card",
|
|
1289
|
+
open: expanded,
|
|
1290
|
+
onOpenChange: onToggle,
|
|
1291
|
+
className: cn("aui-reasoning-card w-full rounded-lg border px-3 py-2", className),
|
|
1292
|
+
children: [
|
|
1293
|
+
/* @__PURE__ */ jsxs17(CollapsibleTrigger, { className: "text-muted-foreground hover:text-foreground flex max-w-[75%] origin-left items-center gap-2 py-1.5 text-sm transition-[color,scale] active:scale-[0.98]", children: [
|
|
1294
|
+
/* @__PURE__ */ jsx27(BrainIcon, { className: "size-4 shrink-0" }),
|
|
1295
|
+
/* @__PURE__ */ jsxs17("span", { className: "leading-none tabular-nums", children: [
|
|
1296
|
+
"Reasoning",
|
|
1297
|
+
streaming && /* @__PURE__ */ jsxs17("span", { "aria-hidden": true, className: "shimmer pointer-events-none", children: [
|
|
1298
|
+
" ",
|
|
1299
|
+
"\u2026"
|
|
1300
|
+
] })
|
|
1301
|
+
] }),
|
|
1302
|
+
/* @__PURE__ */ jsx27(
|
|
1303
|
+
ChevronDownIcon,
|
|
1304
|
+
{
|
|
1305
|
+
className: cn(
|
|
1306
|
+
"mt-0.5 size-4 shrink-0 transition-transform duration-200 ease-[cubic-bezier(0.32,0.72,0,1)]",
|
|
1307
|
+
expanded ? "rotate-0" : "-rotate-90"
|
|
1308
|
+
)
|
|
1309
|
+
}
|
|
1310
|
+
)
|
|
1311
|
+
] }),
|
|
1312
|
+
/* @__PURE__ */ jsx27(CollapsibleContent, { className: "text-muted-foreground max-h-64 overflow-y-auto pt-2 pb-1 pl-6 text-sm leading-relaxed", children })
|
|
1313
|
+
]
|
|
1314
|
+
}
|
|
1315
|
+
);
|
|
1316
|
+
}
|
|
1317
|
+
|
|
1318
|
+
// src/atoms/ToolApprovalBar.tsx
|
|
1319
|
+
import { useState as useState3 } from "react";
|
|
1320
|
+
import { jsx as jsx28, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
1321
|
+
function ToolApprovalBar({ options, onSelectOption, className }) {
|
|
1322
|
+
const [confirmingId, setConfirmingId] = useState3(null);
|
|
1323
|
+
const confirming = confirmingId != null ? options.find((o) => o.id === confirmingId) : void 0;
|
|
1324
|
+
if (confirming) {
|
|
1325
|
+
return /* @__PURE__ */ jsxs18("div", { className: cn("aui-tool-approval-confirm flex flex-col gap-2 pt-1", className), children: [
|
|
1326
|
+
/* @__PURE__ */ jsx28("p", { className: "font-semibold", children: confirming.confirm?.title ?? `${confirming.label}?` }),
|
|
1327
|
+
confirming.confirm?.description && /* @__PURE__ */ jsx28("p", { className: "text-muted-foreground", children: confirming.confirm.description }),
|
|
1328
|
+
confirming.grants && confirming.grants.length > 0 && /* @__PURE__ */ jsx28("ul", { className: "flex flex-col gap-1", children: confirming.grants.map((grant) => /* @__PURE__ */ jsx28("li", { children: /* @__PURE__ */ jsx28("code", { className: "bg-muted rounded px-1.5 py-0.5 text-xs", children: grant }) }, grant)) }),
|
|
1329
|
+
/* @__PURE__ */ jsxs18("div", { className: "flex items-center gap-2", children: [
|
|
1330
|
+
/* @__PURE__ */ jsx28(
|
|
1331
|
+
Button,
|
|
1332
|
+
{
|
|
1333
|
+
size: "sm",
|
|
1334
|
+
className: "active:scale-[0.98]",
|
|
1335
|
+
onClick: () => {
|
|
1336
|
+
onSelectOption(confirming.id);
|
|
1337
|
+
setConfirmingId(null);
|
|
1338
|
+
},
|
|
1339
|
+
children: "Confirm"
|
|
1340
|
+
}
|
|
1341
|
+
),
|
|
1342
|
+
/* @__PURE__ */ jsx28(
|
|
1343
|
+
Button,
|
|
1344
|
+
{
|
|
1345
|
+
size: "sm",
|
|
1346
|
+
variant: "outline",
|
|
1347
|
+
className: "active:scale-[0.98]",
|
|
1348
|
+
onClick: () => setConfirmingId(null),
|
|
1349
|
+
children: "Back"
|
|
1350
|
+
}
|
|
1351
|
+
)
|
|
1352
|
+
] })
|
|
1353
|
+
] });
|
|
1354
|
+
}
|
|
1355
|
+
const firstAllowId = options.find((o) => o.isAllow)?.id;
|
|
1356
|
+
return /* @__PURE__ */ jsx28("div", { className: cn("aui-tool-approval-bar flex flex-wrap items-center gap-2 pt-1", className), children: options.map((option) => /* @__PURE__ */ jsx28(
|
|
1357
|
+
Button,
|
|
1358
|
+
{
|
|
1359
|
+
size: "sm",
|
|
1360
|
+
variant: option.id === firstAllowId ? "default" : "outline",
|
|
1361
|
+
className: "active:scale-[0.98]",
|
|
1362
|
+
onClick: () => option.confirm ? setConfirmingId(option.id) : onSelectOption(option.id),
|
|
1363
|
+
children: option.label
|
|
1364
|
+
},
|
|
1365
|
+
option.id
|
|
1366
|
+
)) });
|
|
1367
|
+
}
|
|
1368
|
+
|
|
1369
|
+
// src/atoms/ThreadListRow.tsx
|
|
1370
|
+
import { ArchiveIcon, MoreHorizontalIcon as MoreHorizontalIcon2, TrashIcon } from "lucide-react";
|
|
1371
|
+
import { DropdownMenu as DropdownMenu2 } from "radix-ui";
|
|
1372
|
+
import { jsx as jsx29, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
1373
|
+
function ThreadListRow({ title, active, onSelect, onArchive, onDelete, className }) {
|
|
1374
|
+
return /* @__PURE__ */ jsxs19(
|
|
1375
|
+
"div",
|
|
1376
|
+
{
|
|
1377
|
+
"data-slot": "aui_thread-list-item",
|
|
1378
|
+
"data-active": active || void 0,
|
|
1379
|
+
className: cn(
|
|
1380
|
+
"group hover:bg-muted data-[active]:bg-muted relative flex min-h-9 items-center rounded-lg transition-colors",
|
|
1381
|
+
className
|
|
1382
|
+
),
|
|
1383
|
+
children: [
|
|
1384
|
+
/* @__PURE__ */ jsx29(
|
|
1385
|
+
"button",
|
|
1386
|
+
{
|
|
1387
|
+
type: "button",
|
|
1388
|
+
onClick: onSelect,
|
|
1389
|
+
"data-slot": "aui_thread-list-item-trigger",
|
|
1390
|
+
className: "flex min-h-9 min-w-0 flex-1 items-center rounded-lg px-2.5 py-2 text-start text-sm outline-none group-hover:pe-9",
|
|
1391
|
+
children: /* @__PURE__ */ jsx29("span", { className: "min-w-0 flex-1 truncate", children: title })
|
|
1392
|
+
}
|
|
1393
|
+
),
|
|
1394
|
+
(onArchive || onDelete) && /* @__PURE__ */ jsxs19(DropdownMenu2.Root, { children: [
|
|
1395
|
+
/* @__PURE__ */ jsx29(DropdownMenu2.Trigger, { asChild: true, children: /* @__PURE__ */ jsx29(
|
|
1396
|
+
IconButton,
|
|
1397
|
+
{
|
|
1398
|
+
tooltip: "More options",
|
|
1399
|
+
className: "absolute end-1.5 top-1/2 size-6 -translate-y-1/2 p-0 opacity-0 group-hover:opacity-100 data-[state=open]:opacity-100",
|
|
1400
|
+
children: /* @__PURE__ */ jsx29(MoreHorizontalIcon2, { className: "size-3.5" })
|
|
1401
|
+
}
|
|
1402
|
+
) }),
|
|
1403
|
+
/* @__PURE__ */ jsx29(DropdownMenu2.Portal, { children: /* @__PURE__ */ jsxs19(
|
|
1404
|
+
DropdownMenu2.Content,
|
|
1405
|
+
{
|
|
1406
|
+
side: "right",
|
|
1407
|
+
align: "start",
|
|
1408
|
+
sideOffset: 6,
|
|
1409
|
+
className: "bg-popover/95 text-popover-foreground z-50 min-w-32 overflow-hidden rounded-xl border p-1.5 shadow-lg backdrop-blur-sm",
|
|
1410
|
+
children: [
|
|
1411
|
+
onArchive && /* @__PURE__ */ jsxs19(
|
|
1412
|
+
DropdownMenu2.Item,
|
|
1413
|
+
{
|
|
1414
|
+
onSelect: onArchive,
|
|
1415
|
+
className: "hover:bg-accent hover:text-accent-foreground flex cursor-pointer items-center gap-2 rounded-lg px-2.5 py-1.5 text-sm outline-none select-none",
|
|
1416
|
+
children: [
|
|
1417
|
+
/* @__PURE__ */ jsx29(ArchiveIcon, { className: "size-4" }),
|
|
1418
|
+
"Archive"
|
|
1419
|
+
]
|
|
1420
|
+
}
|
|
1421
|
+
),
|
|
1422
|
+
onDelete && /* @__PURE__ */ jsxs19(
|
|
1423
|
+
DropdownMenu2.Item,
|
|
1424
|
+
{
|
|
1425
|
+
onSelect: onDelete,
|
|
1426
|
+
className: "text-destructive hover:bg-destructive/10 flex cursor-pointer items-center gap-2 rounded-lg px-2.5 py-1.5 text-sm outline-none select-none",
|
|
1427
|
+
children: [
|
|
1428
|
+
/* @__PURE__ */ jsx29(TrashIcon, { className: "size-4" }),
|
|
1429
|
+
"Delete"
|
|
1430
|
+
]
|
|
1431
|
+
}
|
|
1432
|
+
)
|
|
1433
|
+
]
|
|
1434
|
+
}
|
|
1435
|
+
) })
|
|
1436
|
+
] })
|
|
1437
|
+
]
|
|
1438
|
+
}
|
|
1439
|
+
);
|
|
1440
|
+
}
|
|
1441
|
+
|
|
1442
|
+
// src/atoms/ThreadListMisc.tsx
|
|
1443
|
+
import { PlusIcon as PlusIcon3 } from "lucide-react";
|
|
1444
|
+
import { jsx as jsx30, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
1445
|
+
function ThreadListNewButton({ className, ...rest }) {
|
|
1446
|
+
return /* @__PURE__ */ jsxs20(
|
|
1447
|
+
Button,
|
|
1448
|
+
{
|
|
1449
|
+
variant: "ghost",
|
|
1450
|
+
"data-slot": "aui_thread-list-new",
|
|
1451
|
+
className: cn("hover:bg-muted h-8 justify-start gap-2 rounded-md px-2.5 text-sm font-normal", className),
|
|
1452
|
+
...rest,
|
|
1453
|
+
children: [
|
|
1454
|
+
/* @__PURE__ */ jsx30(PlusIcon3, { className: "size-4 shrink-0" }),
|
|
1455
|
+
/* @__PURE__ */ jsx30("span", { className: "whitespace-nowrap", children: "New Thread" })
|
|
1456
|
+
]
|
|
1457
|
+
}
|
|
1458
|
+
);
|
|
1459
|
+
}
|
|
1460
|
+
function ThreadListRowSkeleton({ count = 5, className }) {
|
|
1461
|
+
return /* @__PURE__ */ jsx30("div", { className: cn("flex flex-col gap-1", className), role: "status", "aria-label": "Loading threads", children: Array.from({ length: count }, (_, i) => /* @__PURE__ */ jsx30("div", { className: "flex h-8 items-center px-2.5", children: /* @__PURE__ */ jsx30(Skeleton, { className: "h-3.5 w-full" }) }, i)) });
|
|
1462
|
+
}
|
|
1463
|
+
function ThreadListEmptyState({ message = "No threads yet", className }) {
|
|
1464
|
+
return /* @__PURE__ */ jsx30("div", { className: cn("text-muted-foreground flex flex-1 items-center justify-center px-4 text-center text-sm", className), children: message });
|
|
1465
|
+
}
|
|
1466
|
+
function ThreadListShell({ header, children, className }) {
|
|
1467
|
+
return /* @__PURE__ */ jsxs20("div", { className: cn("flex min-h-0 flex-1 flex-col gap-1 overflow-hidden p-3", className), children: [
|
|
1468
|
+
header,
|
|
1469
|
+
/* @__PURE__ */ jsx30("div", { className: "flex min-h-0 flex-1 flex-col gap-3 overflow-y-auto pb-1", children })
|
|
1470
|
+
] });
|
|
1471
|
+
}
|
|
1472
|
+
|
|
1473
|
+
// src/atoms/Toast.tsx
|
|
1474
|
+
import { XIcon as XIcon3 } from "lucide-react";
|
|
1475
|
+
import { Toast as ToastPrimitive } from "radix-ui";
|
|
1476
|
+
import { jsx as jsx31, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
1477
|
+
function Toast({ title, description, open, onOpenChange, className }) {
|
|
1478
|
+
return /* @__PURE__ */ jsxs21(
|
|
1479
|
+
ToastPrimitive.Root,
|
|
1480
|
+
{
|
|
1481
|
+
open,
|
|
1482
|
+
onOpenChange,
|
|
1483
|
+
className: cn(
|
|
1484
|
+
"border-destructive bg-background text-destructive dark:bg-card pointer-events-auto relative flex max-h-[min(70vh,32rem)] w-full items-start gap-3 rounded-xl border p-4 shadow-lg dark:text-red-200",
|
|
1485
|
+
"data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:slide-in-from-bottom-4",
|
|
1486
|
+
"data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:slide-out-to-bottom-4",
|
|
1487
|
+
className
|
|
1488
|
+
),
|
|
1489
|
+
children: [
|
|
1490
|
+
/* @__PURE__ */ jsxs21("div", { className: "grid min-h-0 min-w-0 flex-1 gap-1 overflow-y-auto pe-6", children: [
|
|
1491
|
+
/* @__PURE__ */ jsx31(ToastPrimitive.Title, { className: "text-sm leading-none font-semibold", children: title }),
|
|
1492
|
+
/* @__PURE__ */ jsx31(ToastPrimitive.Description, { className: "font-mono text-sm break-words whitespace-pre-wrap", children: description })
|
|
1493
|
+
] }),
|
|
1494
|
+
/* @__PURE__ */ jsxs21(ToastPrimitive.Close, { className: "text-destructive hover:bg-muted focus-visible:ring-ring absolute top-3 right-3 rounded-md p-1 transition-colors focus:outline-none focus-visible:ring-2", children: [
|
|
1495
|
+
/* @__PURE__ */ jsx31(XIcon3, { className: "size-4" }),
|
|
1496
|
+
/* @__PURE__ */ jsx31("span", { className: "sr-only", children: "Close" })
|
|
1497
|
+
] })
|
|
1498
|
+
]
|
|
1499
|
+
}
|
|
1500
|
+
);
|
|
1501
|
+
}
|
|
1502
|
+
function ToastStack({ children, duration = Number.POSITIVE_INFINITY }) {
|
|
1503
|
+
return /* @__PURE__ */ jsxs21(ToastPrimitive.Provider, { duration, children: [
|
|
1504
|
+
children,
|
|
1505
|
+
/* @__PURE__ */ jsx31(ToastPrimitive.Viewport, { className: "fixed inset-x-0 bottom-0 z-50 flex max-h-screen flex-col-reverse gap-2 p-4 sm:bottom-4 sm:left-1/2 sm:w-full sm:max-w-2xl sm:-translate-x-1/2" })
|
|
1506
|
+
] });
|
|
1507
|
+
}
|
|
1508
|
+
|
|
1509
|
+
// src/atoms/ToolCallCard.tsx
|
|
1510
|
+
import { BriefcaseIcon, CheckIcon as CheckIcon4, ChevronDownIcon as ChevronDownIcon2, LoaderIcon as LoaderIcon3, PlugIcon, WrenchIcon, XCircleIcon } from "lucide-react";
|
|
1511
|
+
import { jsx as jsx32, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
1512
|
+
var variantIcon = {
|
|
1513
|
+
tool: WrenchIcon,
|
|
1514
|
+
"sub-agent": BriefcaseIcon,
|
|
1515
|
+
"mcp-listing": PlugIcon
|
|
1516
|
+
};
|
|
1517
|
+
function StatusIcon({ status }) {
|
|
1518
|
+
if (status === "running") {
|
|
1519
|
+
return /* @__PURE__ */ jsx32(
|
|
1520
|
+
LoaderIcon3,
|
|
1521
|
+
{
|
|
1522
|
+
"data-slot": "tool-call-card-status-icon",
|
|
1523
|
+
className: "text-muted-foreground size-4 shrink-0 animate-spin [animation-duration:0.6s]"
|
|
1524
|
+
}
|
|
1525
|
+
);
|
|
1526
|
+
}
|
|
1527
|
+
if (status === "success") {
|
|
1528
|
+
return /* @__PURE__ */ jsx32(
|
|
1529
|
+
CheckIcon4,
|
|
1530
|
+
{
|
|
1531
|
+
"data-slot": "tool-call-card-status-icon",
|
|
1532
|
+
className: "size-4 shrink-0 text-emerald-600 dark:text-emerald-400"
|
|
1533
|
+
}
|
|
1534
|
+
);
|
|
1535
|
+
}
|
|
1536
|
+
return /* @__PURE__ */ jsx32(XCircleIcon, { "data-slot": "tool-call-card-status-icon", className: "text-destructive size-4 shrink-0" });
|
|
1537
|
+
}
|
|
1538
|
+
function IconChip({ Icon }) {
|
|
1539
|
+
return /* @__PURE__ */ jsx32("span", { className: "bg-muted text-muted-foreground flex size-6 shrink-0 items-center justify-center rounded-md", children: /* @__PURE__ */ jsx32(Icon, { className: "size-3.5" }) });
|
|
1540
|
+
}
|
|
1541
|
+
function ToolCallCard(props) {
|
|
1542
|
+
const { variant, name, status, expanded, onToggle, durationText, className } = props;
|
|
1543
|
+
const VariantIcon = variantIcon[variant];
|
|
1544
|
+
return /* @__PURE__ */ jsxs22(
|
|
1545
|
+
Collapsible,
|
|
1546
|
+
{
|
|
1547
|
+
"data-slot": "tool-call-card",
|
|
1548
|
+
"data-variant": variant,
|
|
1549
|
+
open: expanded,
|
|
1550
|
+
onOpenChange: onToggle,
|
|
1551
|
+
className: cn("aui-tool-call-card w-full rounded-lg border py-2", className),
|
|
1552
|
+
children: [
|
|
1553
|
+
/* @__PURE__ */ jsxs22(CollapsibleTrigger, { className: "flex w-full items-center gap-2 px-3 text-left", children: [
|
|
1554
|
+
/* @__PURE__ */ jsx32(IconChip, { Icon: VariantIcon }),
|
|
1555
|
+
variant === "tool" && /* @__PURE__ */ jsx32("span", { className: "text-sm", children: name }),
|
|
1556
|
+
variant === "sub-agent" && /* @__PURE__ */ jsxs22("span", { className: "flex min-w-0 flex-col items-start", children: [
|
|
1557
|
+
/* @__PURE__ */ jsx32("span", { className: "text-muted-foreground text-[10px] font-semibold tracking-wide uppercase", children: "Sub-agent" }),
|
|
1558
|
+
/* @__PURE__ */ jsx32("span", { className: "truncate text-sm font-medium", children: props.agentName })
|
|
1559
|
+
] }),
|
|
1560
|
+
variant === "mcp-listing" && /* @__PURE__ */ jsxs22("span", { className: "truncate text-sm", children: [
|
|
1561
|
+
"Listing tools \xB7 ",
|
|
1562
|
+
props.serverName
|
|
1563
|
+
] }),
|
|
1564
|
+
/* @__PURE__ */ jsxs22("span", { className: "ml-auto flex shrink-0 items-center gap-2", children: [
|
|
1565
|
+
durationText && /* @__PURE__ */ jsx32("span", { className: "text-muted-foreground text-xs tabular-nums", children: durationText }),
|
|
1566
|
+
/* @__PURE__ */ jsx32(StatusIcon, { status }),
|
|
1567
|
+
/* @__PURE__ */ jsx32(
|
|
1568
|
+
ChevronDownIcon2,
|
|
1569
|
+
{
|
|
1570
|
+
className: cn(
|
|
1571
|
+
"size-4 shrink-0 transition-transform duration-200 ease-[cubic-bezier(0.32,0.72,0,1)]",
|
|
1572
|
+
expanded ? "rotate-0" : "-rotate-90"
|
|
1573
|
+
)
|
|
1574
|
+
}
|
|
1575
|
+
)
|
|
1576
|
+
] })
|
|
1577
|
+
] }),
|
|
1578
|
+
/* @__PURE__ */ jsxs22(CollapsibleContent, { className: "px-3 pt-2", children: [
|
|
1579
|
+
variant === "tool" && /* @__PURE__ */ jsxs22("div", { className: "flex flex-col gap-2", children: [
|
|
1580
|
+
props.approvalSlot,
|
|
1581
|
+
props.argsText && /* @__PURE__ */ jsxs22("div", { children: [
|
|
1582
|
+
/* @__PURE__ */ jsx32("p", { className: "text-muted-foreground text-xs font-medium", children: "Request:" }),
|
|
1583
|
+
/* @__PURE__ */ jsx32("pre", { className: "bg-muted/50 text-foreground/90 mt-1 rounded-md p-2.5 text-xs break-words whitespace-pre-wrap", children: props.argsText })
|
|
1584
|
+
] }),
|
|
1585
|
+
props.result !== void 0 && /* @__PURE__ */ jsxs22("div", { children: [
|
|
1586
|
+
/* @__PURE__ */ jsx32("p", { className: "text-muted-foreground text-xs font-medium", children: "Result:" }),
|
|
1587
|
+
/* @__PURE__ */ jsx32(
|
|
1588
|
+
"pre",
|
|
1589
|
+
{
|
|
1590
|
+
className: cn(
|
|
1591
|
+
"bg-muted/50 mt-1 rounded-md p-2.5 text-xs break-words whitespace-pre-wrap",
|
|
1592
|
+
props.isError ? "text-destructive" : "text-foreground/90"
|
|
1593
|
+
),
|
|
1594
|
+
children: props.result
|
|
1595
|
+
}
|
|
1596
|
+
)
|
|
1597
|
+
] })
|
|
1598
|
+
] }),
|
|
1599
|
+
variant === "sub-agent" && /* @__PURE__ */ jsxs22("div", { className: "flex flex-col gap-2", children: [
|
|
1600
|
+
/* @__PURE__ */ jsx32("p", { className: "text-muted-foreground line-clamp-2 text-sm", children: props.instruction }),
|
|
1601
|
+
/* @__PURE__ */ jsxs22("p", { className: "text-muted-foreground text-[10px] font-medium tracking-wide uppercase", children: [
|
|
1602
|
+
"Steps \xB7 ",
|
|
1603
|
+
props.stepCount,
|
|
1604
|
+
" steps"
|
|
1605
|
+
] }),
|
|
1606
|
+
/* @__PURE__ */ jsx32("div", { className: "border-border/60 flex flex-col gap-2 border-l pl-3", children: props.children })
|
|
1607
|
+
] }),
|
|
1608
|
+
variant === "mcp-listing" && /* @__PURE__ */ jsxs22("div", { className: "flex flex-col gap-2", children: [
|
|
1609
|
+
/* @__PURE__ */ jsx32("p", { className: "text-muted-foreground text-sm", children: props.description }),
|
|
1610
|
+
/* @__PURE__ */ jsxs22("div", { children: [
|
|
1611
|
+
/* @__PURE__ */ jsx32("p", { className: "text-muted-foreground text-xs font-medium", children: "Request:" }),
|
|
1612
|
+
/* @__PURE__ */ jsx32("pre", { className: "bg-muted/50 text-foreground/90 mt-1 rounded-md p-2.5 text-xs break-words whitespace-pre-wrap", children: props.argsText })
|
|
1613
|
+
] }),
|
|
1614
|
+
/* @__PURE__ */ jsxs22("div", { children: [
|
|
1615
|
+
/* @__PURE__ */ jsx32("p", { className: "text-muted-foreground text-xs font-medium", children: "Result:" }),
|
|
1616
|
+
/* @__PURE__ */ jsx32("pre", { className: "bg-muted/50 text-foreground/90 mt-1 rounded-md p-2.5 text-xs break-words whitespace-pre-wrap", children: props.resultText })
|
|
1617
|
+
] })
|
|
1618
|
+
] })
|
|
1619
|
+
] })
|
|
1620
|
+
]
|
|
1621
|
+
}
|
|
1622
|
+
);
|
|
1623
|
+
}
|
|
1624
|
+
|
|
1625
|
+
// src/atoms/ToolGroupCard.tsx
|
|
1626
|
+
import { ChevronDownIcon as ChevronDownIcon3, LoaderIcon as LoaderIcon4 } from "lucide-react";
|
|
1627
|
+
import { jsx as jsx33, jsxs as jsxs23 } from "react/jsx-runtime";
|
|
1628
|
+
function ToolGroupCard({
|
|
1629
|
+
toolCallCount,
|
|
1630
|
+
expanded,
|
|
1631
|
+
active = false,
|
|
1632
|
+
onToggle,
|
|
1633
|
+
children,
|
|
1634
|
+
className
|
|
1635
|
+
}) {
|
|
1636
|
+
const label = `${toolCallCount} tool ${toolCallCount === 1 ? "call" : "calls"}`;
|
|
1637
|
+
return /* @__PURE__ */ jsxs23(
|
|
1638
|
+
Collapsible,
|
|
1639
|
+
{
|
|
1640
|
+
"data-slot": "tool-group-card",
|
|
1641
|
+
open: expanded,
|
|
1642
|
+
onOpenChange: onToggle,
|
|
1643
|
+
className: cn("aui-tool-group-card group/tool-group w-full", className),
|
|
1644
|
+
children: [
|
|
1645
|
+
/* @__PURE__ */ jsxs23(CollapsibleTrigger, { className: "text-muted-foreground hover:text-foreground flex origin-left items-center gap-2 py-1.5 text-sm transition-[color,scale] active:scale-[0.98]", children: [
|
|
1646
|
+
active && /* @__PURE__ */ jsx33(LoaderIcon4, { className: "size-3 shrink-0 animate-spin [animation-duration:0.6s]" }),
|
|
1647
|
+
/* @__PURE__ */ jsx33("span", { className: "text-xs font-medium", children: label }),
|
|
1648
|
+
/* @__PURE__ */ jsx33(
|
|
1649
|
+
ChevronDownIcon3,
|
|
1650
|
+
{
|
|
1651
|
+
className: cn(
|
|
1652
|
+
"size-3 shrink-0 transition-transform duration-200 ease-[cubic-bezier(0.32,0.72,0,1)]",
|
|
1653
|
+
expanded ? "rotate-0" : "-rotate-90"
|
|
1654
|
+
)
|
|
1655
|
+
}
|
|
1656
|
+
)
|
|
1657
|
+
] }),
|
|
1658
|
+
/* @__PURE__ */ jsx33(CollapsibleContent, { className: "mt-1 flex flex-col gap-1", children })
|
|
1659
|
+
]
|
|
1660
|
+
}
|
|
1661
|
+
);
|
|
1662
|
+
}
|
|
1663
|
+
|
|
1664
|
+
// src/atoms/WelcomeScreen.tsx
|
|
1665
|
+
import { jsx as jsx34 } from "react/jsx-runtime";
|
|
1666
|
+
function WelcomeScreen({ heading = "How can I help you today?", className }) {
|
|
1667
|
+
return /* @__PURE__ */ jsx34("div", { className: cn("aui-thread-welcome-root mb-6 flex flex-col items-center px-4 text-center", className), children: /* @__PURE__ */ jsx34("h1", { className: "aui-thread-welcome-message-inner fade-in slide-in-from-bottom-1 animate-in fill-mode-both text-2xl font-semibold duration-200", children: heading }) });
|
|
1668
|
+
}
|
|
1669
|
+
|
|
1670
|
+
// src/theme/defaultSlots.ts
|
|
1671
|
+
var defaultSlots = {
|
|
1672
|
+
Button,
|
|
1673
|
+
IconButton,
|
|
1674
|
+
Avatar,
|
|
1675
|
+
AvatarImage,
|
|
1676
|
+
AvatarFallback,
|
|
1677
|
+
Tooltip,
|
|
1678
|
+
TooltipProvider,
|
|
1679
|
+
TooltipTrigger,
|
|
1680
|
+
TooltipContent,
|
|
1681
|
+
Dialog,
|
|
1682
|
+
DialogTrigger,
|
|
1683
|
+
DialogPortal,
|
|
1684
|
+
DialogClose,
|
|
1685
|
+
DialogOverlay,
|
|
1686
|
+
DialogContent,
|
|
1687
|
+
DialogHeader,
|
|
1688
|
+
DialogFooter,
|
|
1689
|
+
DialogTitle,
|
|
1690
|
+
DialogDescription,
|
|
1691
|
+
Collapsible,
|
|
1692
|
+
CollapsibleTrigger,
|
|
1693
|
+
CollapsibleContent,
|
|
1694
|
+
Skeleton,
|
|
1695
|
+
Markdown,
|
|
1696
|
+
OpenUIBlock,
|
|
1697
|
+
SandboxArtifactList,
|
|
1698
|
+
CodeBlockHeader,
|
|
1699
|
+
MessageBubble,
|
|
1700
|
+
MessageErrorBanner,
|
|
1701
|
+
MessageActionBar,
|
|
1702
|
+
UserMessageActionBar,
|
|
1703
|
+
BranchIndicator,
|
|
1704
|
+
MessageIndicator,
|
|
1705
|
+
WelcomeScreen,
|
|
1706
|
+
MessageListSkeleton,
|
|
1707
|
+
ScrollToBottomButton,
|
|
1708
|
+
ThreadRootShell,
|
|
1709
|
+
ThreadViewportShell,
|
|
1710
|
+
ThreadComposerAreaShell,
|
|
1711
|
+
MessageGroup,
|
|
1712
|
+
ToolCallCard,
|
|
1713
|
+
ToolApprovalBar,
|
|
1714
|
+
ToolGroupCard,
|
|
1715
|
+
ReasoningCard,
|
|
1716
|
+
ComposerShell,
|
|
1717
|
+
AskUserPrompt,
|
|
1718
|
+
McpAuthPrompt,
|
|
1719
|
+
AttachmentCard,
|
|
1720
|
+
AttachmentPreviewDialog,
|
|
1721
|
+
AttachmentPickerButton,
|
|
1722
|
+
ThreadListRow,
|
|
1723
|
+
ThreadListNewButton,
|
|
1724
|
+
ThreadListRowSkeleton,
|
|
1725
|
+
ThreadListEmptyState,
|
|
1726
|
+
ThreadListShell,
|
|
1727
|
+
Toast,
|
|
1728
|
+
ToastStack
|
|
1729
|
+
};
|
|
1730
|
+
|
|
1731
|
+
// src/theme/SlotsProvider.tsx
|
|
1732
|
+
import { jsx as jsx35 } from "react/jsx-runtime";
|
|
1733
|
+
var SlotsContext = createContext(defaultSlots);
|
|
1734
|
+
function SlotsProvider({
|
|
1735
|
+
overrides,
|
|
1736
|
+
children
|
|
1737
|
+
}) {
|
|
1738
|
+
const parentSlots = useContext(SlotsContext);
|
|
1739
|
+
const resolved = useMemo2(
|
|
1740
|
+
() => ({ ...parentSlots, ...overrides }),
|
|
1741
|
+
[parentSlots, overrides]
|
|
1742
|
+
);
|
|
1743
|
+
return /* @__PURE__ */ jsx35(SlotsContext.Provider, { value: resolved, children });
|
|
1744
|
+
}
|
|
1745
|
+
function useSlot(name) {
|
|
1746
|
+
const slots = useContext(SlotsContext);
|
|
1747
|
+
return slots[name];
|
|
1748
|
+
}
|
|
1749
|
+
|
|
1750
|
+
// src/theme/tokens.ts
|
|
1751
|
+
import { createContext as createContext2, createElement, useContext as useContext2 } from "react";
|
|
1752
|
+
var defaultTokens = {
|
|
1753
|
+
colors: {
|
|
1754
|
+
background: "var(--background)",
|
|
1755
|
+
foreground: "var(--foreground)",
|
|
1756
|
+
muted: "var(--muted)",
|
|
1757
|
+
mutedForeground: "var(--muted-foreground)",
|
|
1758
|
+
border: "var(--border)",
|
|
1759
|
+
primary: "var(--primary)",
|
|
1760
|
+
primaryForeground: "var(--primary-foreground)",
|
|
1761
|
+
destructive: "var(--destructive)",
|
|
1762
|
+
destructiveForeground: "var(--destructive-foreground)",
|
|
1763
|
+
accent: "var(--accent)",
|
|
1764
|
+
accentForeground: "var(--accent-foreground)"
|
|
1765
|
+
},
|
|
1766
|
+
radii: {
|
|
1767
|
+
none: "0px",
|
|
1768
|
+
sm: "calc(var(--radius) - 4px)",
|
|
1769
|
+
md: "calc(var(--radius) - 2px)",
|
|
1770
|
+
lg: "var(--radius)",
|
|
1771
|
+
full: "9999px"
|
|
1772
|
+
},
|
|
1773
|
+
spacing: {
|
|
1774
|
+
none: "0px",
|
|
1775
|
+
xs: "0.25rem",
|
|
1776
|
+
sm: "0.5rem",
|
|
1777
|
+
md: "0.75rem",
|
|
1778
|
+
lg: "1rem",
|
|
1779
|
+
xl: "1.5rem"
|
|
1780
|
+
},
|
|
1781
|
+
typography: {
|
|
1782
|
+
body: { fontSize: "0.875rem", lineHeight: "1.5rem", fontWeight: 400 },
|
|
1783
|
+
bodySmall: { fontSize: "0.75rem", lineHeight: "1.25rem", fontWeight: 400 },
|
|
1784
|
+
label: { fontSize: "0.75rem", lineHeight: "1rem", fontWeight: 500 },
|
|
1785
|
+
heading: { fontSize: "1.25rem", lineHeight: "1.75rem", fontWeight: 600 },
|
|
1786
|
+
code: { fontSize: "0.8125rem", lineHeight: "1.25rem", fontWeight: 400 },
|
|
1787
|
+
caption: { fontSize: "0.6875rem", lineHeight: "1rem", fontWeight: 400 }
|
|
1788
|
+
}
|
|
1789
|
+
};
|
|
1790
|
+
var TokensContext = createContext2(defaultTokens);
|
|
1791
|
+
function TokensProvider({
|
|
1792
|
+
tokens,
|
|
1793
|
+
children
|
|
1794
|
+
}) {
|
|
1795
|
+
return createElement(TokensContext.Provider, { value: tokens }, children);
|
|
1796
|
+
}
|
|
1797
|
+
function useTokens() {
|
|
1798
|
+
return useContext2(TokensContext);
|
|
1799
|
+
}
|
|
1800
|
+
|
|
1801
|
+
// src/containers/ThreadContainer.tsx
|
|
1802
|
+
import { ThreadPrimitive, useAuiState as useAuiState8 } from "@assistant-ui/react";
|
|
1803
|
+
|
|
1804
|
+
// src/hooks/useComposerBusyState.ts
|
|
1805
|
+
import { useThreadIsRunning } from "@assistant-ui/core/react";
|
|
1806
|
+
import { createContext as createContext3, createElement as createElement2, useCallback, useContext as useContext3, useEffect, useState as useState4 } from "react";
|
|
1807
|
+
var ComposerBusyContext = createContext3(null);
|
|
1808
|
+
function useComposerBusyStateValue() {
|
|
1809
|
+
const isRunning = useThreadIsRunning();
|
|
1810
|
+
const [isSubmitting, setIsSubmitting] = useState4(false);
|
|
1811
|
+
useEffect(() => {
|
|
1812
|
+
if (!isRunning) {
|
|
1813
|
+
setIsSubmitting(false);
|
|
1814
|
+
}
|
|
1815
|
+
}, [isRunning]);
|
|
1816
|
+
const isBusy = isRunning || isSubmitting;
|
|
1817
|
+
const resetBusy = useCallback(() => {
|
|
1818
|
+
setIsSubmitting(false);
|
|
1819
|
+
}, []);
|
|
1820
|
+
const send = useCallback((sendFn) => {
|
|
1821
|
+
setIsSubmitting(true);
|
|
1822
|
+
try {
|
|
1823
|
+
const result = sendFn();
|
|
1824
|
+
if (result != null && typeof result.then === "function") {
|
|
1825
|
+
void result.catch(() => {
|
|
1826
|
+
setIsSubmitting(false);
|
|
1827
|
+
});
|
|
1828
|
+
}
|
|
1829
|
+
} catch {
|
|
1830
|
+
setIsSubmitting(false);
|
|
1831
|
+
}
|
|
1832
|
+
}, []);
|
|
1833
|
+
return { isBusy, isRunning, isSubmitting, send, resetBusy };
|
|
1834
|
+
}
|
|
1835
|
+
function ComposerBusyProvider({ children }) {
|
|
1836
|
+
const value = useComposerBusyStateValue();
|
|
1837
|
+
return createElement2(ComposerBusyContext.Provider, { value }, children);
|
|
1838
|
+
}
|
|
1839
|
+
function useComposerBusyState() {
|
|
1840
|
+
const value = useContext3(ComposerBusyContext);
|
|
1841
|
+
if (value == null) {
|
|
1842
|
+
throw new Error("useComposerBusyState must be used within ComposerBusyProvider");
|
|
1843
|
+
}
|
|
1844
|
+
return value;
|
|
1845
|
+
}
|
|
1846
|
+
|
|
1847
|
+
// src/containers/AssistantMessageContainer.tsx
|
|
1848
|
+
import { groupPartByType, MessagePrimitive as MessagePrimitive2, useAui as useAui2 } from "@assistant-ui/react";
|
|
1849
|
+
import {
|
|
1850
|
+
useActionBarCopy as useActionBarCopy2,
|
|
1851
|
+
useMessageBranching,
|
|
1852
|
+
useMessageError,
|
|
1853
|
+
useThreadIsRunning as useThreadIsRunning2
|
|
1854
|
+
} from "@assistant-ui/core/react";
|
|
1855
|
+
|
|
1856
|
+
// src/containers/AssistantTextContainer.tsx
|
|
1857
|
+
import { useCallback as useCallback3 } from "react";
|
|
1858
|
+
import { useAuiState as useAuiState2 } from "@assistant-ui/react";
|
|
1859
|
+
import { useTrueFoundryDownloadSandboxFile } from "@truefoundry/assistant-ui-runtime";
|
|
1860
|
+
|
|
1861
|
+
// src/containers/ErrorToasterContainer.tsx
|
|
1862
|
+
import { createContext as createContext4, useCallback as useCallback2, useContext as useContext4, useMemo as useMemo3, useState as useState5 } from "react";
|
|
1863
|
+
import { TrueFoundryGatewayError } from "truefoundry-gateway-sdk";
|
|
1864
|
+
import { jsx as jsx36, jsxs as jsxs24 } from "react/jsx-runtime";
|
|
1865
|
+
var ErrorToasterContext = createContext4(null);
|
|
1866
|
+
function formatErrorBody(body) {
|
|
1867
|
+
if (body == null) return void 0;
|
|
1868
|
+
if (typeof body === "string") return body;
|
|
1869
|
+
try {
|
|
1870
|
+
return JSON.stringify(body, null, 2);
|
|
1871
|
+
} catch {
|
|
1872
|
+
return String(body);
|
|
1873
|
+
}
|
|
1874
|
+
}
|
|
1875
|
+
function normalizeError(error) {
|
|
1876
|
+
if (error instanceof TrueFoundryGatewayError) {
|
|
1877
|
+
const statusCode = error.statusCode;
|
|
1878
|
+
const title = statusCode != null ? `Request failed (${statusCode})` : "Request failed";
|
|
1879
|
+
const description = formatErrorBody(error.body) ?? (error.message || "The gateway returned an error.");
|
|
1880
|
+
return { title, description };
|
|
1881
|
+
}
|
|
1882
|
+
if (error instanceof Error) {
|
|
1883
|
+
return { title: "Something went wrong", description: error.message || "An unexpected error occurred." };
|
|
1884
|
+
}
|
|
1885
|
+
return { title: "Something went wrong", description: String(error) };
|
|
1886
|
+
}
|
|
1887
|
+
function ErrorToasterProvider({ children }) {
|
|
1888
|
+
const ToastStack2 = useSlot("ToastStack");
|
|
1889
|
+
const Toast2 = useSlot("Toast");
|
|
1890
|
+
const [toast, setToast] = useState5(null);
|
|
1891
|
+
const [open, setOpen] = useState5(false);
|
|
1892
|
+
const showError = useCallback2((error) => {
|
|
1893
|
+
setToast(normalizeError(error));
|
|
1894
|
+
setOpen(true);
|
|
1895
|
+
}, []);
|
|
1896
|
+
const value = useMemo3(() => ({ showError }), [showError]);
|
|
1897
|
+
return /* @__PURE__ */ jsx36(ErrorToasterContext.Provider, { value, children: /* @__PURE__ */ jsxs24(ToastStack2, { children: [
|
|
1898
|
+
children,
|
|
1899
|
+
toast != null && /* @__PURE__ */ jsx36(Toast2, { title: toast.title, description: toast.description, open, onOpenChange: setOpen })
|
|
1900
|
+
] }) });
|
|
1901
|
+
}
|
|
1902
|
+
function useErrorToaster() {
|
|
1903
|
+
const context = useContext4(ErrorToasterContext);
|
|
1904
|
+
if (context == null) {
|
|
1905
|
+
throw new Error("useErrorToaster must be used within ErrorToasterProvider");
|
|
1906
|
+
}
|
|
1907
|
+
return context;
|
|
1908
|
+
}
|
|
1909
|
+
function useErrorToasterOptional() {
|
|
1910
|
+
return useContext4(ErrorToasterContext);
|
|
1911
|
+
}
|
|
1912
|
+
|
|
1913
|
+
// src/containers/AssistantTextContainer.tsx
|
|
1914
|
+
import { jsx as jsx37 } from "react/jsx-runtime";
|
|
1915
|
+
function filenameFromPath(path) {
|
|
1916
|
+
return path.split("/").pop() || "download";
|
|
1917
|
+
}
|
|
1918
|
+
function triggerBrowserDownload(blob, filename) {
|
|
1919
|
+
if (typeof document === "undefined") return;
|
|
1920
|
+
const url = URL.createObjectURL(blob);
|
|
1921
|
+
const anchor = document.createElement("a");
|
|
1922
|
+
anchor.href = url;
|
|
1923
|
+
anchor.download = filename;
|
|
1924
|
+
anchor.click();
|
|
1925
|
+
URL.revokeObjectURL(url);
|
|
1926
|
+
}
|
|
1927
|
+
function AssistantTextContainer() {
|
|
1928
|
+
const Markdown2 = useSlot("Markdown");
|
|
1929
|
+
const downloadSandboxFile = useTrueFoundryDownloadSandboxFile();
|
|
1930
|
+
const errorToaster = useErrorToasterOptional();
|
|
1931
|
+
const text = useAuiState2(
|
|
1932
|
+
(s) => s.part.type === "text" || s.part.type === "reasoning" ? s.part.text : ""
|
|
1933
|
+
);
|
|
1934
|
+
const isStreaming = useAuiState2((s) => {
|
|
1935
|
+
if (s.message.status?.type !== "running") return false;
|
|
1936
|
+
const lastIndex = s.message.parts.length - 1;
|
|
1937
|
+
if (lastIndex < 0) return false;
|
|
1938
|
+
if (s.part.type !== "text" && s.part.type !== "reasoning") return false;
|
|
1939
|
+
return s.message.parts[lastIndex] === s.part;
|
|
1940
|
+
});
|
|
1941
|
+
const handleDownloadArtifact = useCallback3(
|
|
1942
|
+
(path) => downloadSandboxFile(path).then((blob) => triggerBrowserDownload(blob, filenameFromPath(path))).catch((error) => {
|
|
1943
|
+
if (errorToaster != null) {
|
|
1944
|
+
errorToaster.showError(error);
|
|
1945
|
+
} else {
|
|
1946
|
+
console.error("Failed to download sandbox artifact", error);
|
|
1947
|
+
}
|
|
1948
|
+
}),
|
|
1949
|
+
[downloadSandboxFile, errorToaster]
|
|
1950
|
+
);
|
|
1951
|
+
return /* @__PURE__ */ jsx37(Markdown2, { content: text, isStreaming, onDownloadArtifact: handleDownloadArtifact });
|
|
1952
|
+
}
|
|
1953
|
+
|
|
1954
|
+
// src/containers/MessageImageContainer.tsx
|
|
1955
|
+
import { useAuiState as useAuiState3 } from "@assistant-ui/react";
|
|
1956
|
+
import { jsx as jsx38 } from "react/jsx-runtime";
|
|
1957
|
+
function MessageImageContainer() {
|
|
1958
|
+
const AttachmentPreviewDialog2 = useSlot("AttachmentPreviewDialog");
|
|
1959
|
+
const image = useAuiState3((s) => s.part.type === "image" ? s.part.image : "");
|
|
1960
|
+
const filename = useAuiState3(
|
|
1961
|
+
(s) => s.part.type === "image" ? s.part.filename : void 0
|
|
1962
|
+
);
|
|
1963
|
+
if (!image) {
|
|
1964
|
+
return null;
|
|
1965
|
+
}
|
|
1966
|
+
const card = /* @__PURE__ */ jsx38(
|
|
1967
|
+
AttachmentCard,
|
|
1968
|
+
{
|
|
1969
|
+
name: filename ?? "image",
|
|
1970
|
+
previewSrc: image,
|
|
1971
|
+
isImage: true,
|
|
1972
|
+
size: "preview",
|
|
1973
|
+
previewRem: USER_MESSAGE_ATTACHMENT_PREVIEW_REM
|
|
1974
|
+
}
|
|
1975
|
+
);
|
|
1976
|
+
return /* @__PURE__ */ jsx38(AttachmentPreviewDialog2, { previewSrc: image, children: /* @__PURE__ */ jsx38("div", { className: "aui-message-image", children: card }) });
|
|
1977
|
+
}
|
|
1978
|
+
|
|
1979
|
+
// src/containers/ReasoningContainer.tsx
|
|
1980
|
+
import { useState as useState6 } from "react";
|
|
1981
|
+
import { useAuiState as useAuiState4 } from "@assistant-ui/react";
|
|
1982
|
+
import { jsx as jsx39 } from "react/jsx-runtime";
|
|
1983
|
+
function ReasoningContainer({ group, children }) {
|
|
1984
|
+
const ReasoningCard2 = useSlot("ReasoningCard");
|
|
1985
|
+
const streaming = useAuiState4((s) => {
|
|
1986
|
+
if (s.message.status?.type !== "running") return false;
|
|
1987
|
+
const lastIndex = s.message.parts.length - 1;
|
|
1988
|
+
if (lastIndex < 0) return false;
|
|
1989
|
+
if (s.message.parts[lastIndex]?.type !== "reasoning") return false;
|
|
1990
|
+
return lastIndex >= group.indices[0] && lastIndex <= group.indices[group.indices.length - 1];
|
|
1991
|
+
});
|
|
1992
|
+
const [expanded, setExpanded] = useState6(streaming);
|
|
1993
|
+
const [prevStreaming, setPrevStreaming] = useState6(streaming);
|
|
1994
|
+
if (streaming !== prevStreaming) {
|
|
1995
|
+
setPrevStreaming(streaming);
|
|
1996
|
+
if (streaming) setExpanded(true);
|
|
1997
|
+
}
|
|
1998
|
+
return /* @__PURE__ */ jsx39(ReasoningCard2, { streaming, expanded, onToggle: () => setExpanded((prev) => !prev), children });
|
|
1999
|
+
}
|
|
2000
|
+
|
|
2001
|
+
// src/containers/ToolCallContainer.tsx
|
|
2002
|
+
import { useState as useState7 } from "react";
|
|
2003
|
+
import {
|
|
2004
|
+
MessagePrimitive,
|
|
2005
|
+
useToolCallElapsed
|
|
2006
|
+
} from "@assistant-ui/react";
|
|
2007
|
+
import { useTrueFoundryRespondToToolApproval } from "@truefoundry/assistant-ui-runtime";
|
|
2008
|
+
|
|
2009
|
+
// src/containers/nestedApprovalBridge.ts
|
|
2010
|
+
import { createContext as createContext5, useContext as useContext5 } from "react";
|
|
2011
|
+
var NestedApprovalBridgeContext = createContext5(
|
|
2012
|
+
null
|
|
2013
|
+
);
|
|
2014
|
+
function useNestedApprovalBridge() {
|
|
2015
|
+
return useContext5(NestedApprovalBridgeContext);
|
|
2016
|
+
}
|
|
2017
|
+
|
|
2018
|
+
// src/containers/ToolCallContainer.tsx
|
|
2019
|
+
import { jsx as jsx40 } from "react/jsx-runtime";
|
|
2020
|
+
var SUB_AGENT_TOOL_NAME = "create_sub_agent";
|
|
2021
|
+
var APPROVAL_OPTION_DEFAULT_LABELS = {
|
|
2022
|
+
"allow-once": "Allow",
|
|
2023
|
+
"allow-always": "Always allow",
|
|
2024
|
+
"reject-once": "Deny",
|
|
2025
|
+
"reject-always": "Always deny"
|
|
2026
|
+
};
|
|
2027
|
+
var isAllowKind = (kind) => kind === "allow-once" || kind === "allow-always";
|
|
2028
|
+
function hasPendingToolApproval(approval) {
|
|
2029
|
+
return approval != null && approval.approved === void 0 && approval.resolution === void 0;
|
|
2030
|
+
}
|
|
2031
|
+
function buildApprovalOptions(options) {
|
|
2032
|
+
const declared = options?.filter((o) => Object.hasOwn(APPROVAL_OPTION_DEFAULT_LABELS, o.kind));
|
|
2033
|
+
if (declared && declared.length > 0) {
|
|
2034
|
+
const allow = declared.filter((o) => isAllowKind(o.kind));
|
|
2035
|
+
const reject = declared.filter((o) => !isAllowKind(o.kind));
|
|
2036
|
+
const mapped = [...allow, ...reject].map((o) => ({
|
|
2037
|
+
id: o.id,
|
|
2038
|
+
label: o.label ?? APPROVAL_OPTION_DEFAULT_LABELS[o.kind] ?? o.id,
|
|
2039
|
+
isAllow: isAllowKind(o.kind),
|
|
2040
|
+
grants: o.grants,
|
|
2041
|
+
confirm: o.confirm != null ? typeof o.confirm === "object" ? o.confirm : {} : void 0
|
|
2042
|
+
}));
|
|
2043
|
+
if (reject.length === 0) {
|
|
2044
|
+
mapped.push({ id: "__deny", label: "Deny", isAllow: false });
|
|
2045
|
+
}
|
|
2046
|
+
return mapped;
|
|
2047
|
+
}
|
|
2048
|
+
return [
|
|
2049
|
+
{ id: "__allow", label: "Allow", isAllow: true },
|
|
2050
|
+
{ id: "__deny", label: "Deny", isAllow: false }
|
|
2051
|
+
];
|
|
2052
|
+
}
|
|
2053
|
+
function formatDuration(ms) {
|
|
2054
|
+
if (ms < 1e3) return "<1s";
|
|
2055
|
+
const seconds = ms / 1e3;
|
|
2056
|
+
if (seconds < 10) return `${(Math.floor(seconds * 10) / 10).toFixed(1)}s`;
|
|
2057
|
+
if (seconds < 60) return `${Math.floor(seconds)}s`;
|
|
2058
|
+
return `${Math.floor(seconds / 60)}m ${Math.floor(seconds % 60)}s`;
|
|
2059
|
+
}
|
|
2060
|
+
function toStatus(statusType) {
|
|
2061
|
+
if (statusType === "complete") return "success";
|
|
2062
|
+
if (statusType === "incomplete") return "error";
|
|
2063
|
+
return "running";
|
|
2064
|
+
}
|
|
2065
|
+
function ToolApprovalSlot({ part }) {
|
|
2066
|
+
const ToolApprovalBar2 = useSlot("ToolApprovalBar");
|
|
2067
|
+
const nestedBridge = useNestedApprovalBridge();
|
|
2068
|
+
const respond = (response) => {
|
|
2069
|
+
if (nestedBridge) {
|
|
2070
|
+
nestedBridge(response);
|
|
2071
|
+
return;
|
|
2072
|
+
}
|
|
2073
|
+
part.respondToApproval(response);
|
|
2074
|
+
};
|
|
2075
|
+
const onSelectOption = (optionId) => {
|
|
2076
|
+
if (optionId === "__allow") return respond({ approved: true });
|
|
2077
|
+
if (optionId === "__deny") return respond({ approved: false });
|
|
2078
|
+
return respond({ optionId });
|
|
2079
|
+
};
|
|
2080
|
+
return /* @__PURE__ */ jsx40(ToolApprovalBar2, { options: buildApprovalOptions(part.approval?.options), onSelectOption });
|
|
2081
|
+
}
|
|
2082
|
+
var ToolCallContainer = (part) => {
|
|
2083
|
+
const ToolCallCard2 = useSlot("ToolCallCard");
|
|
2084
|
+
const respondToNestedApproval = useTrueFoundryRespondToToolApproval();
|
|
2085
|
+
const elapsedMs = useToolCallElapsed();
|
|
2086
|
+
const isRequiresAction = part.status?.type === "requires-action";
|
|
2087
|
+
const [expanded, setExpanded] = useState7(isRequiresAction);
|
|
2088
|
+
const [prevRequiresAction, setPrevRequiresAction] = useState7(isRequiresAction);
|
|
2089
|
+
if (isRequiresAction !== prevRequiresAction) {
|
|
2090
|
+
setPrevRequiresAction(isRequiresAction);
|
|
2091
|
+
if (isRequiresAction) setExpanded(true);
|
|
2092
|
+
}
|
|
2093
|
+
const showApproval = isRequiresAction && hasPendingToolApproval(part.approval);
|
|
2094
|
+
const isSubAgent = part.toolName === SUB_AGENT_TOOL_NAME;
|
|
2095
|
+
const durationText = elapsedMs === void 0 ? void 0 : formatDuration(elapsedMs);
|
|
2096
|
+
const status = toStatus(part.status?.type);
|
|
2097
|
+
if (isSubAgent) {
|
|
2098
|
+
const firstNested = part.messages?.[0];
|
|
2099
|
+
const subAgent = firstNested?.metadata?.custom?.subAgent;
|
|
2100
|
+
const agentName = subAgent?.title ?? subAgent?.name ?? part.toolName;
|
|
2101
|
+
const instruction = subAgent?.input ?? "";
|
|
2102
|
+
const stepCount = part.messages?.length ?? 0;
|
|
2103
|
+
const bridge = (response) => {
|
|
2104
|
+
if (part.approval == null) return;
|
|
2105
|
+
const approved = "approved" in response ? response.approved : void 0;
|
|
2106
|
+
if (approved === void 0) return;
|
|
2107
|
+
respondToNestedApproval({ approvalId: part.approval.id, approved });
|
|
2108
|
+
};
|
|
2109
|
+
return /* @__PURE__ */ jsx40(
|
|
2110
|
+
ToolCallCard2,
|
|
2111
|
+
{
|
|
2112
|
+
variant: "sub-agent",
|
|
2113
|
+
name: part.toolName,
|
|
2114
|
+
status,
|
|
2115
|
+
expanded,
|
|
2116
|
+
onToggle: () => setExpanded((prev) => !prev),
|
|
2117
|
+
durationText,
|
|
2118
|
+
agentName,
|
|
2119
|
+
instruction,
|
|
2120
|
+
stepCount,
|
|
2121
|
+
children: /* @__PURE__ */ jsx40(NestedApprovalBridgeContext.Provider, { value: bridge, children: /* @__PURE__ */ jsx40(MessagePrimitive.Root, { "data-role": "assistant", children: /* @__PURE__ */ jsx40(MessagePrimitive.Parts, { components: { tools: { Fallback: ToolCallContainer } } }) }) })
|
|
2122
|
+
}
|
|
2123
|
+
);
|
|
2124
|
+
}
|
|
2125
|
+
return /* @__PURE__ */ jsx40(
|
|
2126
|
+
ToolCallCard2,
|
|
2127
|
+
{
|
|
2128
|
+
variant: "tool",
|
|
2129
|
+
name: part.toolName,
|
|
2130
|
+
status,
|
|
2131
|
+
expanded,
|
|
2132
|
+
onToggle: () => setExpanded((prev) => !prev),
|
|
2133
|
+
durationText,
|
|
2134
|
+
argsText: part.argsText,
|
|
2135
|
+
result: part.result === void 0 ? void 0 : typeof part.result === "string" ? part.result : JSON.stringify(part.result, null, 2),
|
|
2136
|
+
isError: part.isError,
|
|
2137
|
+
approvalSlot: showApproval ? /* @__PURE__ */ jsx40(ToolApprovalSlot, { part }) : void 0
|
|
2138
|
+
}
|
|
2139
|
+
);
|
|
2140
|
+
};
|
|
2141
|
+
|
|
2142
|
+
// src/containers/ToolGroupContainer.tsx
|
|
2143
|
+
import { useState as useState8 } from "react";
|
|
2144
|
+
import { jsx as jsx41 } from "react/jsx-runtime";
|
|
2145
|
+
function ToolGroupContainer({ group, children }) {
|
|
2146
|
+
const ToolGroupCard2 = useSlot("ToolGroupCard");
|
|
2147
|
+
const [expanded, setExpanded] = useState8(true);
|
|
2148
|
+
return /* @__PURE__ */ jsx41(
|
|
2149
|
+
ToolGroupCard2,
|
|
2150
|
+
{
|
|
2151
|
+
toolCallCount: group.indices.length,
|
|
2152
|
+
active: group.status.type === "running",
|
|
2153
|
+
expanded,
|
|
2154
|
+
onToggle: () => setExpanded((prev) => !prev),
|
|
2155
|
+
children
|
|
2156
|
+
}
|
|
2157
|
+
);
|
|
2158
|
+
}
|
|
2159
|
+
|
|
2160
|
+
// src/containers/AssistantMessageContainer.tsx
|
|
2161
|
+
import { jsx as jsx42 } from "react/jsx-runtime";
|
|
2162
|
+
function AssistantLeafPartContainer({ part }) {
|
|
2163
|
+
switch (part.type) {
|
|
2164
|
+
case "text":
|
|
2165
|
+
case "reasoning":
|
|
2166
|
+
return /* @__PURE__ */ jsx42(AssistantTextContainer, {});
|
|
2167
|
+
case "image":
|
|
2168
|
+
return /* @__PURE__ */ jsx42(MessageImageContainer, {});
|
|
2169
|
+
case "tool-call":
|
|
2170
|
+
return /* @__PURE__ */ jsx42(ToolCallContainer, { ...part });
|
|
2171
|
+
default:
|
|
2172
|
+
return null;
|
|
2173
|
+
}
|
|
2174
|
+
}
|
|
2175
|
+
function downloadMarkdown(text) {
|
|
2176
|
+
if (typeof document === "undefined") return;
|
|
2177
|
+
const blob = new Blob([text], { type: "text/markdown" });
|
|
2178
|
+
const url = URL.createObjectURL(blob);
|
|
2179
|
+
const anchor = document.createElement("a");
|
|
2180
|
+
anchor.href = url;
|
|
2181
|
+
anchor.download = "message.md";
|
|
2182
|
+
anchor.click();
|
|
2183
|
+
URL.revokeObjectURL(url);
|
|
2184
|
+
}
|
|
2185
|
+
function AssistantMessageContainer() {
|
|
2186
|
+
const MessageBubble2 = useSlot("MessageBubble");
|
|
2187
|
+
const MessageIndicator2 = useSlot("MessageIndicator");
|
|
2188
|
+
const MessageErrorBanner2 = useSlot("MessageErrorBanner");
|
|
2189
|
+
const MessageActionBar2 = useSlot("MessageActionBar");
|
|
2190
|
+
const BranchIndicator2 = useSlot("BranchIndicator");
|
|
2191
|
+
const aui = useAui2();
|
|
2192
|
+
const isRunning = useThreadIsRunning2();
|
|
2193
|
+
const error = useMessageError();
|
|
2194
|
+
const { copy, isCopied } = useActionBarCopy2({
|
|
2195
|
+
copyToClipboard: (text) => navigator.clipboard.writeText(text)
|
|
2196
|
+
});
|
|
2197
|
+
const { branchNumber, branchCount, goToPrev, goToNext } = useMessageBranching();
|
|
2198
|
+
return /* @__PURE__ */ jsx42(MessagePrimitive2.Root, { "data-role": "assistant", children: /* @__PURE__ */ jsx42(
|
|
2199
|
+
MessageBubble2,
|
|
2200
|
+
{
|
|
2201
|
+
variant: "assistant",
|
|
2202
|
+
error: error !== void 0 ? /* @__PURE__ */ jsx42(MessageErrorBanner2, { message: String(error) }) : void 0,
|
|
2203
|
+
branchIndicator: /* @__PURE__ */ jsx42(
|
|
2204
|
+
BranchIndicator2,
|
|
2205
|
+
{
|
|
2206
|
+
index: branchNumber,
|
|
2207
|
+
count: branchCount,
|
|
2208
|
+
onPrevious: goToPrev,
|
|
2209
|
+
onNext: goToNext
|
|
2210
|
+
}
|
|
2211
|
+
),
|
|
2212
|
+
actionBar: !isRunning ? /* @__PURE__ */ jsx42(
|
|
2213
|
+
MessageActionBar2,
|
|
2214
|
+
{
|
|
2215
|
+
isCopied,
|
|
2216
|
+
onCopy: copy,
|
|
2217
|
+
onExportMarkdown: () => downloadMarkdown(aui.message().getCopyText())
|
|
2218
|
+
}
|
|
2219
|
+
) : void 0,
|
|
2220
|
+
children: /* @__PURE__ */ jsx42(
|
|
2221
|
+
MessagePrimitive2.GroupedParts,
|
|
2222
|
+
{
|
|
2223
|
+
groupBy: groupPartByType({
|
|
2224
|
+
reasoning: ["group-chainOfThought", "group-reasoning"],
|
|
2225
|
+
"tool-call": ["group-chainOfThought", "group-tool"],
|
|
2226
|
+
"standalone-tool-call": []
|
|
2227
|
+
}),
|
|
2228
|
+
children: ({ part, children }) => {
|
|
2229
|
+
switch (part.type) {
|
|
2230
|
+
case "group-chainOfThought":
|
|
2231
|
+
return /* @__PURE__ */ jsx42("div", { "data-slot": "aui_chain-of-thought", className: "flex flex-col gap-3", children });
|
|
2232
|
+
case "group-tool":
|
|
2233
|
+
return /* @__PURE__ */ jsx42(ToolGroupContainer, { group: part, children });
|
|
2234
|
+
case "group-reasoning":
|
|
2235
|
+
return /* @__PURE__ */ jsx42(ReasoningContainer, { group: part, children });
|
|
2236
|
+
case "text":
|
|
2237
|
+
case "reasoning":
|
|
2238
|
+
case "tool-call":
|
|
2239
|
+
case "image":
|
|
2240
|
+
case "data":
|
|
2241
|
+
return /* @__PURE__ */ jsx42(AssistantLeafPartContainer, { part });
|
|
2242
|
+
case "indicator":
|
|
2243
|
+
return /* @__PURE__ */ jsx42(MessageIndicator2, {});
|
|
2244
|
+
default:
|
|
2245
|
+
return null;
|
|
2246
|
+
}
|
|
2247
|
+
}
|
|
2248
|
+
}
|
|
2249
|
+
)
|
|
2250
|
+
}
|
|
2251
|
+
) });
|
|
2252
|
+
}
|
|
2253
|
+
|
|
2254
|
+
// src/containers/UserEditComposerContainer.tsx
|
|
2255
|
+
import {
|
|
2256
|
+
ComposerPrimitive as ComposerPrimitive2,
|
|
2257
|
+
MessagePrimitive as MessagePrimitive4,
|
|
2258
|
+
useAuiState as useAuiState7
|
|
2259
|
+
} from "@assistant-ui/react";
|
|
2260
|
+
import { useThreadIsRunning as useThreadIsRunning3 } from "@assistant-ui/core/react";
|
|
2261
|
+
|
|
2262
|
+
// src/containers/AttachmentsContainer.tsx
|
|
2263
|
+
import { ComposerPrimitive, MessagePrimitive as MessagePrimitive3, useAui as useAui3, useAuiState as useAuiState6 } from "@assistant-ui/react";
|
|
2264
|
+
|
|
2265
|
+
// src/containers/useAttachmentPreviewSrc.ts
|
|
2266
|
+
import { useEffect as useEffect2, useState as useState9 } from "react";
|
|
2267
|
+
import { useAuiState as useAuiState5 } from "@assistant-ui/react";
|
|
2268
|
+
function isImageAttachment(type, contentType) {
|
|
2269
|
+
return type === "image" || (contentType?.startsWith("image/") ?? false);
|
|
2270
|
+
}
|
|
2271
|
+
function useFileObjectUrl(file) {
|
|
2272
|
+
const [src, setSrc] = useState9(void 0);
|
|
2273
|
+
useEffect2(() => {
|
|
2274
|
+
if (!file) {
|
|
2275
|
+
setSrc(void 0);
|
|
2276
|
+
return;
|
|
2277
|
+
}
|
|
2278
|
+
const objectUrl = URL.createObjectURL(file);
|
|
2279
|
+
setSrc(objectUrl);
|
|
2280
|
+
return () => URL.revokeObjectURL(objectUrl);
|
|
2281
|
+
}, [file]);
|
|
2282
|
+
return src;
|
|
2283
|
+
}
|
|
2284
|
+
function useAttachmentPreviewSrc() {
|
|
2285
|
+
const type = useAuiState5((s) => s.attachment.type);
|
|
2286
|
+
const contentType = useAuiState5((s) => s.attachment.contentType);
|
|
2287
|
+
const file = useAuiState5((s) => "file" in s.attachment ? s.attachment.file : void 0);
|
|
2288
|
+
const contentSrc = useAuiState5((s) => {
|
|
2289
|
+
if (!isImageAttachment(s.attachment.type, s.attachment.contentType)) return void 0;
|
|
2290
|
+
const imagePart = s.attachment.content?.find((part) => part.type === "image");
|
|
2291
|
+
if (imagePart?.type === "image" && imagePart.image) return imagePart.image;
|
|
2292
|
+
return void 0;
|
|
2293
|
+
});
|
|
2294
|
+
const image = isImageAttachment(type, contentType);
|
|
2295
|
+
const fileSrc = useFileObjectUrl(image ? file : void 0);
|
|
2296
|
+
if (!image) return void 0;
|
|
2297
|
+
return fileSrc ?? contentSrc;
|
|
2298
|
+
}
|
|
2299
|
+
|
|
2300
|
+
// src/containers/AttachmentsContainer.tsx
|
|
2301
|
+
import { jsx as jsx43 } from "react/jsx-runtime";
|
|
2302
|
+
function ComposerAttachmentItem() {
|
|
2303
|
+
const AttachmentCard2 = useSlot("AttachmentCard");
|
|
2304
|
+
const AttachmentPreviewDialog2 = useSlot("AttachmentPreviewDialog");
|
|
2305
|
+
const aui = useAui3();
|
|
2306
|
+
const name = useAuiState6((s) => s.attachment.name);
|
|
2307
|
+
const contentType = useAuiState6((s) => s.attachment.contentType);
|
|
2308
|
+
const type = useAuiState6((s) => s.attachment.type);
|
|
2309
|
+
const isImage = isImageAttachment(type, contentType);
|
|
2310
|
+
const previewSrc = useAttachmentPreviewSrc();
|
|
2311
|
+
return /* @__PURE__ */ jsx43(AttachmentPreviewDialog2, { previewSrc, children: /* @__PURE__ */ jsx43(
|
|
2312
|
+
AttachmentCard2,
|
|
2313
|
+
{
|
|
2314
|
+
name,
|
|
2315
|
+
contentType,
|
|
2316
|
+
previewSrc,
|
|
2317
|
+
isImage,
|
|
2318
|
+
size: "chip",
|
|
2319
|
+
onRemove: () => void aui.attachment().remove()
|
|
2320
|
+
}
|
|
2321
|
+
) });
|
|
2322
|
+
}
|
|
2323
|
+
function MessageAttachmentItem() {
|
|
2324
|
+
const AttachmentCard2 = useSlot("AttachmentCard");
|
|
2325
|
+
const AttachmentPreviewDialog2 = useSlot("AttachmentPreviewDialog");
|
|
2326
|
+
const name = useAuiState6((s) => s.attachment.name);
|
|
2327
|
+
const contentType = useAuiState6((s) => s.attachment.contentType);
|
|
2328
|
+
const type = useAuiState6((s) => s.attachment.type);
|
|
2329
|
+
const isImage = isImageAttachment(type, contentType);
|
|
2330
|
+
const previewSrc = useAttachmentPreviewSrc();
|
|
2331
|
+
const card = /* @__PURE__ */ jsx43(
|
|
2332
|
+
AttachmentCard2,
|
|
2333
|
+
{
|
|
2334
|
+
name,
|
|
2335
|
+
contentType,
|
|
2336
|
+
previewSrc,
|
|
2337
|
+
isImage,
|
|
2338
|
+
size: isImage ? "preview" : "chip",
|
|
2339
|
+
previewRem: USER_MESSAGE_ATTACHMENT_PREVIEW_REM
|
|
2340
|
+
}
|
|
2341
|
+
);
|
|
2342
|
+
if (isImage && previewSrc) {
|
|
2343
|
+
return /* @__PURE__ */ jsx43(AttachmentPreviewDialog2, { previewSrc, children: card });
|
|
2344
|
+
}
|
|
2345
|
+
return card;
|
|
2346
|
+
}
|
|
2347
|
+
function ComposerAttachmentsContainer() {
|
|
2348
|
+
return /* @__PURE__ */ jsx43("div", { className: "aui-composer-attachments flex w-full flex-row flex-wrap items-center gap-2 empty:hidden", children: /* @__PURE__ */ jsx43(ComposerPrimitive.Attachments, { children: () => /* @__PURE__ */ jsx43(ComposerAttachmentItem, {}) }) });
|
|
2349
|
+
}
|
|
2350
|
+
function MessageAttachmentsContainer() {
|
|
2351
|
+
return /* @__PURE__ */ jsx43("div", { className: "aui-user-message-attachments-end col-span-full col-start-1 row-start-1 flex w-full flex-row justify-end gap-2", children: /* @__PURE__ */ jsx43(MessagePrimitive3.Attachments, { children: () => /* @__PURE__ */ jsx43(MessageAttachmentItem, {}) }) });
|
|
2352
|
+
}
|
|
2353
|
+
function ComposerAttachmentPickerContainer() {
|
|
2354
|
+
const AttachmentPickerButton2 = useSlot("AttachmentPickerButton");
|
|
2355
|
+
return /* @__PURE__ */ jsx43(ComposerPrimitive.AddAttachment, { asChild: true, children: /* @__PURE__ */ jsx43(AttachmentPickerButton2, {}) });
|
|
2356
|
+
}
|
|
2357
|
+
|
|
2358
|
+
// src/containers/UserEditComposerContainer.tsx
|
|
2359
|
+
import { jsx as jsx44, jsxs as jsxs25 } from "react/jsx-runtime";
|
|
2360
|
+
function ReadOnlyMessageAttachments() {
|
|
2361
|
+
const hasAttachments = useAuiState7(
|
|
2362
|
+
(s) => (s.message.attachments?.length ?? 0) > 0
|
|
2363
|
+
);
|
|
2364
|
+
if (!hasAttachments) {
|
|
2365
|
+
return null;
|
|
2366
|
+
}
|
|
2367
|
+
return /* @__PURE__ */ jsx44("div", { className: "pointer-events-none opacity-90", children: /* @__PURE__ */ jsx44(MessageAttachmentsContainer, {}) });
|
|
2368
|
+
}
|
|
2369
|
+
function UserEditComposerContainer() {
|
|
2370
|
+
const Button2 = useSlot("Button");
|
|
2371
|
+
const isRunning = useThreadIsRunning3();
|
|
2372
|
+
return /* @__PURE__ */ jsx44(MessagePrimitive4.Root, { "data-role": "user", children: /* @__PURE__ */ jsxs25(
|
|
2373
|
+
"div",
|
|
2374
|
+
{
|
|
2375
|
+
"data-slot": "aui_user-edit-composer-root",
|
|
2376
|
+
className: "fade-in slide-in-from-bottom-1 animate-in grid auto-rows-auto grid-cols-[minmax(72px,1fr)_auto] content-start gap-y-2 px-2 duration-150 [&:where(>*)]:col-start-2",
|
|
2377
|
+
children: [
|
|
2378
|
+
/* @__PURE__ */ jsx44(ReadOnlyMessageAttachments, {}),
|
|
2379
|
+
/* @__PURE__ */ jsx44(ComposerPrimitive2.Root, { asChild: true, children: /* @__PURE__ */ jsx44("div", { className: "aui-user-edit-composer col-start-2 min-w-0", children: /* @__PURE__ */ jsxs25("div", { className: "ring-primary/60 bg-muted rounded-xl px-4 py-3 ring-2", children: [
|
|
2380
|
+
/* @__PURE__ */ jsx44(
|
|
2381
|
+
ComposerPrimitive2.Input,
|
|
2382
|
+
{
|
|
2383
|
+
disabled: isRunning,
|
|
2384
|
+
className: "placeholder:text-muted-foreground/80 max-h-32 min-h-10 w-full resize-none bg-transparent text-base outline-none"
|
|
2385
|
+
}
|
|
2386
|
+
),
|
|
2387
|
+
/* @__PURE__ */ jsxs25("div", { className: "mt-3 flex items-end justify-between gap-3", children: [
|
|
2388
|
+
/* @__PURE__ */ jsxs25("p", { className: "text-muted-foreground text-xs", children: [
|
|
2389
|
+
/* @__PURE__ */ jsx44("kbd", { className: "bg-background/60 rounded border px-1 py-0.5 font-sans text-[10px]", children: "Enter" }),
|
|
2390
|
+
" ",
|
|
2391
|
+
"to save",
|
|
2392
|
+
" ",
|
|
2393
|
+
/* @__PURE__ */ jsx44("kbd", { className: "bg-background/60 rounded border px-1 py-0.5 font-sans text-[10px]", children: "Esc" }),
|
|
2394
|
+
" ",
|
|
2395
|
+
"to cancel"
|
|
2396
|
+
] }),
|
|
2397
|
+
/* @__PURE__ */ jsxs25("div", { className: "flex items-center gap-2", children: [
|
|
2398
|
+
/* @__PURE__ */ jsx44(ComposerPrimitive2.Cancel, { asChild: true, children: /* @__PURE__ */ jsx44(
|
|
2399
|
+
Button2,
|
|
2400
|
+
{
|
|
2401
|
+
type: "button",
|
|
2402
|
+
variant: "ghost",
|
|
2403
|
+
size: "sm",
|
|
2404
|
+
className: "text-muted-foreground h-8 px-2",
|
|
2405
|
+
children: "Cancel"
|
|
2406
|
+
}
|
|
2407
|
+
) }),
|
|
2408
|
+
/* @__PURE__ */ jsx44(ComposerPrimitive2.Send, { asChild: true, children: /* @__PURE__ */ jsx44(
|
|
2409
|
+
Button2,
|
|
2410
|
+
{
|
|
2411
|
+
type: "button",
|
|
2412
|
+
size: "sm",
|
|
2413
|
+
className: cn("h-8 rounded-lg px-3"),
|
|
2414
|
+
disabled: isRunning,
|
|
2415
|
+
children: "Send"
|
|
2416
|
+
}
|
|
2417
|
+
) })
|
|
2418
|
+
] })
|
|
2419
|
+
] })
|
|
2420
|
+
] }) }) })
|
|
2421
|
+
]
|
|
2422
|
+
}
|
|
2423
|
+
) });
|
|
2424
|
+
}
|
|
2425
|
+
|
|
2426
|
+
// src/containers/UserMessageContainer.tsx
|
|
2427
|
+
import { MessagePrimitive as MessagePrimitive5 } from "@assistant-ui/react";
|
|
2428
|
+
import { useThreadIsRunning as useThreadIsRunning4 } from "@assistant-ui/core/react";
|
|
2429
|
+
import { jsx as jsx45 } from "react/jsx-runtime";
|
|
2430
|
+
function UserMessageContainer() {
|
|
2431
|
+
const MessageBubble2 = useSlot("MessageBubble");
|
|
2432
|
+
const UserMessageActionBar2 = useSlot("UserMessageActionBar");
|
|
2433
|
+
const isRunning = useThreadIsRunning4();
|
|
2434
|
+
return /* @__PURE__ */ jsx45(MessagePrimitive5.Root, { "data-role": "user", children: /* @__PURE__ */ jsx45(
|
|
2435
|
+
MessageBubble2,
|
|
2436
|
+
{
|
|
2437
|
+
variant: "user",
|
|
2438
|
+
attachments: /* @__PURE__ */ jsx45(MessageAttachmentsContainer, {}),
|
|
2439
|
+
actionBar: !isRunning ? /* @__PURE__ */ jsx45(UserMessageActionBar2, {}) : void 0,
|
|
2440
|
+
children: /* @__PURE__ */ jsx45(MessagePrimitive5.Parts, { components: { Text: AssistantTextContainer } })
|
|
2441
|
+
}
|
|
2442
|
+
) });
|
|
2443
|
+
}
|
|
2444
|
+
|
|
2445
|
+
// src/containers/ThreadContainer.tsx
|
|
2446
|
+
import { jsx as jsx46, jsxs as jsxs26 } from "react/jsx-runtime";
|
|
2447
|
+
var isNewChatView = (s) => s.thread.messages.length === 0 && (!s.thread.isLoading || s.threads.isLoading);
|
|
2448
|
+
function ThreadMessage({ isEditing }) {
|
|
2449
|
+
const role = useAuiState8((s) => s.message.role);
|
|
2450
|
+
if (role === "user") {
|
|
2451
|
+
if (isEditing) {
|
|
2452
|
+
return /* @__PURE__ */ jsx46(UserEditComposerContainer, {});
|
|
2453
|
+
}
|
|
2454
|
+
return /* @__PURE__ */ jsx46(UserMessageContainer, {});
|
|
2455
|
+
}
|
|
2456
|
+
return /* @__PURE__ */ jsx46(AssistantMessageContainer, {});
|
|
2457
|
+
}
|
|
2458
|
+
function ThreadContainer({ composer }) {
|
|
2459
|
+
const ThreadRootShell2 = useSlot("ThreadRootShell");
|
|
2460
|
+
const ThreadViewportShell2 = useSlot("ThreadViewportShell");
|
|
2461
|
+
const ThreadComposerAreaShell2 = useSlot("ThreadComposerAreaShell");
|
|
2462
|
+
const MessageGroup2 = useSlot("MessageGroup");
|
|
2463
|
+
const WelcomeScreen2 = useSlot("WelcomeScreen");
|
|
2464
|
+
const MessageListSkeleton2 = useSlot("MessageListSkeleton");
|
|
2465
|
+
const ScrollToBottomButton2 = useSlot("ScrollToBottomButton");
|
|
2466
|
+
const isEmpty = useAuiState8(isNewChatView);
|
|
2467
|
+
const isLoading = useAuiState8((s) => s.thread.isLoading);
|
|
2468
|
+
return /* @__PURE__ */ jsx46(ComposerBusyProvider, { children: /* @__PURE__ */ jsx46(ThreadPrimitive.Root, { asChild: true, children: /* @__PURE__ */ jsxs26(ThreadRootShell2, { children: [
|
|
2469
|
+
/* @__PURE__ */ jsx46(ThreadPrimitive.Viewport, { asChild: true, turnAnchor: "top", autoScroll: true, children: /* @__PURE__ */ jsxs26(ThreadViewportShell2, { isEmpty, children: [
|
|
2470
|
+
isEmpty && /* @__PURE__ */ jsx46(WelcomeScreen2, {}),
|
|
2471
|
+
isLoading ? /* @__PURE__ */ jsx46(MessageListSkeleton2, {}) : /* @__PURE__ */ jsx46(MessageGroup2, { children: /* @__PURE__ */ jsx46(ThreadPrimitive.Messages, { children: ({ message }) => /* @__PURE__ */ jsx46(
|
|
2472
|
+
ThreadMessage,
|
|
2473
|
+
{
|
|
2474
|
+
isEditing: message.role === "user" && message.composer.isEditing
|
|
2475
|
+
}
|
|
2476
|
+
) }) })
|
|
2477
|
+
] }) }),
|
|
2478
|
+
!isLoading && /* @__PURE__ */ jsxs26(ThreadComposerAreaShell2, { isEmpty, children: [
|
|
2479
|
+
/* @__PURE__ */ jsx46(ThreadPrimitive.ScrollToBottom, { asChild: true, children: /* @__PURE__ */ jsx46(ScrollToBottomButton2, {}) }),
|
|
2480
|
+
composer
|
|
2481
|
+
] })
|
|
2482
|
+
] }) }) });
|
|
2483
|
+
}
|
|
2484
|
+
|
|
2485
|
+
// src/containers/ComposerContainer.tsx
|
|
2486
|
+
import { useRef } from "react";
|
|
2487
|
+
import { useAui as useAui4, useAuiState as useAuiState9 } from "@assistant-ui/react";
|
|
2488
|
+
import { useTrueFoundryCancel, useTrueFoundryToolResponses as useTrueFoundryToolResponses2 } from "@truefoundry/assistant-ui-runtime";
|
|
2489
|
+
|
|
2490
|
+
// src/containers/AskUserContainer.tsx
|
|
2491
|
+
import { useState as useState10 } from "react";
|
|
2492
|
+
import { useTrueFoundryToolResponses } from "@truefoundry/assistant-ui-runtime";
|
|
2493
|
+
import { useThreadIsRunning as useThreadIsRunning5 } from "@assistant-ui/core/react";
|
|
2494
|
+
import { jsx as jsx47 } from "react/jsx-runtime";
|
|
2495
|
+
var OTHER_OPTION_ID2 = "__other";
|
|
2496
|
+
function AskUserContainer() {
|
|
2497
|
+
const AskUserPrompt2 = useSlot("AskUserPrompt");
|
|
2498
|
+
const { pending, respond } = useTrueFoundryToolResponses();
|
|
2499
|
+
const isRunning = useThreadIsRunning5();
|
|
2500
|
+
const [selectedOptionId, setSelectedOptionId] = useState10(void 0);
|
|
2501
|
+
const [otherValue, setOtherValue] = useState10("");
|
|
2502
|
+
const item = pending[0];
|
|
2503
|
+
if (item == null) return null;
|
|
2504
|
+
const options = (item.options ?? []).map((option) => ({ id: option, label: option }));
|
|
2505
|
+
const allowOther = options.length === 0;
|
|
2506
|
+
const onSubmit = () => {
|
|
2507
|
+
const content = selectedOptionId != null && selectedOptionId !== OTHER_OPTION_ID2 ? options.find((o) => o.id === selectedOptionId)?.label ?? "" : otherValue.trim();
|
|
2508
|
+
if (!content) return;
|
|
2509
|
+
respond({ toolCallId: item.toolCallId, content });
|
|
2510
|
+
setSelectedOptionId(void 0);
|
|
2511
|
+
setOtherValue("");
|
|
2512
|
+
};
|
|
2513
|
+
return /* @__PURE__ */ jsx47(
|
|
2514
|
+
AskUserPrompt2,
|
|
2515
|
+
{
|
|
2516
|
+
question: item.question ?? "Answer required",
|
|
2517
|
+
options,
|
|
2518
|
+
allowOther,
|
|
2519
|
+
selectedOptionId,
|
|
2520
|
+
otherValue,
|
|
2521
|
+
disabled: isRunning,
|
|
2522
|
+
onSelectOption: setSelectedOptionId,
|
|
2523
|
+
onOtherValueChange: setOtherValue,
|
|
2524
|
+
onSubmit
|
|
2525
|
+
}
|
|
2526
|
+
);
|
|
2527
|
+
}
|
|
2528
|
+
|
|
2529
|
+
// src/containers/McpAuthContainer.tsx
|
|
2530
|
+
import { useTrueFoundryMcpAuth } from "@truefoundry/assistant-ui-runtime";
|
|
2531
|
+
import { useThreadIsRunning as useThreadIsRunning6 } from "@assistant-ui/core/react";
|
|
2532
|
+
import { jsx as jsx48 } from "react/jsx-runtime";
|
|
2533
|
+
function McpAuthContainer() {
|
|
2534
|
+
const McpAuthPrompt2 = useSlot("McpAuthPrompt");
|
|
2535
|
+
const { pending, resume } = useTrueFoundryMcpAuth();
|
|
2536
|
+
const isRunning = useThreadIsRunning6();
|
|
2537
|
+
if (!pending) return null;
|
|
2538
|
+
return /* @__PURE__ */ jsx48(
|
|
2539
|
+
McpAuthPrompt2,
|
|
2540
|
+
{
|
|
2541
|
+
servers: pending.mcpServers,
|
|
2542
|
+
disabled: isRunning,
|
|
2543
|
+
onContinue: () => void resume()
|
|
2544
|
+
}
|
|
2545
|
+
);
|
|
2546
|
+
}
|
|
2547
|
+
|
|
2548
|
+
// src/containers/ComposerContainer.tsx
|
|
2549
|
+
import { Fragment as Fragment3, jsx as jsx49, jsxs as jsxs27 } from "react/jsx-runtime";
|
|
2550
|
+
var threadHasPendingMcpAuth = (s) => {
|
|
2551
|
+
const messages = s.thread.messages;
|
|
2552
|
+
const last = messages[messages.length - 1];
|
|
2553
|
+
if (last?.role !== "assistant") return false;
|
|
2554
|
+
if (last.status?.type !== "requires-action") return false;
|
|
2555
|
+
return last.metadata?.custom?.pendingMcpAuth === true;
|
|
2556
|
+
};
|
|
2557
|
+
function ComposerContainer() {
|
|
2558
|
+
const ComposerShell2 = useSlot("ComposerShell");
|
|
2559
|
+
const aui = useAui4();
|
|
2560
|
+
const text = useAuiState9((s) => s.composer.text);
|
|
2561
|
+
const { isBusy, send, resetBusy } = useComposerBusyState();
|
|
2562
|
+
const mcpPending = useAuiState9(threadHasPendingMcpAuth);
|
|
2563
|
+
const { pending: toolResponsesPending } = useTrueFoundryToolResponses2();
|
|
2564
|
+
const cancel = useTrueFoundryCancel();
|
|
2565
|
+
const fileInputRef = useRef(null);
|
|
2566
|
+
if (mcpPending) {
|
|
2567
|
+
return /* @__PURE__ */ jsx49(McpAuthContainer, {});
|
|
2568
|
+
}
|
|
2569
|
+
if (toolResponsesPending.length > 0) {
|
|
2570
|
+
return /* @__PURE__ */ jsx49(AskUserContainer, {});
|
|
2571
|
+
}
|
|
2572
|
+
return /* @__PURE__ */ jsxs27(Fragment3, { children: [
|
|
2573
|
+
/* @__PURE__ */ jsx49(
|
|
2574
|
+
"input",
|
|
2575
|
+
{
|
|
2576
|
+
ref: fileInputRef,
|
|
2577
|
+
type: "file",
|
|
2578
|
+
hidden: true,
|
|
2579
|
+
onChange: (event) => {
|
|
2580
|
+
const file = event.target.files?.[0];
|
|
2581
|
+
if (file) void aui.composer().addAttachment(file);
|
|
2582
|
+
event.target.value = "";
|
|
2583
|
+
}
|
|
2584
|
+
}
|
|
2585
|
+
),
|
|
2586
|
+
/* @__PURE__ */ jsx49(
|
|
2587
|
+
ComposerShell2,
|
|
2588
|
+
{
|
|
2589
|
+
attachments: /* @__PURE__ */ jsx49(ComposerAttachmentsContainer, {}),
|
|
2590
|
+
value: text,
|
|
2591
|
+
placeholder: "Ask anything... (Shift+Enter for new line)",
|
|
2592
|
+
disabled: isBusy,
|
|
2593
|
+
isRunning: isBusy,
|
|
2594
|
+
onValueChange: (value) => aui.composer().setText(value),
|
|
2595
|
+
onSubmit: () => send(() => aui.composer().send()),
|
|
2596
|
+
onCancel: () => {
|
|
2597
|
+
resetBusy();
|
|
2598
|
+
void cancel();
|
|
2599
|
+
},
|
|
2600
|
+
onAttach: () => fileInputRef.current?.click()
|
|
2601
|
+
}
|
|
2602
|
+
)
|
|
2603
|
+
] });
|
|
2604
|
+
}
|
|
2605
|
+
|
|
2606
|
+
// src/containers/ThreadListContainer.tsx
|
|
2607
|
+
import { useAui as useAui5, useAuiState as useAuiState10 } from "@assistant-ui/react";
|
|
2608
|
+
import { jsx as jsx50, jsxs as jsxs28 } from "react/jsx-runtime";
|
|
2609
|
+
function ThreadListContainer() {
|
|
2610
|
+
const ThreadListShell2 = useSlot("ThreadListShell");
|
|
2611
|
+
const ThreadListNewButton2 = useSlot("ThreadListNewButton");
|
|
2612
|
+
const ThreadListRow2 = useSlot("ThreadListRow");
|
|
2613
|
+
const ThreadListRowSkeleton2 = useSlot("ThreadListRowSkeleton");
|
|
2614
|
+
const ThreadListEmptyState2 = useSlot("ThreadListEmptyState");
|
|
2615
|
+
const Button2 = useSlot("Button");
|
|
2616
|
+
const aui = useAui5();
|
|
2617
|
+
const isLoading = useAuiState10((s) => s.threads.isLoading);
|
|
2618
|
+
const isLoadingMore = useAuiState10((s) => s.threads.isLoadingMore);
|
|
2619
|
+
const hasMore = useAuiState10((s) => s.threads.hasMore);
|
|
2620
|
+
const threadIds = useAuiState10((s) => s.threads.threadIds);
|
|
2621
|
+
const threadItems = useAuiState10((s) => s.threads.threadItems);
|
|
2622
|
+
const mainThreadId = useAuiState10((s) => s.threads.mainThreadId);
|
|
2623
|
+
const itemsById = new Map(threadItems.map((item) => [item.id, item]));
|
|
2624
|
+
return /* @__PURE__ */ jsxs28(ThreadListShell2, { header: /* @__PURE__ */ jsx50(ThreadListNewButton2, { onClick: () => aui.threads().switchToNewThread() }), children: [
|
|
2625
|
+
isLoading ? /* @__PURE__ */ jsx50(ThreadListRowSkeleton2, {}) : threadIds.length === 0 ? /* @__PURE__ */ jsx50(ThreadListEmptyState2, {}) : threadIds.map((id) => {
|
|
2626
|
+
const item = itemsById.get(id);
|
|
2627
|
+
return /* @__PURE__ */ jsx50(
|
|
2628
|
+
ThreadListRow2,
|
|
2629
|
+
{
|
|
2630
|
+
title: item?.title ?? "New Chat",
|
|
2631
|
+
active: id === mainThreadId,
|
|
2632
|
+
onSelect: () => aui.threads().switchToThread(id),
|
|
2633
|
+
onArchive: () => aui.threads().item({ id }).archive(),
|
|
2634
|
+
onDelete: () => aui.threads().item({ id }).delete()
|
|
2635
|
+
},
|
|
2636
|
+
id
|
|
2637
|
+
);
|
|
2638
|
+
}),
|
|
2639
|
+
!isLoading && hasMore && (isLoadingMore ? /* @__PURE__ */ jsx50(ThreadListRowSkeleton2, { count: 1 }) : /* @__PURE__ */ jsx50(Button2, { variant: "ghost", onClick: () => void aui.threads().loadMore(), children: "Load more" }))
|
|
2640
|
+
] });
|
|
2641
|
+
}
|
|
2642
|
+
|
|
2643
|
+
// src/containers/Thread.tsx
|
|
2644
|
+
import { jsx as jsx51 } from "react/jsx-runtime";
|
|
2645
|
+
function Thread() {
|
|
2646
|
+
return /* @__PURE__ */ jsx51(ThreadContainer, { composer: /* @__PURE__ */ jsx51(ComposerContainer, {}) });
|
|
2647
|
+
}
|
|
2648
|
+
export {
|
|
2649
|
+
AskUserContainer,
|
|
2650
|
+
AskUserPrompt,
|
|
2651
|
+
AssistantMessageContainer,
|
|
2652
|
+
AssistantTextContainer,
|
|
2653
|
+
AttachmentCard,
|
|
2654
|
+
AttachmentPickerButton,
|
|
2655
|
+
AttachmentPreviewDialog,
|
|
2656
|
+
Avatar,
|
|
2657
|
+
AvatarFallback,
|
|
2658
|
+
AvatarImage,
|
|
2659
|
+
BranchIndicator,
|
|
2660
|
+
Button,
|
|
2661
|
+
CodeBlockHeader,
|
|
2662
|
+
Collapsible,
|
|
2663
|
+
CollapsibleContent,
|
|
2664
|
+
CollapsibleTrigger,
|
|
2665
|
+
ComposerAttachmentPickerContainer,
|
|
2666
|
+
ComposerAttachmentsContainer,
|
|
2667
|
+
ComposerBusyProvider,
|
|
2668
|
+
ComposerContainer,
|
|
2669
|
+
ComposerShell,
|
|
2670
|
+
Dialog,
|
|
2671
|
+
DialogClose,
|
|
2672
|
+
DialogContent,
|
|
2673
|
+
DialogDescription,
|
|
2674
|
+
DialogFooter,
|
|
2675
|
+
DialogHeader,
|
|
2676
|
+
DialogOverlay,
|
|
2677
|
+
DialogPortal,
|
|
2678
|
+
DialogTitle,
|
|
2679
|
+
DialogTrigger,
|
|
2680
|
+
ErrorToasterProvider,
|
|
2681
|
+
IconButton,
|
|
2682
|
+
Markdown,
|
|
2683
|
+
McpAuthContainer,
|
|
2684
|
+
McpAuthPrompt,
|
|
2685
|
+
MessageActionBar,
|
|
2686
|
+
MessageAttachmentsContainer,
|
|
2687
|
+
MessageBubble,
|
|
2688
|
+
MessageErrorBanner,
|
|
2689
|
+
MessageGroup,
|
|
2690
|
+
MessageIndicator,
|
|
2691
|
+
MessageListSkeleton,
|
|
2692
|
+
OpenUIBlock,
|
|
2693
|
+
ReasoningCard,
|
|
2694
|
+
ReasoningContainer,
|
|
2695
|
+
SandboxArtifactList,
|
|
2696
|
+
ScrollToBottomButton,
|
|
2697
|
+
Skeleton,
|
|
2698
|
+
SlotsProvider,
|
|
2699
|
+
Thread,
|
|
2700
|
+
ThreadComposerAreaShell,
|
|
2701
|
+
ThreadContainer,
|
|
2702
|
+
ThreadListContainer,
|
|
2703
|
+
ThreadListEmptyState,
|
|
2704
|
+
ThreadListNewButton,
|
|
2705
|
+
ThreadListRow,
|
|
2706
|
+
ThreadListRowSkeleton,
|
|
2707
|
+
ThreadListShell,
|
|
2708
|
+
ThreadRootShell,
|
|
2709
|
+
ThreadViewportShell,
|
|
2710
|
+
Toast,
|
|
2711
|
+
ToastStack,
|
|
2712
|
+
TokensProvider,
|
|
2713
|
+
ToolApprovalBar,
|
|
2714
|
+
ToolCallCard,
|
|
2715
|
+
ToolCallContainer,
|
|
2716
|
+
ToolGroupCard,
|
|
2717
|
+
ToolGroupContainer,
|
|
2718
|
+
Tooltip,
|
|
2719
|
+
TooltipContent,
|
|
2720
|
+
TooltipProvider,
|
|
2721
|
+
TooltipTrigger,
|
|
2722
|
+
USER_MESSAGE_ATTACHMENT_PREVIEW_REM,
|
|
2723
|
+
UserEditComposerContainer,
|
|
2724
|
+
UserMessageActionBar,
|
|
2725
|
+
UserMessageContainer,
|
|
2726
|
+
WelcomeScreen,
|
|
2727
|
+
buttonVariants,
|
|
2728
|
+
defaultSlots,
|
|
2729
|
+
defaultTokens,
|
|
2730
|
+
useComposerBusyState,
|
|
2731
|
+
useErrorToaster,
|
|
2732
|
+
useErrorToasterOptional,
|
|
2733
|
+
useSlot,
|
|
2734
|
+
useTokens
|
|
2735
|
+
};
|
|
2736
|
+
//# sourceMappingURL=index.js.map
|