@tinkrapp/widget 1.0.0 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/course-ai-widget.global.js +119 -119
- package/dist/course-ai-widget.global.js.map +1 -1
- package/dist/react.cjs +1289 -1286
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +1 -1
- package/dist/react.d.ts +1 -1
- package/dist/react.js +996 -993
- package/dist/react.js.map +1 -1
- package/package.json +79 -2
package/dist/react.js
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
import * as
|
|
2
|
-
import { forwardRef, memo,
|
|
1
|
+
import * as React2 from 'react';
|
|
2
|
+
import { createContext, forwardRef, memo, useRef, useState, useCallback, useImperativeHandle, useEffect, useMemo, useContext } from 'react';
|
|
3
3
|
import { makeAssistantToolUI, useComposerRuntime, ThreadPrimitive, AssistantIf, ComposerPrimitive, MessagePrimitive, ActionBarPrimitive, BranchPickerPrimitive, ThreadListPrimitive, ThreadListItemPrimitive, useAssistantState, unstable_useRemoteThreadListRuntime, AssistantRuntimeProvider, ErrorPrimitive, useMessage, useAssistantApi, AttachmentPrimitive } from '@assistant-ui/react';
|
|
4
4
|
import { AssistantChatTransport, useChatRuntime } from '@assistant-ui/react-ai-sdk';
|
|
5
5
|
import { CacheProvider, ThemeProvider } from '@emotion/react';
|
|
6
6
|
import { createAssistantStream } from 'assistant-stream';
|
|
7
|
-
import
|
|
8
|
-
import
|
|
9
|
-
import {
|
|
7
|
+
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
8
|
+
import styled from '@emotion/styled';
|
|
9
|
+
import { motion, AnimatePresence } from 'motion/react';
|
|
10
|
+
import { FileTextIcon, ChevronUpIcon, ChevronDownIcon, CheckIcon, CopyIcon, ExternalLinkIcon, Loader2Icon, BarChart3Icon, PresentationIcon, HelpCircleIcon, LayersIcon, NetworkIcon, VideoIcon, HeadphonesIcon, DownloadIcon, XCircleIcon, ArrowDownIcon, MessageSquareTextIcon, PodcastIcon, BadgeQuestionMarkIcon, WalletCardsIcon, AtSignIcon, GlobeIcon, ArrowUpIcon, SquareIcon, RefreshCwIcon, PencilIcon, ChevronLeftIcon, ChevronRightIcon, PlusIcon, MessageSquareIcon, ArchiveIcon, Trash2Icon, ArchiveRestoreIcon, EditIcon, LayoutIcon, Minimize2Icon, BotIcon, LoaderIcon, LinkIcon, FileIcon, XIcon, PaperclipIcon, PanelLeftIcon, Maximize2Icon, FileText } from 'lucide-react';
|
|
10
11
|
import { clsx } from 'clsx';
|
|
11
12
|
import { twMerge } from 'tailwind-merge';
|
|
13
|
+
import ReactMarkdown from 'react-markdown';
|
|
14
|
+
import remarkGfm from 'remark-gfm';
|
|
12
15
|
import { Slot, Slottable } from '@radix-ui/react-slot';
|
|
13
16
|
import * as TooltipPrimitive from '@radix-ui/react-tooltip';
|
|
14
|
-
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
15
17
|
import { cva } from 'class-variance-authority';
|
|
16
|
-
import styled from '@emotion/styled';
|
|
17
|
-
import { motion, AnimatePresence } from 'motion/react';
|
|
18
18
|
import { useShallow } from 'zustand/shallow';
|
|
19
19
|
import * as DialogPrimitive from '@radix-ui/react-dialog';
|
|
20
20
|
import * as AvatarPrimitive from '@radix-ui/react-avatar';
|
|
@@ -249,557 +249,143 @@ var WidgetClient = class {
|
|
|
249
249
|
this.events.emit("state:change", { previous, current: newState });
|
|
250
250
|
}
|
|
251
251
|
};
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
252
|
+
var MessageContext = createContext(null);
|
|
253
|
+
function MessageContextProvider({ children }) {
|
|
254
|
+
const [selectedContext, setSelectedContext] = useState([]);
|
|
255
|
+
const addContextItem = useCallback((item) => {
|
|
256
|
+
console.log("[MessageContext] Adding context item:", item.id, item.title);
|
|
257
|
+
setSelectedContext((prev2) => {
|
|
258
|
+
if (prev2.some((i) => i.id === item.id)) {
|
|
259
|
+
console.log("[MessageContext] Item already exists, skipping");
|
|
260
|
+
return prev2;
|
|
261
|
+
}
|
|
262
|
+
console.log("[MessageContext] Context items count:", prev2.length + 1);
|
|
263
|
+
return [...prev2, item];
|
|
264
|
+
});
|
|
265
|
+
}, []);
|
|
266
|
+
const removeContextItem = useCallback((id) => {
|
|
267
|
+
setSelectedContext((prev2) => prev2.filter((item) => item.id !== id));
|
|
268
|
+
}, []);
|
|
269
|
+
const clearContext = useCallback(() => {
|
|
270
|
+
console.log("[MessageContext] Clearing context");
|
|
271
|
+
setSelectedContext([]);
|
|
272
|
+
}, []);
|
|
273
|
+
const setContext = useCallback((items) => {
|
|
274
|
+
setSelectedContext(items);
|
|
275
|
+
}, []);
|
|
276
|
+
const consumeContext = useCallback(() => {
|
|
277
|
+
const context = selectedContext;
|
|
278
|
+
console.log("[MessageContext] Consuming context:", context.length, "items");
|
|
279
|
+
return context;
|
|
280
|
+
}, [selectedContext]);
|
|
259
281
|
return /* @__PURE__ */ jsx(
|
|
260
|
-
|
|
282
|
+
MessageContext.Provider,
|
|
261
283
|
{
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
284
|
+
value: {
|
|
285
|
+
selectedContext,
|
|
286
|
+
addContextItem,
|
|
287
|
+
removeContextItem,
|
|
288
|
+
clearContext,
|
|
289
|
+
setContext,
|
|
290
|
+
consumeContext
|
|
291
|
+
},
|
|
292
|
+
children
|
|
265
293
|
}
|
|
266
294
|
);
|
|
267
295
|
}
|
|
268
|
-
function
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
return /* @__PURE__ */ jsx(TooltipPrimitive.Trigger, { "data-slot": "tooltip-trigger", ...props });
|
|
277
|
-
}
|
|
278
|
-
function TooltipContent({
|
|
279
|
-
className,
|
|
280
|
-
sideOffset = 0,
|
|
281
|
-
children,
|
|
282
|
-
...props
|
|
283
|
-
}) {
|
|
284
|
-
return /* @__PURE__ */ jsx(TooltipPrimitive.Portal, { children: /* @__PURE__ */ jsxs(
|
|
285
|
-
TooltipPrimitive.Content,
|
|
286
|
-
{
|
|
287
|
-
"data-slot": "tooltip-content",
|
|
288
|
-
sideOffset,
|
|
289
|
-
className: cn(
|
|
290
|
-
"bg-foreground text-background animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 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 w-fit origin-(--radix-tooltip-content-transform-origin) rounded-md px-3 py-1.5 text-xs text-balance",
|
|
291
|
-
className
|
|
292
|
-
),
|
|
293
|
-
...props,
|
|
294
|
-
children: [
|
|
295
|
-
children,
|
|
296
|
-
/* @__PURE__ */ jsx(TooltipPrimitive.Arrow, { className: "bg-foreground fill-foreground z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px]" })
|
|
297
|
-
]
|
|
298
|
-
}
|
|
299
|
-
) });
|
|
296
|
+
function useMessageContext() {
|
|
297
|
+
const context = useContext(MessageContext);
|
|
298
|
+
if (!context) {
|
|
299
|
+
throw new Error(
|
|
300
|
+
"useMessageContext must be used within a MessageContextProvider"
|
|
301
|
+
);
|
|
302
|
+
}
|
|
303
|
+
return context;
|
|
300
304
|
}
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
|
|
310
|
-
ghost: "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
|
|
311
|
-
link: "text-primary underline-offset-4 hover:underline"
|
|
312
|
-
},
|
|
313
|
-
size: {
|
|
314
|
-
default: "h-9 px-4 py-2 has-[>svg]:px-3",
|
|
315
|
-
sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5",
|
|
316
|
-
lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
|
|
317
|
-
icon: "size-9",
|
|
318
|
-
"icon-sm": "size-8",
|
|
319
|
-
"icon-lg": "size-10"
|
|
320
|
-
}
|
|
305
|
+
|
|
306
|
+
// src/react/styles/theme.ts
|
|
307
|
+
var theme = {
|
|
308
|
+
colors: {
|
|
309
|
+
background: {
|
|
310
|
+
primary: "#1a1a1a",
|
|
311
|
+
secondary: "#2a2a2a",
|
|
312
|
+
tertiary: "#3a3a3a"
|
|
321
313
|
},
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
314
|
+
accent: {
|
|
315
|
+
primary: "#c9a227",
|
|
316
|
+
hover: "#d4af37",
|
|
317
|
+
muted: "rgba(201, 162, 39, 0.4)"
|
|
318
|
+
},
|
|
319
|
+
text: {
|
|
320
|
+
primary: "#ffffff",
|
|
321
|
+
secondary: "#888888",
|
|
322
|
+
tertiary: "#cccccc",
|
|
323
|
+
inverse: "#1a1a1a"
|
|
324
|
+
},
|
|
325
|
+
border: "#2a2a2a",
|
|
326
|
+
shadow: "rgba(0, 0, 0, 0.4)"
|
|
327
|
+
},
|
|
328
|
+
spacing: {
|
|
329
|
+
xs: "0.25rem",
|
|
330
|
+
sm: "0.5rem",
|
|
331
|
+
md: "1rem",
|
|
332
|
+
lg: "1.5rem",
|
|
333
|
+
xl: "2rem",
|
|
334
|
+
"2xl": "3rem"
|
|
335
|
+
},
|
|
336
|
+
radii: {
|
|
337
|
+
sm: "0.5rem",
|
|
338
|
+
md: "0.75rem",
|
|
339
|
+
lg: "1rem",
|
|
340
|
+
xl: "1.5rem",
|
|
341
|
+
full: "50%"
|
|
342
|
+
},
|
|
343
|
+
typography: {
|
|
344
|
+
fontFamily: "system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif",
|
|
345
|
+
fontSize: {
|
|
346
|
+
xs: "0.75rem",
|
|
347
|
+
sm: "0.875rem",
|
|
348
|
+
md: "1rem",
|
|
349
|
+
lg: "1.125rem",
|
|
350
|
+
xl: "1.25rem",
|
|
351
|
+
"2xl": "1.5rem"
|
|
352
|
+
},
|
|
353
|
+
fontWeight: {
|
|
354
|
+
normal: 400,
|
|
355
|
+
medium: 500,
|
|
356
|
+
semibold: 600,
|
|
357
|
+
bold: 700
|
|
358
|
+
},
|
|
359
|
+
lineHeight: {
|
|
360
|
+
tight: 1.25,
|
|
361
|
+
normal: 1.5,
|
|
362
|
+
relaxed: 1.7
|
|
325
363
|
}
|
|
364
|
+
},
|
|
365
|
+
zIndex: {
|
|
366
|
+
widget: 9999,
|
|
367
|
+
overlay: 9998
|
|
368
|
+
},
|
|
369
|
+
shadows: {
|
|
370
|
+
sm: "0 2px 8px rgba(0, 0, 0, 0.2)",
|
|
371
|
+
md: "0 4px 16px rgba(0, 0, 0, 0.3)",
|
|
372
|
+
lg: "0 8px 32px rgba(0, 0, 0, 0.4)",
|
|
373
|
+
accent: "0 4px 16px rgba(201, 162, 39, 0.4)",
|
|
374
|
+
accentHover: "0 6px 20px rgba(201, 162, 39, 0.5)"
|
|
375
|
+
},
|
|
376
|
+
transitions: {
|
|
377
|
+
fast: "0.15s ease",
|
|
378
|
+
normal: "0.2s ease",
|
|
379
|
+
slow: "0.3s ease"
|
|
326
380
|
}
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
"data-variant": variant,
|
|
336
|
-
"data-size": size,
|
|
337
|
-
className: cn(buttonVariants({ variant, size, className })),
|
|
338
|
-
...props
|
|
339
|
-
}
|
|
340
|
-
);
|
|
341
|
-
});
|
|
342
|
-
Button.displayName = "Button";
|
|
343
|
-
var TooltipIconButton = forwardRef(({ children, tooltip, side = "bottom", className, ...rest }, ref) => {
|
|
344
|
-
return /* @__PURE__ */ jsxs(Tooltip, { children: [
|
|
345
|
-
/* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(Button, { variant: "ghost", size: "icon-sm", ...rest, ref, children: [
|
|
346
|
-
/* @__PURE__ */ jsx(Slottable, { children }),
|
|
347
|
-
/* @__PURE__ */ jsx("span", { className: "aui-sr-only sr-only", children: tooltip })
|
|
348
|
-
] }) }),
|
|
349
|
-
/* @__PURE__ */ jsx(TooltipContent, { side, children: tooltip })
|
|
350
|
-
] });
|
|
351
|
-
});
|
|
352
|
-
TooltipIconButton.displayName = "TooltipIconButton";
|
|
353
|
-
var ToolCard = ({
|
|
354
|
-
title,
|
|
355
|
-
subtitle,
|
|
356
|
-
isStreaming,
|
|
357
|
-
isError = false,
|
|
358
|
-
icon,
|
|
359
|
-
persistentContent,
|
|
360
|
-
children,
|
|
361
|
-
footer
|
|
362
|
-
}) => {
|
|
363
|
-
const [manualExpanded, setManualExpanded] = useState(null);
|
|
364
|
-
const prevStreamingRef = useRef(isStreaming);
|
|
365
|
-
const contentRef = useRef(null);
|
|
366
|
-
const isExpanded = manualExpanded ?? isStreaming;
|
|
367
|
-
useEffect(() => {
|
|
368
|
-
if (isStreaming && !prevStreamingRef.current) {
|
|
369
|
-
setManualExpanded(null);
|
|
370
|
-
}
|
|
371
|
-
prevStreamingRef.current = isStreaming;
|
|
372
|
-
}, [isStreaming]);
|
|
373
|
-
useEffect(() => {
|
|
374
|
-
if (isStreaming && contentRef.current) {
|
|
375
|
-
contentRef.current.scrollTop = contentRef.current.scrollHeight;
|
|
376
|
-
}
|
|
377
|
-
});
|
|
378
|
-
const renderIcon = () => {
|
|
379
|
-
if (icon) return icon;
|
|
380
|
-
const iconClass = cn("h-4 w-4", isStreaming && "animate-spin");
|
|
381
|
-
if (isStreaming) {
|
|
382
|
-
return /* @__PURE__ */ jsx(Loader2Icon, { className: iconClass });
|
|
383
|
-
}
|
|
384
|
-
if (isError) {
|
|
385
|
-
return /* @__PURE__ */ jsx(XCircleIcon, { className: "h-4 w-4 text-red-400" });
|
|
386
|
-
}
|
|
387
|
-
return /* @__PURE__ */ jsx(CheckIcon, { className: "h-4 w-4" });
|
|
388
|
-
};
|
|
389
|
-
const handleToggle = () => {
|
|
390
|
-
if (!isStreaming) {
|
|
391
|
-
setManualExpanded((prev2) => prev2 === null ? true : !prev2);
|
|
392
|
-
}
|
|
393
|
-
};
|
|
394
|
-
return /* @__PURE__ */ jsxs("div", { className: "my-2 overflow-hidden rounded-xl border border-border shadow-sm", children: [
|
|
395
|
-
/* @__PURE__ */ jsxs(
|
|
396
|
-
"div",
|
|
397
|
-
{
|
|
398
|
-
className: cn(
|
|
399
|
-
"flex items-center gap-2 p-2 cursor-pointer transition-colors text-white bg-primary-foreground",
|
|
400
|
-
!isStreaming && "hover:opacity-90"
|
|
401
|
-
),
|
|
402
|
-
onClick: handleToggle,
|
|
403
|
-
children: [
|
|
404
|
-
/* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: renderIcon() }),
|
|
405
|
-
/* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
406
|
-
subtitle && /* @__PURE__ */ jsx("p", { className: "font-medium opacity-80 leading-tight text-xs text-muted-foreground", children: subtitle }),
|
|
407
|
-
/* @__PURE__ */ jsx("h4", { className: "truncate font-semibold leading-tight text-sm text-muted-foreground", children: title })
|
|
408
|
-
] }),
|
|
409
|
-
/* @__PURE__ */ jsx(
|
|
410
|
-
"button",
|
|
411
|
-
{
|
|
412
|
-
className: "p-1 rounded hover:bg-white/20 transition-colors",
|
|
413
|
-
"aria-label": isExpanded ? "Collapse" : "Expand",
|
|
414
|
-
onClick: (e) => {
|
|
415
|
-
e.stopPropagation();
|
|
416
|
-
handleToggle();
|
|
417
|
-
},
|
|
418
|
-
children: isExpanded ? /* @__PURE__ */ jsx(ChevronUpIcon, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx(ChevronDownIcon, { className: "h-4 w-4" })
|
|
419
|
-
}
|
|
420
|
-
)
|
|
421
|
-
]
|
|
422
|
-
}
|
|
423
|
-
),
|
|
424
|
-
persistentContent,
|
|
425
|
-
isExpanded && /* @__PURE__ */ jsx(
|
|
426
|
-
"div",
|
|
427
|
-
{
|
|
428
|
-
ref: contentRef,
|
|
429
|
-
className: "p-2 max-h-[400px] overflow-y-auto bg-secondary",
|
|
430
|
-
children
|
|
431
|
-
}
|
|
432
|
-
),
|
|
433
|
-
isExpanded && footer && /* @__PURE__ */ jsx("div", { className: "flex items-center justify-end gap-2 border-t border-white/10 p-2 bg-primary-foreground/80", children: footer })
|
|
434
|
-
] });
|
|
435
|
-
};
|
|
436
|
-
var useCopyToClipboard = ({
|
|
437
|
-
copiedDuration = 3e3
|
|
438
|
-
} = {}) => {
|
|
439
|
-
const [isCopied, setIsCopied] = useState(false);
|
|
440
|
-
const copyToClipboard = (value) => {
|
|
441
|
-
if (!value) return;
|
|
442
|
-
navigator.clipboard.writeText(value).then(() => {
|
|
443
|
-
setIsCopied(true);
|
|
444
|
-
setTimeout(() => setIsCopied(false), copiedDuration);
|
|
445
|
-
});
|
|
446
|
-
};
|
|
447
|
-
return { isCopied, copyToClipboard };
|
|
448
|
-
};
|
|
449
|
-
var MarkdownContent = memo(({ content }) => {
|
|
450
|
-
return /* @__PURE__ */ jsx("div", { className: "aui-md max-w-none text-white", children: /* @__PURE__ */ jsx(
|
|
451
|
-
ReactMarkdown,
|
|
452
|
-
{
|
|
453
|
-
remarkPlugins: [remarkGfm],
|
|
454
|
-
components: {
|
|
455
|
-
h1: ({ className, ...props }) => /* @__PURE__ */ jsx(
|
|
456
|
-
"h1",
|
|
457
|
-
{
|
|
458
|
-
className: cn(
|
|
459
|
-
"mb-2 font-extrabold tracking-tight last:mb-0 text-white",
|
|
460
|
-
className
|
|
461
|
-
),
|
|
462
|
-
style: { fontSize: "12px" },
|
|
463
|
-
...props
|
|
464
|
-
}
|
|
465
|
-
),
|
|
466
|
-
h2: ({ className, ...props }) => /* @__PURE__ */ jsx(
|
|
467
|
-
"h2",
|
|
468
|
-
{
|
|
469
|
-
className: cn(
|
|
470
|
-
"mt-3 mb-1.5 font-semibold tracking-tight first:mt-0 last:mb-0 text-white",
|
|
471
|
-
className
|
|
472
|
-
),
|
|
473
|
-
style: { fontSize: "10px" },
|
|
474
|
-
...props
|
|
475
|
-
}
|
|
476
|
-
),
|
|
477
|
-
h3: ({ className, ...props }) => /* @__PURE__ */ jsx(
|
|
478
|
-
"h3",
|
|
479
|
-
{
|
|
480
|
-
className: cn(
|
|
481
|
-
"mt-2 mb-1 font-semibold tracking-tight first:mt-0 last:mb-0 text-white",
|
|
482
|
-
className
|
|
483
|
-
),
|
|
484
|
-
style: { fontSize: "9px" },
|
|
485
|
-
...props
|
|
486
|
-
}
|
|
487
|
-
),
|
|
488
|
-
p: ({ className, ...props }) => /* @__PURE__ */ jsx(
|
|
489
|
-
"p",
|
|
490
|
-
{
|
|
491
|
-
className: cn(
|
|
492
|
-
"mt-1.5 mb-1.5 leading-relaxed first:mt-0 last:mb-0 text-white/90",
|
|
493
|
-
className
|
|
494
|
-
),
|
|
495
|
-
...props
|
|
496
|
-
}
|
|
497
|
-
),
|
|
498
|
-
ul: ({ className, ...props }) => /* @__PURE__ */ jsx(
|
|
499
|
-
"ul",
|
|
500
|
-
{
|
|
501
|
-
className: cn(
|
|
502
|
-
"my-1.5 ml-3 list-disc [&>li]:mt-0.5 text-white/90",
|
|
503
|
-
className
|
|
504
|
-
),
|
|
505
|
-
...props
|
|
506
|
-
}
|
|
507
|
-
),
|
|
508
|
-
ol: ({ className, ...props }) => /* @__PURE__ */ jsx(
|
|
509
|
-
"ol",
|
|
510
|
-
{
|
|
511
|
-
className: cn(
|
|
512
|
-
"my-1.5 ml-3 list-decimal [&>li]:mt-0.5 text-white/90",
|
|
513
|
-
className
|
|
514
|
-
),
|
|
515
|
-
...props
|
|
516
|
-
}
|
|
517
|
-
),
|
|
518
|
-
blockquote: ({ className, ...props }) => /* @__PURE__ */ jsx(
|
|
519
|
-
"blockquote",
|
|
520
|
-
{
|
|
521
|
-
className: cn(
|
|
522
|
-
"border-l-2 border-white/30 pl-2 italic text-white/70",
|
|
523
|
-
className
|
|
524
|
-
),
|
|
525
|
-
...props
|
|
526
|
-
}
|
|
527
|
-
),
|
|
528
|
-
pre: ({ className, ...props }) => /* @__PURE__ */ jsx(
|
|
529
|
-
"pre",
|
|
530
|
-
{
|
|
531
|
-
className: cn(
|
|
532
|
-
"overflow-x-auto rounded bg-black/30 p-1.5 text-white/90 my-1.5",
|
|
533
|
-
className
|
|
534
|
-
),
|
|
535
|
-
...props
|
|
536
|
-
}
|
|
537
|
-
),
|
|
538
|
-
code: ({ className, ...props }) => {
|
|
539
|
-
const isInline = !className?.includes("language-");
|
|
540
|
-
return /* @__PURE__ */ jsx(
|
|
541
|
-
"code",
|
|
542
|
-
{
|
|
543
|
-
className: cn(
|
|
544
|
-
isInline && "rounded bg-black/30 px-0.5 py-0.5 font-mono text-white/90",
|
|
545
|
-
className
|
|
546
|
-
),
|
|
547
|
-
...props
|
|
548
|
-
}
|
|
549
|
-
);
|
|
550
|
-
},
|
|
551
|
-
a: ({ className, ...props }) => /* @__PURE__ */ jsx(
|
|
552
|
-
"a",
|
|
553
|
-
{
|
|
554
|
-
className: cn(
|
|
555
|
-
"font-medium text-blue-300 underline underline-offset-2",
|
|
556
|
-
className
|
|
557
|
-
),
|
|
558
|
-
target: "_blank",
|
|
559
|
-
rel: "noopener noreferrer",
|
|
560
|
-
...props
|
|
561
|
-
}
|
|
562
|
-
),
|
|
563
|
-
hr: ({ className, ...props }) => /* @__PURE__ */ jsx(
|
|
564
|
-
"hr",
|
|
565
|
-
{
|
|
566
|
-
className: cn("my-2 border-b border-white/20", className),
|
|
567
|
-
...props
|
|
568
|
-
}
|
|
569
|
-
)
|
|
570
|
-
},
|
|
571
|
-
children: content
|
|
572
|
-
}
|
|
573
|
-
) });
|
|
574
|
-
});
|
|
575
|
-
MarkdownContent.displayName = "MarkdownContent";
|
|
576
|
-
var DetailedAnswerToolUI = makeAssistantToolUI({
|
|
577
|
-
toolName: "generateDetailedAnswer",
|
|
578
|
-
render: function DetailedAnswerUI({ args, result, status }) {
|
|
579
|
-
const { isCopied, copyToClipboard } = useCopyToClipboard();
|
|
580
|
-
const isStreaming = status.type === "running";
|
|
581
|
-
const isError = status.type === "incomplete";
|
|
582
|
-
const title = result?.title || args.title || "Generating...";
|
|
583
|
-
const content = result?.content || args.content || "";
|
|
584
|
-
const summary = result?.summary || args.summary || "";
|
|
585
|
-
const handleCopy = () => {
|
|
586
|
-
if (content) {
|
|
587
|
-
copyToClipboard(content);
|
|
588
|
-
}
|
|
589
|
-
};
|
|
590
|
-
const handleOpenFullScreen = () => {
|
|
591
|
-
const newWindow = window.open("", "_blank");
|
|
592
|
-
if (newWindow) {
|
|
593
|
-
newWindow.document.write(`
|
|
594
|
-
<!DOCTYPE html>
|
|
595
|
-
<html>
|
|
596
|
-
<head>
|
|
597
|
-
<title>${title}</title>
|
|
598
|
-
<meta charset="utf-8">
|
|
599
|
-
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
600
|
-
<style>
|
|
601
|
-
body {
|
|
602
|
-
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
|
|
603
|
-
max-width: 800px;
|
|
604
|
-
margin: 0 auto;
|
|
605
|
-
padding: 2rem;
|
|
606
|
-
line-height: 1.6;
|
|
607
|
-
color: #1a1a1a;
|
|
608
|
-
}
|
|
609
|
-
h1 { border-bottom: 1px solid #eee; padding-bottom: 0.5rem; }
|
|
610
|
-
pre { background: #f5f5f5; padding: 1rem; overflow-x: auto; border-radius: 4px; }
|
|
611
|
-
code { background: #f5f5f5; padding: 0.2em 0.4em; border-radius: 3px; font-size: 0.9em; }
|
|
612
|
-
pre code { background: none; padding: 0; }
|
|
613
|
-
blockquote { border-left: 4px solid #ddd; margin: 0; padding-left: 1rem; color: #666; }
|
|
614
|
-
</style>
|
|
615
|
-
</head>
|
|
616
|
-
<body>
|
|
617
|
-
<h1>${title}</h1>
|
|
618
|
-
<div id="content">${content.replace(/</g, "<").replace(/>/g, ">")}</div>
|
|
619
|
-
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
|
|
620
|
-
<script>
|
|
621
|
-
document.getElementById('content').innerHTML = marked.parse(${JSON.stringify(
|
|
622
|
-
content
|
|
623
|
-
)});
|
|
624
|
-
</script>
|
|
625
|
-
</body>
|
|
626
|
-
</html>
|
|
627
|
-
`);
|
|
628
|
-
newWindow.document.close();
|
|
629
|
-
}
|
|
630
|
-
};
|
|
631
|
-
const persistentSummary = summary ? /* @__PURE__ */ jsx("div", { className: "p-2 text-white/80 border-b border-white/10 bg-primary-foreground text-xs", children: summary }) : void 0;
|
|
632
|
-
const footerActions = content ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
633
|
-
/* @__PURE__ */ jsx(
|
|
634
|
-
TooltipIconButton,
|
|
635
|
-
{
|
|
636
|
-
tooltip: isCopied ? "Copied!" : "Copy markdown",
|
|
637
|
-
onClick: handleCopy,
|
|
638
|
-
className: "flex items-center justify-center rounded-md p-1.5 text-white/70 hover:bg-white/10 transition-colors",
|
|
639
|
-
children: isCopied ? /* @__PURE__ */ jsx(CheckIcon, { className: "h-3.5 w-3.5" }) : /* @__PURE__ */ jsx(CopyIcon, { className: "h-3.5 w-3.5" })
|
|
640
|
-
}
|
|
641
|
-
),
|
|
642
|
-
/* @__PURE__ */ jsx(
|
|
643
|
-
TooltipIconButton,
|
|
644
|
-
{
|
|
645
|
-
tooltip: "Open in new window",
|
|
646
|
-
onClick: handleOpenFullScreen,
|
|
647
|
-
className: "flex items-center justify-center rounded-md p-1.5 text-white/70 hover:bg-white/10 transition-colors",
|
|
648
|
-
children: /* @__PURE__ */ jsx(ExternalLinkIcon, { className: "h-3.5 w-3.5" })
|
|
649
|
-
}
|
|
650
|
-
)
|
|
651
|
-
] }) : void 0;
|
|
652
|
-
return /* @__PURE__ */ jsx(
|
|
653
|
-
ToolCard,
|
|
654
|
-
{
|
|
655
|
-
title,
|
|
656
|
-
isStreaming,
|
|
657
|
-
isError,
|
|
658
|
-
icon: !isStreaming && !isError ? /* @__PURE__ */ jsx(FileTextIcon, { className: "h-4 w-4" }) : void 0,
|
|
659
|
-
persistentContent: persistentSummary,
|
|
660
|
-
footer: footerActions,
|
|
661
|
-
children: content ? /* @__PURE__ */ jsx(MarkdownContent, { content }) : /* @__PURE__ */ jsx("p", { className: "text-muted-foreground italic", children: "Generating content..." })
|
|
662
|
-
}
|
|
663
|
-
);
|
|
664
|
-
}
|
|
665
|
-
});
|
|
666
|
-
var MessageContext = createContext(null);
|
|
667
|
-
function MessageContextProvider({ children }) {
|
|
668
|
-
const [selectedContext, setSelectedContext] = useState([]);
|
|
669
|
-
const addContextItem = useCallback((item) => {
|
|
670
|
-
console.log("[MessageContext] Adding context item:", item.id, item.title);
|
|
671
|
-
setSelectedContext((prev2) => {
|
|
672
|
-
if (prev2.some((i) => i.id === item.id)) {
|
|
673
|
-
console.log("[MessageContext] Item already exists, skipping");
|
|
674
|
-
return prev2;
|
|
675
|
-
}
|
|
676
|
-
console.log("[MessageContext] Context items count:", prev2.length + 1);
|
|
677
|
-
return [...prev2, item];
|
|
678
|
-
});
|
|
679
|
-
}, []);
|
|
680
|
-
const removeContextItem = useCallback((id) => {
|
|
681
|
-
setSelectedContext((prev2) => prev2.filter((item) => item.id !== id));
|
|
682
|
-
}, []);
|
|
683
|
-
const clearContext = useCallback(() => {
|
|
684
|
-
console.log("[MessageContext] Clearing context");
|
|
685
|
-
setSelectedContext([]);
|
|
686
|
-
}, []);
|
|
687
|
-
const setContext = useCallback((items) => {
|
|
688
|
-
setSelectedContext(items);
|
|
689
|
-
}, []);
|
|
690
|
-
const consumeContext = useCallback(() => {
|
|
691
|
-
const context = selectedContext;
|
|
692
|
-
console.log("[MessageContext] Consuming context:", context.length, "items");
|
|
693
|
-
return context;
|
|
694
|
-
}, [selectedContext]);
|
|
695
|
-
return /* @__PURE__ */ jsx(
|
|
696
|
-
MessageContext.Provider,
|
|
697
|
-
{
|
|
698
|
-
value: {
|
|
699
|
-
selectedContext,
|
|
700
|
-
addContextItem,
|
|
701
|
-
removeContextItem,
|
|
702
|
-
clearContext,
|
|
703
|
-
setContext,
|
|
704
|
-
consumeContext
|
|
705
|
-
},
|
|
706
|
-
children
|
|
707
|
-
}
|
|
708
|
-
);
|
|
709
|
-
}
|
|
710
|
-
function useMessageContext() {
|
|
711
|
-
const context = useContext(MessageContext);
|
|
712
|
-
if (!context) {
|
|
713
|
-
throw new Error(
|
|
714
|
-
"useMessageContext must be used within a MessageContextProvider"
|
|
715
|
-
);
|
|
716
|
-
}
|
|
717
|
-
return context;
|
|
718
|
-
}
|
|
719
|
-
|
|
720
|
-
// src/react/styles/theme.ts
|
|
721
|
-
var theme = {
|
|
722
|
-
colors: {
|
|
723
|
-
background: {
|
|
724
|
-
primary: "#1a1a1a",
|
|
725
|
-
secondary: "#2a2a2a",
|
|
726
|
-
tertiary: "#3a3a3a"
|
|
727
|
-
},
|
|
728
|
-
accent: {
|
|
729
|
-
primary: "#c9a227",
|
|
730
|
-
hover: "#d4af37",
|
|
731
|
-
muted: "rgba(201, 162, 39, 0.4)"
|
|
732
|
-
},
|
|
733
|
-
text: {
|
|
734
|
-
primary: "#ffffff",
|
|
735
|
-
secondary: "#888888",
|
|
736
|
-
tertiary: "#cccccc",
|
|
737
|
-
inverse: "#1a1a1a"
|
|
738
|
-
},
|
|
739
|
-
border: "#2a2a2a",
|
|
740
|
-
shadow: "rgba(0, 0, 0, 0.4)"
|
|
741
|
-
},
|
|
742
|
-
spacing: {
|
|
743
|
-
xs: "0.25rem",
|
|
744
|
-
sm: "0.5rem",
|
|
745
|
-
md: "1rem",
|
|
746
|
-
lg: "1.5rem",
|
|
747
|
-
xl: "2rem",
|
|
748
|
-
"2xl": "3rem"
|
|
749
|
-
},
|
|
750
|
-
radii: {
|
|
751
|
-
sm: "0.5rem",
|
|
752
|
-
md: "0.75rem",
|
|
753
|
-
lg: "1rem",
|
|
754
|
-
xl: "1.5rem",
|
|
755
|
-
full: "50%"
|
|
756
|
-
},
|
|
757
|
-
typography: {
|
|
758
|
-
fontFamily: "system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif",
|
|
759
|
-
fontSize: {
|
|
760
|
-
xs: "0.75rem",
|
|
761
|
-
sm: "0.875rem",
|
|
762
|
-
md: "1rem",
|
|
763
|
-
lg: "1.125rem",
|
|
764
|
-
xl: "1.25rem",
|
|
765
|
-
"2xl": "1.5rem"
|
|
766
|
-
},
|
|
767
|
-
fontWeight: {
|
|
768
|
-
normal: 400,
|
|
769
|
-
medium: 500,
|
|
770
|
-
semibold: 600,
|
|
771
|
-
bold: 700
|
|
772
|
-
},
|
|
773
|
-
lineHeight: {
|
|
774
|
-
tight: 1.25,
|
|
775
|
-
normal: 1.5,
|
|
776
|
-
relaxed: 1.7
|
|
777
|
-
}
|
|
778
|
-
},
|
|
779
|
-
zIndex: {
|
|
780
|
-
widget: 9999,
|
|
781
|
-
overlay: 9998
|
|
782
|
-
},
|
|
783
|
-
shadows: {
|
|
784
|
-
sm: "0 2px 8px rgba(0, 0, 0, 0.2)",
|
|
785
|
-
md: "0 4px 16px rgba(0, 0, 0, 0.3)",
|
|
786
|
-
lg: "0 8px 32px rgba(0, 0, 0, 0.4)",
|
|
787
|
-
accent: "0 4px 16px rgba(201, 162, 39, 0.4)",
|
|
788
|
-
accentHover: "0 6px 20px rgba(201, 162, 39, 0.5)"
|
|
789
|
-
},
|
|
790
|
-
transitions: {
|
|
791
|
-
fast: "0.15s ease",
|
|
792
|
-
normal: "0.2s ease",
|
|
793
|
-
slow: "0.3s ease"
|
|
794
|
-
}
|
|
795
|
-
};
|
|
796
|
-
function sheetForTag(tag) {
|
|
797
|
-
if (tag.sheet) {
|
|
798
|
-
return tag.sheet;
|
|
799
|
-
}
|
|
800
|
-
for (var i = 0; i < document.styleSheets.length; i++) {
|
|
801
|
-
if (document.styleSheets[i].ownerNode === tag) {
|
|
802
|
-
return document.styleSheets[i];
|
|
381
|
+
};
|
|
382
|
+
function sheetForTag(tag) {
|
|
383
|
+
if (tag.sheet) {
|
|
384
|
+
return tag.sheet;
|
|
385
|
+
}
|
|
386
|
+
for (var i = 0; i < document.styleSheets.length; i++) {
|
|
387
|
+
if (document.styleSheets[i].ownerNode === tag) {
|
|
388
|
+
return document.styleSheets[i];
|
|
803
389
|
}
|
|
804
390
|
}
|
|
805
391
|
return void 0;
|
|
@@ -2133,342 +1719,881 @@ function createThreadListAdapter(baseUrl, userId, assistantId) {
|
|
|
2133
1719
|
console.error("[Threads] Rename error:", error);
|
|
2134
1720
|
}
|
|
2135
1721
|
},
|
|
2136
|
-
// Archive a thread
|
|
2137
|
-
async archive(remoteId) {
|
|
2138
|
-
try {
|
|
2139
|
-
await fetch(`${baseUrl}/api/widget/threads/${remoteId}/archive`, {
|
|
2140
|
-
method: "POST",
|
|
2141
|
-
headers
|
|
2142
|
-
});
|
|
2143
|
-
} catch (error) {
|
|
2144
|
-
console.error("[Threads] Archive error:", error);
|
|
1722
|
+
// Archive a thread
|
|
1723
|
+
async archive(remoteId) {
|
|
1724
|
+
try {
|
|
1725
|
+
await fetch(`${baseUrl}/api/widget/threads/${remoteId}/archive`, {
|
|
1726
|
+
method: "POST",
|
|
1727
|
+
headers
|
|
1728
|
+
});
|
|
1729
|
+
} catch (error) {
|
|
1730
|
+
console.error("[Threads] Archive error:", error);
|
|
1731
|
+
}
|
|
1732
|
+
},
|
|
1733
|
+
// Unarchive a thread
|
|
1734
|
+
async unarchive(remoteId) {
|
|
1735
|
+
try {
|
|
1736
|
+
await fetch(`${baseUrl}/api/widget/threads/${remoteId}/unarchive`, {
|
|
1737
|
+
method: "POST",
|
|
1738
|
+
headers
|
|
1739
|
+
});
|
|
1740
|
+
} catch (error) {
|
|
1741
|
+
console.error("[Threads] Unarchive error:", error);
|
|
1742
|
+
}
|
|
1743
|
+
},
|
|
1744
|
+
// Delete a thread
|
|
1745
|
+
async delete(remoteId) {
|
|
1746
|
+
try {
|
|
1747
|
+
await fetch(`${baseUrl}/api/widget/threads/${remoteId}`, {
|
|
1748
|
+
method: "DELETE",
|
|
1749
|
+
headers
|
|
1750
|
+
});
|
|
1751
|
+
} catch (error) {
|
|
1752
|
+
console.error("[Threads] Delete error:", error);
|
|
1753
|
+
}
|
|
1754
|
+
},
|
|
1755
|
+
// Generate a title from messages
|
|
1756
|
+
async generateTitle(remoteId, messages) {
|
|
1757
|
+
return createAssistantStream(async (controller) => {
|
|
1758
|
+
try {
|
|
1759
|
+
const response = await fetch(
|
|
1760
|
+
`${baseUrl}/api/widget/threads/${remoteId}/title`,
|
|
1761
|
+
{
|
|
1762
|
+
method: "POST",
|
|
1763
|
+
headers,
|
|
1764
|
+
body: JSON.stringify({ messages })
|
|
1765
|
+
}
|
|
1766
|
+
);
|
|
1767
|
+
if (!response.ok) {
|
|
1768
|
+
throw new Error(`Title generation failed: ${response.status}`);
|
|
1769
|
+
}
|
|
1770
|
+
const data = await response.json();
|
|
1771
|
+
controller.appendText(data.title);
|
|
1772
|
+
controller.close();
|
|
1773
|
+
} catch (error) {
|
|
1774
|
+
console.error("[Threads] Title generation error:", error);
|
|
1775
|
+
controller.appendText("New Chat");
|
|
1776
|
+
controller.close();
|
|
1777
|
+
}
|
|
1778
|
+
});
|
|
1779
|
+
}
|
|
1780
|
+
};
|
|
1781
|
+
}
|
|
1782
|
+
async function saveMessages(baseUrl, userId, assistantId, threadId, messages) {
|
|
1783
|
+
try {
|
|
1784
|
+
const response = await fetch(
|
|
1785
|
+
`${baseUrl}/api/widget/threads/${threadId}/messages/sync`,
|
|
1786
|
+
{
|
|
1787
|
+
method: "POST",
|
|
1788
|
+
headers: createApiHeaders(userId, assistantId),
|
|
1789
|
+
body: JSON.stringify({ messages })
|
|
1790
|
+
}
|
|
1791
|
+
);
|
|
1792
|
+
if (!response.ok) {
|
|
1793
|
+
console.error("[Messages] Sync failed:", response.status);
|
|
1794
|
+
}
|
|
1795
|
+
} catch (error) {
|
|
1796
|
+
console.error("[Messages] Sync error:", error);
|
|
1797
|
+
}
|
|
1798
|
+
}
|
|
1799
|
+
function createHistoryAdapter(baseUrl, userId, assistantId, remoteId) {
|
|
1800
|
+
const headers = createApiHeaders(userId, assistantId);
|
|
1801
|
+
return {
|
|
1802
|
+
async load() {
|
|
1803
|
+
console.log("[History] load() called, remoteId:", remoteId);
|
|
1804
|
+
if (!remoteId) return { headId: null, messages: [] };
|
|
1805
|
+
try {
|
|
1806
|
+
const response = await fetch(
|
|
1807
|
+
`${baseUrl}/api/widget/threads/${remoteId}/messages`,
|
|
1808
|
+
{ headers }
|
|
1809
|
+
);
|
|
1810
|
+
if (!response.ok) {
|
|
1811
|
+
console.error("[History] Failed to load messages:", response.status);
|
|
1812
|
+
return { headId: null, messages: [] };
|
|
1813
|
+
}
|
|
1814
|
+
const { messages } = await response.json();
|
|
1815
|
+
console.log("[History] Loaded messages:", messages.length);
|
|
1816
|
+
const formattedMessages = messages.map(
|
|
1817
|
+
(m, index) => ({
|
|
1818
|
+
parentId: index > 0 ? messages[index - 1].id : null,
|
|
1819
|
+
message: {
|
|
1820
|
+
id: m.id,
|
|
1821
|
+
role: m.role,
|
|
1822
|
+
parts: m.content,
|
|
1823
|
+
metadata: m.metadata,
|
|
1824
|
+
createdAt: new Date(m.createdAt)
|
|
1825
|
+
}
|
|
1826
|
+
})
|
|
1827
|
+
);
|
|
1828
|
+
console.log("[History] Formatted messages:", formattedMessages.length);
|
|
1829
|
+
return {
|
|
1830
|
+
headId: messages.length > 0 ? messages[messages.length - 1].id : null,
|
|
1831
|
+
messages: formattedMessages
|
|
1832
|
+
};
|
|
1833
|
+
} catch (error) {
|
|
1834
|
+
console.error("[History] Load error:", error);
|
|
1835
|
+
return { headId: null, messages: [] };
|
|
1836
|
+
}
|
|
1837
|
+
},
|
|
1838
|
+
async append(message) {
|
|
1839
|
+
console.log("[History] append() called");
|
|
1840
|
+
},
|
|
1841
|
+
// Required by useExternalHistory in @assistant-ui/react-ai-sdk
|
|
1842
|
+
withFormat(_formatAdapter) {
|
|
1843
|
+
console.log("[History.withFormat] called, remoteId:", remoteId);
|
|
1844
|
+
return {
|
|
1845
|
+
async load() {
|
|
1846
|
+
if (!remoteId) return { headId: null, messages: [] };
|
|
1847
|
+
try {
|
|
1848
|
+
const response = await fetch(
|
|
1849
|
+
`${baseUrl}/api/widget/threads/${remoteId}/messages`,
|
|
1850
|
+
{ headers }
|
|
1851
|
+
);
|
|
1852
|
+
if (!response.ok) {
|
|
1853
|
+
console.error("[History.withFormat] Failed:", response.status);
|
|
1854
|
+
return { headId: null, messages: [] };
|
|
1855
|
+
}
|
|
1856
|
+
const { messages } = await response.json();
|
|
1857
|
+
console.log("[History.withFormat] Loaded:", messages.length);
|
|
1858
|
+
const formattedMessages = messages.map(
|
|
1859
|
+
(m, index) => ({
|
|
1860
|
+
parentId: index > 0 ? messages[index - 1].id : null,
|
|
1861
|
+
message: {
|
|
1862
|
+
id: m.id,
|
|
1863
|
+
role: m.role,
|
|
1864
|
+
parts: m.content,
|
|
1865
|
+
metadata: m.metadata,
|
|
1866
|
+
createdAt: new Date(m.createdAt)
|
|
1867
|
+
}
|
|
1868
|
+
})
|
|
1869
|
+
);
|
|
1870
|
+
return {
|
|
1871
|
+
headId: messages.length > 0 ? messages[messages.length - 1].id : null,
|
|
1872
|
+
messages: formattedMessages
|
|
1873
|
+
};
|
|
1874
|
+
} catch (error) {
|
|
1875
|
+
console.error("[History.withFormat] Error:", error);
|
|
1876
|
+
return { headId: null, messages: [] };
|
|
1877
|
+
}
|
|
1878
|
+
},
|
|
1879
|
+
async append(_item) {
|
|
1880
|
+
}
|
|
1881
|
+
};
|
|
1882
|
+
}
|
|
1883
|
+
};
|
|
1884
|
+
}
|
|
1885
|
+
function AssistantRuntimeWrapper({
|
|
1886
|
+
config,
|
|
1887
|
+
userId,
|
|
1888
|
+
children
|
|
1889
|
+
}) {
|
|
1890
|
+
const baseUrl = config.baseUrl || "http://localhost:3000";
|
|
1891
|
+
const assistantId = config.apiKey;
|
|
1892
|
+
const { consumeContext, clearContext } = useMessageContext();
|
|
1893
|
+
const contextRef = useRef(consumeContext);
|
|
1894
|
+
contextRef.current = consumeContext;
|
|
1895
|
+
const clearContextRef = useRef(clearContext);
|
|
1896
|
+
clearContextRef.current = clearContext;
|
|
1897
|
+
const threadListAdapter = useMemo(
|
|
1898
|
+
() => createThreadListAdapter(baseUrl, userId, assistantId),
|
|
1899
|
+
[baseUrl, userId, assistantId]
|
|
1900
|
+
);
|
|
1901
|
+
const runtime = unstable_useRemoteThreadListRuntime({
|
|
1902
|
+
runtimeHook: function useChatThreadRuntime() {
|
|
1903
|
+
const threadId = useAssistantState(
|
|
1904
|
+
({ threadListItem }) => threadListItem?.remoteId ?? void 0
|
|
1905
|
+
);
|
|
1906
|
+
const threadIdRef = useRef(threadId);
|
|
1907
|
+
threadIdRef.current = threadId;
|
|
1908
|
+
const history = useMemo(
|
|
1909
|
+
() => createHistoryAdapter(baseUrl, userId, assistantId, threadId),
|
|
1910
|
+
[threadId]
|
|
1911
|
+
);
|
|
1912
|
+
const transport = useMemo(() => {
|
|
1913
|
+
console.log("[Widget] Creating transport for threadId:", threadId);
|
|
1914
|
+
return new AssistantChatTransport({
|
|
1915
|
+
api: `${baseUrl}/api/widget/chat`,
|
|
1916
|
+
headers: {
|
|
1917
|
+
"X-User-Id": userId,
|
|
1918
|
+
"X-Assistant-Id": assistantId
|
|
1919
|
+
},
|
|
1920
|
+
// Use body as a function to dynamically include context
|
|
1921
|
+
body: () => {
|
|
1922
|
+
const currentContext = contextRef.current();
|
|
1923
|
+
const contextIds = currentContext.map((item) => item.id);
|
|
1924
|
+
const contextMetadata = currentContext.map((item) => ({
|
|
1925
|
+
id: item.id,
|
|
1926
|
+
type: item.type,
|
|
1927
|
+
title: item.title
|
|
1928
|
+
}));
|
|
1929
|
+
console.log(
|
|
1930
|
+
"[Widget] Transport body - contextIds:",
|
|
1931
|
+
contextIds.length,
|
|
1932
|
+
"threadId:",
|
|
1933
|
+
threadId
|
|
1934
|
+
);
|
|
1935
|
+
if (contextIds.length > 0) {
|
|
1936
|
+
setTimeout(() => clearContextRef.current(), 0);
|
|
1937
|
+
}
|
|
1938
|
+
return {
|
|
1939
|
+
assistantId,
|
|
1940
|
+
threadId,
|
|
1941
|
+
...contextIds.length > 0 && { contextIds, contextMetadata }
|
|
1942
|
+
};
|
|
1943
|
+
}
|
|
1944
|
+
});
|
|
1945
|
+
}, [threadId]);
|
|
1946
|
+
const runtime2 = useChatRuntime({
|
|
1947
|
+
transport,
|
|
1948
|
+
adapters: { history },
|
|
1949
|
+
onFinish: ({ message, messages }) => {
|
|
1950
|
+
const currentThreadId = threadIdRef.current;
|
|
1951
|
+
console.log(
|
|
1952
|
+
"[Widget] onFinish - threadId:",
|
|
1953
|
+
currentThreadId,
|
|
1954
|
+
"messages:",
|
|
1955
|
+
messages.length
|
|
1956
|
+
);
|
|
1957
|
+
if (currentThreadId && messages.length > 0) {
|
|
1958
|
+
saveMessages(
|
|
1959
|
+
baseUrl,
|
|
1960
|
+
userId,
|
|
1961
|
+
assistantId,
|
|
1962
|
+
currentThreadId,
|
|
1963
|
+
messages
|
|
1964
|
+
);
|
|
1965
|
+
}
|
|
1966
|
+
}
|
|
1967
|
+
});
|
|
1968
|
+
return runtime2;
|
|
1969
|
+
},
|
|
1970
|
+
adapter: threadListAdapter
|
|
1971
|
+
});
|
|
1972
|
+
return /* @__PURE__ */ jsx(AssistantRuntimeProvider, { runtime, children });
|
|
1973
|
+
}
|
|
1974
|
+
function WidgetProvider({
|
|
1975
|
+
config,
|
|
1976
|
+
children,
|
|
1977
|
+
autoInitialize = true
|
|
1978
|
+
}) {
|
|
1979
|
+
const [userId] = useState(() => config.userId || generateUserId());
|
|
1980
|
+
const [client] = useState(() => new WidgetClient(config));
|
|
1981
|
+
const [state, setState] = useState(client.getState());
|
|
1982
|
+
useEffect(() => {
|
|
1983
|
+
const unsubscribe = client.on("state:change", ({ current }) => {
|
|
1984
|
+
setState(current);
|
|
1985
|
+
});
|
|
1986
|
+
if (autoInitialize && state.status === "idle") {
|
|
1987
|
+
client.initialize().catch(console.error);
|
|
1988
|
+
}
|
|
1989
|
+
return () => {
|
|
1990
|
+
unsubscribe();
|
|
1991
|
+
client.destroy();
|
|
1992
|
+
};
|
|
1993
|
+
}, [client, autoInitialize, state.status]);
|
|
1994
|
+
const contextValue = useMemo(
|
|
1995
|
+
() => ({ client, state, userId }),
|
|
1996
|
+
[client, state, userId]
|
|
1997
|
+
);
|
|
1998
|
+
return /* @__PURE__ */ jsx(CacheProvider, { value: widgetCache, children: /* @__PURE__ */ jsx(ThemeProvider, { theme, children: /* @__PURE__ */ jsx(WidgetContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx(MessageContextProvider, { children: /* @__PURE__ */ jsx(AssistantRuntimeWrapper, { config, userId, children }) }) }) }) });
|
|
1999
|
+
}
|
|
2000
|
+
function useWidget() {
|
|
2001
|
+
const context = useContext(WidgetContext);
|
|
2002
|
+
if (!context) {
|
|
2003
|
+
throw new Error("useWidget must be used within a WidgetProvider");
|
|
2004
|
+
}
|
|
2005
|
+
const { client, state } = context;
|
|
2006
|
+
const initialize = useCallback(async () => {
|
|
2007
|
+
if (state.status === "idle") {
|
|
2008
|
+
await client.initialize();
|
|
2009
|
+
}
|
|
2010
|
+
}, [client, state.status]);
|
|
2011
|
+
const sendMessage = useCallback(
|
|
2012
|
+
async (content) => {
|
|
2013
|
+
return client.sendMessage(content);
|
|
2014
|
+
},
|
|
2015
|
+
[client]
|
|
2016
|
+
);
|
|
2017
|
+
return {
|
|
2018
|
+
state,
|
|
2019
|
+
client,
|
|
2020
|
+
isIdle: state.status === "idle",
|
|
2021
|
+
isInitializing: state.status === "initializing",
|
|
2022
|
+
isReady: state.status === "ready",
|
|
2023
|
+
isLoading: state.status === "loading",
|
|
2024
|
+
isError: state.status === "error",
|
|
2025
|
+
messages: state.status === "ready" ? state.session.messages : [],
|
|
2026
|
+
error: state.status === "error" ? state.error : null,
|
|
2027
|
+
initialize,
|
|
2028
|
+
sendMessage
|
|
2029
|
+
};
|
|
2030
|
+
}
|
|
2031
|
+
function useChat() {
|
|
2032
|
+
const { sendMessage, messages, isLoading, isReady } = useWidget();
|
|
2033
|
+
const [input, setInput] = useState("");
|
|
2034
|
+
const handleSubmit = useCallback(
|
|
2035
|
+
async (e) => {
|
|
2036
|
+
e?.preventDefault();
|
|
2037
|
+
if (!input.trim() || !isReady || isLoading) {
|
|
2038
|
+
return;
|
|
2145
2039
|
}
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
async unarchive(remoteId) {
|
|
2040
|
+
const message = input.trim();
|
|
2041
|
+
setInput("");
|
|
2149
2042
|
try {
|
|
2150
|
-
await
|
|
2151
|
-
method: "POST",
|
|
2152
|
-
headers
|
|
2153
|
-
});
|
|
2043
|
+
await sendMessage(message);
|
|
2154
2044
|
} catch (error) {
|
|
2155
|
-
console.error("
|
|
2045
|
+
console.error("Failed to send message:", error);
|
|
2046
|
+
setInput(message);
|
|
2156
2047
|
}
|
|
2157
2048
|
},
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2049
|
+
[input, isReady, isLoading, sendMessage]
|
|
2050
|
+
);
|
|
2051
|
+
return {
|
|
2052
|
+
input,
|
|
2053
|
+
setInput,
|
|
2054
|
+
handleSubmit,
|
|
2055
|
+
messages,
|
|
2056
|
+
isLoading,
|
|
2057
|
+
canSubmit: isReady && !isLoading && input.trim().length > 0
|
|
2058
|
+
};
|
|
2059
|
+
}
|
|
2060
|
+
var ThreadListItem = () => {
|
|
2061
|
+
return /* @__PURE__ */ jsx(ThreadListItemPrimitive.Root, { className: "group relative flex items-center gap-2 px-2 py-1.5 hover:bg-muted/50 data-[active]:bg-muted cursor-pointer transition-colors rounded-sm", children: /* @__PURE__ */ jsx(ThreadListItemPrimitive.Trigger, { className: "flex flex-1 items-center gap-2 min-w-0", children: /* @__PURE__ */ jsx("span", { className: "truncate text-sm text-foreground", children: /* @__PURE__ */ jsx(ThreadListItemPrimitive.Title, { fallback: "New Chat" }) }) }) });
|
|
2062
|
+
};
|
|
2063
|
+
var ChatHistoryPopover = ({
|
|
2064
|
+
onSelectThread
|
|
2065
|
+
}) => {
|
|
2066
|
+
const handleThreadSelect = () => {
|
|
2067
|
+
onSelectThread?.();
|
|
2068
|
+
};
|
|
2069
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col", onClick: handleThreadSelect, children: [
|
|
2070
|
+
/* @__PURE__ */ jsx("div", { className: "px-2 py-1.5", children: /* @__PURE__ */ jsx(Text, { size: "xs", style: { color: "hsl(var(--muted-foreground))" }, children: "Previous 7 days" }) }),
|
|
2071
|
+
/* @__PURE__ */ jsx("div", { className: "max-h-[300px] overflow-y-auto", children: /* @__PURE__ */ jsx(
|
|
2072
|
+
ThreadListPrimitive.Items,
|
|
2073
|
+
{
|
|
2074
|
+
components: {
|
|
2075
|
+
ThreadListItem
|
|
2076
|
+
}
|
|
2167
2077
|
}
|
|
2168
|
-
}
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2078
|
+
) })
|
|
2079
|
+
] });
|
|
2080
|
+
};
|
|
2081
|
+
function cn(...inputs) {
|
|
2082
|
+
return twMerge(clsx(inputs));
|
|
2083
|
+
}
|
|
2084
|
+
var categoryIcons = {
|
|
2085
|
+
audio: HeadphonesIcon,
|
|
2086
|
+
"audio-overview": HeadphonesIcon,
|
|
2087
|
+
"video-overview": VideoIcon,
|
|
2088
|
+
"mind-map": NetworkIcon,
|
|
2089
|
+
reports: FileTextIcon,
|
|
2090
|
+
flashcards: LayersIcon,
|
|
2091
|
+
quiz: HelpCircleIcon,
|
|
2092
|
+
"slide-deck": PresentationIcon,
|
|
2093
|
+
infographic: BarChart3Icon
|
|
2094
|
+
};
|
|
2095
|
+
var categoryColors = {
|
|
2096
|
+
audio: "bg-purple-100 text-purple-700 dark:bg-purple-900/30 dark:text-purple-300",
|
|
2097
|
+
"audio-overview": "bg-purple-100 text-purple-700 dark:bg-purple-900/30 dark:text-purple-300",
|
|
2098
|
+
"video-overview": "bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-300",
|
|
2099
|
+
"mind-map": "bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-300",
|
|
2100
|
+
reports: "bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-300",
|
|
2101
|
+
flashcards: "bg-yellow-100 text-yellow-700 dark:bg-yellow-900/30 dark:text-yellow-300",
|
|
2102
|
+
quiz: "bg-orange-100 text-orange-700 dark:bg-orange-900/30 dark:text-orange-300",
|
|
2103
|
+
"slide-deck": "bg-indigo-100 text-indigo-700 dark:bg-indigo-900/30 dark:text-indigo-300",
|
|
2104
|
+
infographic: "bg-teal-100 text-teal-700 dark:bg-teal-900/30 dark:text-teal-300"
|
|
2105
|
+
};
|
|
2106
|
+
var categoryLabels = {
|
|
2107
|
+
audio: "Audio",
|
|
2108
|
+
"audio-overview": "Audio Overview",
|
|
2109
|
+
"video-overview": "Video Overview",
|
|
2110
|
+
"mind-map": "Mind Map",
|
|
2111
|
+
reports: "Report",
|
|
2112
|
+
flashcards: "Flashcards",
|
|
2113
|
+
quiz: "Quiz",
|
|
2114
|
+
"slide-deck": "Slide Deck",
|
|
2115
|
+
infographic: "Infographic"
|
|
2116
|
+
};
|
|
2117
|
+
var ArtifactCard = ({
|
|
2118
|
+
category,
|
|
2119
|
+
title,
|
|
2120
|
+
content,
|
|
2121
|
+
isLoading,
|
|
2122
|
+
children
|
|
2123
|
+
}) => {
|
|
2124
|
+
const Icon = categoryIcons[category];
|
|
2125
|
+
const colorClass = categoryColors[category];
|
|
2126
|
+
const label = categoryLabels[category];
|
|
2127
|
+
return /* @__PURE__ */ jsxs("div", { className: "my-3 overflow-hidden rounded-xl border border-border bg-card shadow-sm", children: [
|
|
2128
|
+
/* @__PURE__ */ jsxs("div", { className: cn("flex items-center gap-3 px-4 py-3", colorClass), children: [
|
|
2129
|
+
/* @__PURE__ */ jsx("div", { className: "flex h-8 w-8 items-center justify-center rounded-lg bg-white/50 dark:bg-black/20", children: isLoading ? /* @__PURE__ */ jsx(Loader2Icon, { className: "h-4 w-4 animate-spin" }) : /* @__PURE__ */ jsx(Icon, { className: "h-4 w-4" }) }),
|
|
2130
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
2131
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs font-medium opacity-80", children: label }),
|
|
2132
|
+
/* @__PURE__ */ jsx("h4", { className: "truncate font-semibold text-sm", children: title })
|
|
2133
|
+
] })
|
|
2134
|
+
] }),
|
|
2135
|
+
content && /* @__PURE__ */ jsx("div", { className: "px-4 py-3 text-sm text-muted-foreground", children: /* @__PURE__ */ jsx("div", { className: "line-clamp-4 whitespace-pre-wrap", children: content }) }),
|
|
2136
|
+
children,
|
|
2137
|
+
!isLoading && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-2 border-t border-border px-4 py-2", children: [
|
|
2138
|
+
/* @__PURE__ */ jsxs("button", { className: "flex items-center gap-1.5 rounded-md px-3 py-1.5 text-xs font-medium text-muted-foreground hover:bg-muted transition-colors", children: [
|
|
2139
|
+
/* @__PURE__ */ jsx(DownloadIcon, { className: "h-3 w-3" }),
|
|
2140
|
+
"Export"
|
|
2141
|
+
] }),
|
|
2142
|
+
/* @__PURE__ */ jsxs("button", { className: "flex items-center gap-1.5 rounded-md px-3 py-1.5 text-xs font-medium text-muted-foreground hover:bg-muted transition-colors", children: [
|
|
2143
|
+
/* @__PURE__ */ jsx(ExternalLinkIcon, { className: "h-3 w-3" }),
|
|
2144
|
+
"Open"
|
|
2145
|
+
] })
|
|
2146
|
+
] })
|
|
2147
|
+
] });
|
|
2148
|
+
};
|
|
2149
|
+
function createArtifactToolUI(category) {
|
|
2150
|
+
return makeAssistantToolUI({
|
|
2151
|
+
toolName: `create_${category.replace(/-/g, "_")}`,
|
|
2152
|
+
render: ({ args, result, status }) => {
|
|
2153
|
+
const isLoading = status.type === "running";
|
|
2154
|
+
return /* @__PURE__ */ jsx(
|
|
2155
|
+
ArtifactCard,
|
|
2156
|
+
{
|
|
2157
|
+
category,
|
|
2158
|
+
title: args.title || "Generating...",
|
|
2159
|
+
content: result?.content || args.content,
|
|
2160
|
+
isLoading
|
|
2191
2161
|
}
|
|
2192
|
-
|
|
2162
|
+
);
|
|
2193
2163
|
}
|
|
2194
|
-
};
|
|
2164
|
+
});
|
|
2165
|
+
}
|
|
2166
|
+
var AudioOverviewToolUI = createArtifactToolUI("audio-overview");
|
|
2167
|
+
var VideoOverviewToolUI = createArtifactToolUI("video-overview");
|
|
2168
|
+
var MindMapToolUI = createArtifactToolUI("mind-map");
|
|
2169
|
+
var ReportsToolUI = createArtifactToolUI("reports");
|
|
2170
|
+
var FlashcardsToolUI = createArtifactToolUI("flashcards");
|
|
2171
|
+
var QuizToolUI = createArtifactToolUI("quiz");
|
|
2172
|
+
var SlideDeckToolUI = createArtifactToolUI("slide-deck");
|
|
2173
|
+
var InfographicToolUI = createArtifactToolUI("infographic");
|
|
2174
|
+
var ArtifactToolUIs = () => {
|
|
2175
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2176
|
+
/* @__PURE__ */ jsx(AudioOverviewToolUI, {}),
|
|
2177
|
+
/* @__PURE__ */ jsx(VideoOverviewToolUI, {}),
|
|
2178
|
+
/* @__PURE__ */ jsx(MindMapToolUI, {}),
|
|
2179
|
+
/* @__PURE__ */ jsx(ReportsToolUI, {}),
|
|
2180
|
+
/* @__PURE__ */ jsx(FlashcardsToolUI, {}),
|
|
2181
|
+
/* @__PURE__ */ jsx(QuizToolUI, {}),
|
|
2182
|
+
/* @__PURE__ */ jsx(SlideDeckToolUI, {}),
|
|
2183
|
+
/* @__PURE__ */ jsx(InfographicToolUI, {})
|
|
2184
|
+
] });
|
|
2185
|
+
};
|
|
2186
|
+
function TooltipProvider({
|
|
2187
|
+
delayDuration = 0,
|
|
2188
|
+
...props
|
|
2189
|
+
}) {
|
|
2190
|
+
return /* @__PURE__ */ jsx(
|
|
2191
|
+
TooltipPrimitive.Provider,
|
|
2192
|
+
{
|
|
2193
|
+
"data-slot": "tooltip-provider",
|
|
2194
|
+
delayDuration,
|
|
2195
|
+
...props
|
|
2196
|
+
}
|
|
2197
|
+
);
|
|
2195
2198
|
}
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2199
|
+
function Tooltip({
|
|
2200
|
+
...props
|
|
2201
|
+
}) {
|
|
2202
|
+
return /* @__PURE__ */ jsx(TooltipProvider, { children: /* @__PURE__ */ jsx(TooltipPrimitive.Root, { "data-slot": "tooltip", ...props }) });
|
|
2203
|
+
}
|
|
2204
|
+
function TooltipTrigger({
|
|
2205
|
+
...props
|
|
2206
|
+
}) {
|
|
2207
|
+
return /* @__PURE__ */ jsx(TooltipPrimitive.Trigger, { "data-slot": "tooltip-trigger", ...props });
|
|
2208
|
+
}
|
|
2209
|
+
function TooltipContent({
|
|
2210
|
+
className,
|
|
2211
|
+
sideOffset = 0,
|
|
2212
|
+
children,
|
|
2213
|
+
...props
|
|
2214
|
+
}) {
|
|
2215
|
+
return /* @__PURE__ */ jsx(TooltipPrimitive.Portal, { children: /* @__PURE__ */ jsxs(
|
|
2216
|
+
TooltipPrimitive.Content,
|
|
2217
|
+
{
|
|
2218
|
+
"data-slot": "tooltip-content",
|
|
2219
|
+
sideOffset,
|
|
2220
|
+
className: cn(
|
|
2221
|
+
"bg-foreground text-background animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 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 w-fit origin-(--radix-tooltip-content-transform-origin) rounded-md px-3 py-1.5 text-xs text-balance",
|
|
2222
|
+
className
|
|
2223
|
+
),
|
|
2224
|
+
...props,
|
|
2225
|
+
children: [
|
|
2226
|
+
children,
|
|
2227
|
+
/* @__PURE__ */ jsx(TooltipPrimitive.Arrow, { className: "bg-foreground fill-foreground z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px]" })
|
|
2228
|
+
]
|
|
2208
2229
|
}
|
|
2209
|
-
}
|
|
2210
|
-
console.error("[Messages] Sync error:", error);
|
|
2211
|
-
}
|
|
2230
|
+
) });
|
|
2212
2231
|
}
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
parentId: index > 0 ? messages[index - 1].id : null,
|
|
2233
|
-
message: {
|
|
2234
|
-
id: m.id,
|
|
2235
|
-
role: m.role,
|
|
2236
|
-
parts: m.content,
|
|
2237
|
-
metadata: m.metadata,
|
|
2238
|
-
createdAt: new Date(m.createdAt)
|
|
2239
|
-
}
|
|
2240
|
-
})
|
|
2241
|
-
);
|
|
2242
|
-
console.log("[History] Formatted messages:", formattedMessages.length);
|
|
2243
|
-
return {
|
|
2244
|
-
headId: messages.length > 0 ? messages[messages.length - 1].id : null,
|
|
2245
|
-
messages: formattedMessages
|
|
2246
|
-
};
|
|
2247
|
-
} catch (error) {
|
|
2248
|
-
console.error("[History] Load error:", error);
|
|
2249
|
-
return { headId: null, messages: [] };
|
|
2232
|
+
var buttonVariants = cva(
|
|
2233
|
+
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
|
|
2234
|
+
{
|
|
2235
|
+
variants: {
|
|
2236
|
+
variant: {
|
|
2237
|
+
default: "bg-primary text-primary-foreground hover:bg-primary/90",
|
|
2238
|
+
destructive: "bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
|
|
2239
|
+
outline: "border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50",
|
|
2240
|
+
secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
|
|
2241
|
+
ghost: "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
|
|
2242
|
+
link: "text-primary underline-offset-4 hover:underline"
|
|
2243
|
+
},
|
|
2244
|
+
size: {
|
|
2245
|
+
default: "h-9 px-4 py-2 has-[>svg]:px-3",
|
|
2246
|
+
sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5",
|
|
2247
|
+
lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
|
|
2248
|
+
icon: "size-9",
|
|
2249
|
+
"icon-sm": "size-8",
|
|
2250
|
+
"icon-lg": "size-10"
|
|
2250
2251
|
}
|
|
2251
2252
|
},
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
}
|
|
2270
|
-
const { messages } = await response.json();
|
|
2271
|
-
console.log("[History.withFormat] Loaded:", messages.length);
|
|
2272
|
-
const formattedMessages = messages.map(
|
|
2273
|
-
(m, index) => ({
|
|
2274
|
-
parentId: index > 0 ? messages[index - 1].id : null,
|
|
2275
|
-
message: {
|
|
2276
|
-
id: m.id,
|
|
2277
|
-
role: m.role,
|
|
2278
|
-
parts: m.content,
|
|
2279
|
-
metadata: m.metadata,
|
|
2280
|
-
createdAt: new Date(m.createdAt)
|
|
2281
|
-
}
|
|
2282
|
-
})
|
|
2283
|
-
);
|
|
2284
|
-
return {
|
|
2285
|
-
headId: messages.length > 0 ? messages[messages.length - 1].id : null,
|
|
2286
|
-
messages: formattedMessages
|
|
2287
|
-
};
|
|
2288
|
-
} catch (error) {
|
|
2289
|
-
console.error("[History.withFormat] Error:", error);
|
|
2290
|
-
return { headId: null, messages: [] };
|
|
2291
|
-
}
|
|
2292
|
-
},
|
|
2293
|
-
async append(_item) {
|
|
2294
|
-
}
|
|
2295
|
-
};
|
|
2253
|
+
defaultVariants: {
|
|
2254
|
+
variant: "default",
|
|
2255
|
+
size: "default"
|
|
2256
|
+
}
|
|
2257
|
+
}
|
|
2258
|
+
);
|
|
2259
|
+
var Button2 = React2.forwardRef(({ className, variant = "default", size = "default", asChild = false, ...props }, ref) => {
|
|
2260
|
+
const Comp = asChild ? Slot : "button";
|
|
2261
|
+
return /* @__PURE__ */ jsx(
|
|
2262
|
+
Comp,
|
|
2263
|
+
{
|
|
2264
|
+
ref,
|
|
2265
|
+
"data-slot": "button",
|
|
2266
|
+
"data-variant": variant,
|
|
2267
|
+
"data-size": size,
|
|
2268
|
+
className: cn(buttonVariants({ variant, size, className })),
|
|
2269
|
+
...props
|
|
2296
2270
|
}
|
|
2297
|
-
};
|
|
2298
|
-
}
|
|
2299
|
-
function AssistantRuntimeWrapper({
|
|
2300
|
-
config,
|
|
2301
|
-
userId,
|
|
2302
|
-
children
|
|
2303
|
-
}) {
|
|
2304
|
-
const baseUrl = config.baseUrl || "http://localhost:3000";
|
|
2305
|
-
const assistantId = config.apiKey;
|
|
2306
|
-
const { consumeContext, clearContext } = useMessageContext();
|
|
2307
|
-
const contextRef = useRef(consumeContext);
|
|
2308
|
-
contextRef.current = consumeContext;
|
|
2309
|
-
const clearContextRef = useRef(clearContext);
|
|
2310
|
-
clearContextRef.current = clearContext;
|
|
2311
|
-
const threadListAdapter = useMemo(
|
|
2312
|
-
() => createThreadListAdapter(baseUrl, userId, assistantId),
|
|
2313
|
-
[baseUrl, userId, assistantId]
|
|
2314
2271
|
);
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
// Use body as a function to dynamically include context
|
|
2335
|
-
body: () => {
|
|
2336
|
-
const currentContext = contextRef.current();
|
|
2337
|
-
const contextIds = currentContext.map((item) => item.id);
|
|
2338
|
-
const contextMetadata = currentContext.map((item) => ({
|
|
2339
|
-
id: item.id,
|
|
2340
|
-
type: item.type,
|
|
2341
|
-
title: item.title
|
|
2342
|
-
}));
|
|
2343
|
-
console.log("[Widget] Transport body - contextIds:", contextIds.length, "threadId:", threadId);
|
|
2344
|
-
if (contextIds.length > 0) {
|
|
2345
|
-
setTimeout(() => clearContextRef.current(), 0);
|
|
2346
|
-
}
|
|
2347
|
-
return {
|
|
2348
|
-
assistantId,
|
|
2349
|
-
threadId,
|
|
2350
|
-
...contextIds.length > 0 && { contextIds, contextMetadata }
|
|
2351
|
-
};
|
|
2352
|
-
}
|
|
2353
|
-
});
|
|
2354
|
-
}, [threadId]);
|
|
2355
|
-
const runtime2 = useChatRuntime({
|
|
2356
|
-
transport,
|
|
2357
|
-
adapters: { history },
|
|
2358
|
-
onFinish: ({ message, messages }) => {
|
|
2359
|
-
const currentThreadId = threadIdRef.current;
|
|
2360
|
-
console.log(
|
|
2361
|
-
"[Widget] onFinish - threadId:",
|
|
2362
|
-
currentThreadId,
|
|
2363
|
-
"messages:",
|
|
2364
|
-
messages.length
|
|
2365
|
-
);
|
|
2366
|
-
if (currentThreadId && messages.length > 0) {
|
|
2367
|
-
saveMessages(
|
|
2368
|
-
baseUrl,
|
|
2369
|
-
userId,
|
|
2370
|
-
assistantId,
|
|
2371
|
-
currentThreadId,
|
|
2372
|
-
messages
|
|
2373
|
-
);
|
|
2374
|
-
}
|
|
2375
|
-
}
|
|
2376
|
-
});
|
|
2377
|
-
return runtime2;
|
|
2378
|
-
},
|
|
2379
|
-
adapter: threadListAdapter
|
|
2380
|
-
});
|
|
2381
|
-
return /* @__PURE__ */ jsxs(AssistantRuntimeProvider, { runtime, children: [
|
|
2382
|
-
/* @__PURE__ */ jsx(DetailedAnswerToolUI, {}),
|
|
2383
|
-
children
|
|
2384
|
-
] });
|
|
2385
|
-
}
|
|
2386
|
-
function WidgetProvider({
|
|
2387
|
-
config,
|
|
2272
|
+
});
|
|
2273
|
+
Button2.displayName = "Button";
|
|
2274
|
+
var TooltipIconButton = forwardRef(({ children, tooltip, side = "bottom", className, ...rest }, ref) => {
|
|
2275
|
+
return /* @__PURE__ */ jsxs(Tooltip, { children: [
|
|
2276
|
+
/* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(Button2, { variant: "ghost", size: "icon-sm", ...rest, ref, children: [
|
|
2277
|
+
/* @__PURE__ */ jsx(Slottable, { children }),
|
|
2278
|
+
/* @__PURE__ */ jsx("span", { className: "aui-sr-only sr-only", children: tooltip })
|
|
2279
|
+
] }) }),
|
|
2280
|
+
/* @__PURE__ */ jsx(TooltipContent, { side, children: tooltip })
|
|
2281
|
+
] });
|
|
2282
|
+
});
|
|
2283
|
+
TooltipIconButton.displayName = "TooltipIconButton";
|
|
2284
|
+
var ToolCard = ({
|
|
2285
|
+
title,
|
|
2286
|
+
subtitle,
|
|
2287
|
+
isStreaming,
|
|
2288
|
+
isError = false,
|
|
2289
|
+
icon,
|
|
2290
|
+
persistentContent,
|
|
2388
2291
|
children,
|
|
2389
|
-
|
|
2390
|
-
}) {
|
|
2391
|
-
const [
|
|
2392
|
-
const
|
|
2393
|
-
const
|
|
2292
|
+
footer
|
|
2293
|
+
}) => {
|
|
2294
|
+
const [manualExpanded, setManualExpanded] = useState(null);
|
|
2295
|
+
const prevStreamingRef = useRef(isStreaming);
|
|
2296
|
+
const contentRef = useRef(null);
|
|
2297
|
+
const isExpanded = manualExpanded ?? isStreaming;
|
|
2394
2298
|
useEffect(() => {
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
});
|
|
2398
|
-
if (autoInitialize && state.status === "idle") {
|
|
2399
|
-
client.initialize().catch(console.error);
|
|
2299
|
+
if (isStreaming && !prevStreamingRef.current) {
|
|
2300
|
+
setManualExpanded(null);
|
|
2400
2301
|
}
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
const contextValue = useMemo(
|
|
2407
|
-
() => ({ client, state, userId }),
|
|
2408
|
-
[client, state, userId]
|
|
2409
|
-
);
|
|
2410
|
-
return /* @__PURE__ */ jsx(CacheProvider, { value: widgetCache, children: /* @__PURE__ */ jsx(ThemeProvider, { theme, children: /* @__PURE__ */ jsx(WidgetContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx(MessageContextProvider, { children: /* @__PURE__ */ jsx(AssistantRuntimeWrapper, { config, userId, children }) }) }) }) });
|
|
2411
|
-
}
|
|
2412
|
-
function useWidget() {
|
|
2413
|
-
const context = useContext(WidgetContext);
|
|
2414
|
-
if (!context) {
|
|
2415
|
-
throw new Error("useWidget must be used within a WidgetProvider");
|
|
2416
|
-
}
|
|
2417
|
-
const { client, state } = context;
|
|
2418
|
-
const initialize = useCallback(async () => {
|
|
2419
|
-
if (state.status === "idle") {
|
|
2420
|
-
await client.initialize();
|
|
2302
|
+
prevStreamingRef.current = isStreaming;
|
|
2303
|
+
}, [isStreaming]);
|
|
2304
|
+
useEffect(() => {
|
|
2305
|
+
if (isStreaming && contentRef.current) {
|
|
2306
|
+
contentRef.current.scrollTop = contentRef.current.scrollHeight;
|
|
2421
2307
|
}
|
|
2422
|
-
}
|
|
2423
|
-
const
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
isInitializing: state.status === "initializing",
|
|
2434
|
-
isReady: state.status === "ready",
|
|
2435
|
-
isLoading: state.status === "loading",
|
|
2436
|
-
isError: state.status === "error",
|
|
2437
|
-
messages: state.status === "ready" ? state.session.messages : [],
|
|
2438
|
-
error: state.status === "error" ? state.error : null,
|
|
2439
|
-
initialize,
|
|
2440
|
-
sendMessage
|
|
2308
|
+
});
|
|
2309
|
+
const renderIcon = () => {
|
|
2310
|
+
if (icon) return icon;
|
|
2311
|
+
const iconClass = cn("h-4 w-4", isStreaming && "animate-spin");
|
|
2312
|
+
if (isStreaming) {
|
|
2313
|
+
return /* @__PURE__ */ jsx(Loader2Icon, { className: iconClass });
|
|
2314
|
+
}
|
|
2315
|
+
if (isError) {
|
|
2316
|
+
return /* @__PURE__ */ jsx(XCircleIcon, { className: "h-4 w-4 text-red-400" });
|
|
2317
|
+
}
|
|
2318
|
+
return /* @__PURE__ */ jsx(CheckIcon, { className: "h-4 w-4" });
|
|
2441
2319
|
};
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2320
|
+
const handleToggle = () => {
|
|
2321
|
+
if (!isStreaming) {
|
|
2322
|
+
setManualExpanded((prev2) => prev2 === null ? true : !prev2);
|
|
2323
|
+
}
|
|
2324
|
+
};
|
|
2325
|
+
return /* @__PURE__ */ jsxs("div", { className: "my-2 overflow-hidden rounded-xl border border-border shadow-sm", children: [
|
|
2326
|
+
/* @__PURE__ */ jsxs(
|
|
2327
|
+
"div",
|
|
2328
|
+
{
|
|
2329
|
+
className: cn(
|
|
2330
|
+
"flex items-center gap-2 p-2 cursor-pointer transition-colors text-white bg-primary-foreground",
|
|
2331
|
+
!isStreaming && "hover:opacity-90"
|
|
2332
|
+
),
|
|
2333
|
+
onClick: handleToggle,
|
|
2334
|
+
children: [
|
|
2335
|
+
/* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: renderIcon() }),
|
|
2336
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
2337
|
+
subtitle && /* @__PURE__ */ jsx("p", { className: "font-medium opacity-80 leading-tight text-xs text-muted-foreground", children: subtitle }),
|
|
2338
|
+
/* @__PURE__ */ jsx("h4", { className: "truncate font-semibold leading-tight text-sm text-muted-foreground", children: title })
|
|
2339
|
+
] }),
|
|
2340
|
+
/* @__PURE__ */ jsx(
|
|
2341
|
+
"button",
|
|
2342
|
+
{
|
|
2343
|
+
className: "p-1 rounded hover:bg-white/20 transition-colors",
|
|
2344
|
+
"aria-label": isExpanded ? "Collapse" : "Expand",
|
|
2345
|
+
onClick: (e) => {
|
|
2346
|
+
e.stopPropagation();
|
|
2347
|
+
handleToggle();
|
|
2348
|
+
},
|
|
2349
|
+
children: isExpanded ? /* @__PURE__ */ jsx(ChevronUpIcon, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx(ChevronDownIcon, { className: "h-4 w-4" })
|
|
2350
|
+
}
|
|
2351
|
+
)
|
|
2352
|
+
]
|
|
2353
|
+
}
|
|
2354
|
+
),
|
|
2355
|
+
persistentContent,
|
|
2356
|
+
isExpanded && /* @__PURE__ */ jsx(
|
|
2357
|
+
"div",
|
|
2358
|
+
{
|
|
2359
|
+
ref: contentRef,
|
|
2360
|
+
className: "p-2 max-h-[400px] overflow-y-auto bg-secondary",
|
|
2361
|
+
children
|
|
2362
|
+
}
|
|
2363
|
+
),
|
|
2364
|
+
isExpanded && footer && /* @__PURE__ */ jsx("div", { className: "flex items-center justify-end gap-2 border-t border-white/10 p-2 bg-primary-foreground/80", children: footer })
|
|
2365
|
+
] });
|
|
2366
|
+
};
|
|
2367
|
+
var useCopyToClipboard = ({
|
|
2368
|
+
copiedDuration = 3e3
|
|
2369
|
+
} = {}) => {
|
|
2370
|
+
const [isCopied, setIsCopied] = useState(false);
|
|
2371
|
+
const copyToClipboard = (value) => {
|
|
2372
|
+
if (!value) return;
|
|
2373
|
+
navigator.clipboard.writeText(value).then(() => {
|
|
2374
|
+
setIsCopied(true);
|
|
2375
|
+
setTimeout(() => setIsCopied(false), copiedDuration);
|
|
2376
|
+
});
|
|
2377
|
+
};
|
|
2378
|
+
return { isCopied, copyToClipboard };
|
|
2379
|
+
};
|
|
2380
|
+
var MarkdownContent = memo(({ content }) => {
|
|
2381
|
+
return /* @__PURE__ */ jsx("div", { className: "aui-md max-w-none text-white", children: /* @__PURE__ */ jsx(
|
|
2382
|
+
ReactMarkdown,
|
|
2383
|
+
{
|
|
2384
|
+
remarkPlugins: [remarkGfm],
|
|
2385
|
+
components: {
|
|
2386
|
+
h1: ({ className, ...props }) => /* @__PURE__ */ jsx(
|
|
2387
|
+
"h1",
|
|
2388
|
+
{
|
|
2389
|
+
className: cn(
|
|
2390
|
+
"mb-2 font-extrabold tracking-tight last:mb-0 text-white",
|
|
2391
|
+
className
|
|
2392
|
+
),
|
|
2393
|
+
style: { fontSize: "12px" },
|
|
2394
|
+
...props
|
|
2395
|
+
}
|
|
2396
|
+
),
|
|
2397
|
+
h2: ({ className, ...props }) => /* @__PURE__ */ jsx(
|
|
2398
|
+
"h2",
|
|
2399
|
+
{
|
|
2400
|
+
className: cn(
|
|
2401
|
+
"mt-3 mb-1.5 font-semibold tracking-tight first:mt-0 last:mb-0 text-white",
|
|
2402
|
+
className
|
|
2403
|
+
),
|
|
2404
|
+
style: { fontSize: "10px" },
|
|
2405
|
+
...props
|
|
2406
|
+
}
|
|
2407
|
+
),
|
|
2408
|
+
h3: ({ className, ...props }) => /* @__PURE__ */ jsx(
|
|
2409
|
+
"h3",
|
|
2410
|
+
{
|
|
2411
|
+
className: cn(
|
|
2412
|
+
"mt-2 mb-1 font-semibold tracking-tight first:mt-0 last:mb-0 text-white",
|
|
2413
|
+
className
|
|
2414
|
+
),
|
|
2415
|
+
style: { fontSize: "9px" },
|
|
2416
|
+
...props
|
|
2417
|
+
}
|
|
2418
|
+
),
|
|
2419
|
+
p: ({ className, ...props }) => /* @__PURE__ */ jsx(
|
|
2420
|
+
"p",
|
|
2421
|
+
{
|
|
2422
|
+
className: cn(
|
|
2423
|
+
"mt-1.5 mb-1.5 leading-relaxed first:mt-0 last:mb-0 text-white/90",
|
|
2424
|
+
className
|
|
2425
|
+
),
|
|
2426
|
+
...props
|
|
2427
|
+
}
|
|
2428
|
+
),
|
|
2429
|
+
ul: ({ className, ...props }) => /* @__PURE__ */ jsx(
|
|
2430
|
+
"ul",
|
|
2431
|
+
{
|
|
2432
|
+
className: cn(
|
|
2433
|
+
"my-1.5 ml-3 list-disc [&>li]:mt-0.5 text-white/90",
|
|
2434
|
+
className
|
|
2435
|
+
),
|
|
2436
|
+
...props
|
|
2437
|
+
}
|
|
2438
|
+
),
|
|
2439
|
+
ol: ({ className, ...props }) => /* @__PURE__ */ jsx(
|
|
2440
|
+
"ol",
|
|
2441
|
+
{
|
|
2442
|
+
className: cn(
|
|
2443
|
+
"my-1.5 ml-3 list-decimal [&>li]:mt-0.5 text-white/90",
|
|
2444
|
+
className
|
|
2445
|
+
),
|
|
2446
|
+
...props
|
|
2447
|
+
}
|
|
2448
|
+
),
|
|
2449
|
+
blockquote: ({ className, ...props }) => /* @__PURE__ */ jsx(
|
|
2450
|
+
"blockquote",
|
|
2451
|
+
{
|
|
2452
|
+
className: cn(
|
|
2453
|
+
"border-l-2 border-white/30 pl-2 italic text-white/70",
|
|
2454
|
+
className
|
|
2455
|
+
),
|
|
2456
|
+
...props
|
|
2457
|
+
}
|
|
2458
|
+
),
|
|
2459
|
+
pre: ({ className, ...props }) => /* @__PURE__ */ jsx(
|
|
2460
|
+
"pre",
|
|
2461
|
+
{
|
|
2462
|
+
className: cn(
|
|
2463
|
+
"overflow-x-auto rounded bg-black/30 p-1.5 text-white/90 my-1.5",
|
|
2464
|
+
className
|
|
2465
|
+
),
|
|
2466
|
+
...props
|
|
2467
|
+
}
|
|
2468
|
+
),
|
|
2469
|
+
code: ({ className, ...props }) => {
|
|
2470
|
+
const isInline = !className?.includes("language-");
|
|
2471
|
+
return /* @__PURE__ */ jsx(
|
|
2472
|
+
"code",
|
|
2473
|
+
{
|
|
2474
|
+
className: cn(
|
|
2475
|
+
isInline && "rounded bg-black/30 px-0.5 py-0.5 font-mono text-white/90",
|
|
2476
|
+
className
|
|
2477
|
+
),
|
|
2478
|
+
...props
|
|
2479
|
+
}
|
|
2480
|
+
);
|
|
2481
|
+
},
|
|
2482
|
+
a: ({ className, ...props }) => /* @__PURE__ */ jsx(
|
|
2483
|
+
"a",
|
|
2484
|
+
{
|
|
2485
|
+
className: cn(
|
|
2486
|
+
"font-medium text-blue-300 underline underline-offset-2",
|
|
2487
|
+
className
|
|
2488
|
+
),
|
|
2489
|
+
target: "_blank",
|
|
2490
|
+
rel: "noopener noreferrer",
|
|
2491
|
+
...props
|
|
2492
|
+
}
|
|
2493
|
+
),
|
|
2494
|
+
hr: ({ className, ...props }) => /* @__PURE__ */ jsx(
|
|
2495
|
+
"hr",
|
|
2496
|
+
{
|
|
2497
|
+
className: cn("my-2 border-b border-white/20", className),
|
|
2498
|
+
...props
|
|
2499
|
+
}
|
|
2500
|
+
)
|
|
2501
|
+
},
|
|
2502
|
+
children: content
|
|
2503
|
+
}
|
|
2504
|
+
) });
|
|
2505
|
+
});
|
|
2506
|
+
MarkdownContent.displayName = "MarkdownContent";
|
|
2507
|
+
var DetailedAnswerToolUI = makeAssistantToolUI({
|
|
2508
|
+
toolName: "generateDetailedAnswer",
|
|
2509
|
+
render: function DetailedAnswerUI({ args, result, status }) {
|
|
2510
|
+
const { isCopied, copyToClipboard } = useCopyToClipboard();
|
|
2511
|
+
const isStreaming = status.type === "running";
|
|
2512
|
+
const isError = status.type === "incomplete";
|
|
2513
|
+
const title = result?.title || args.title || "Generating...";
|
|
2514
|
+
const content = result?.content || args.content || "";
|
|
2515
|
+
const summary = result?.summary || args.summary || "";
|
|
2516
|
+
const handleCopy = () => {
|
|
2517
|
+
if (content) {
|
|
2518
|
+
copyToClipboard(content);
|
|
2451
2519
|
}
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
|
|
2520
|
+
};
|
|
2521
|
+
const handleOpenFullScreen = () => {
|
|
2522
|
+
const newWindow = window.open("", "_blank");
|
|
2523
|
+
if (newWindow) {
|
|
2524
|
+
newWindow.document.write(`
|
|
2525
|
+
<!DOCTYPE html>
|
|
2526
|
+
<html>
|
|
2527
|
+
<head>
|
|
2528
|
+
<title>${title}</title>
|
|
2529
|
+
<meta charset="utf-8">
|
|
2530
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
2531
|
+
<style>
|
|
2532
|
+
body {
|
|
2533
|
+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
|
|
2534
|
+
max-width: 800px;
|
|
2535
|
+
margin: 0 auto;
|
|
2536
|
+
padding: 2rem;
|
|
2537
|
+
line-height: 1.6;
|
|
2538
|
+
color: #1a1a1a;
|
|
2539
|
+
}
|
|
2540
|
+
h1 { border-bottom: 1px solid #eee; padding-bottom: 0.5rem; }
|
|
2541
|
+
pre { background: #f5f5f5; padding: 1rem; overflow-x: auto; border-radius: 4px; }
|
|
2542
|
+
code { background: #f5f5f5; padding: 0.2em 0.4em; border-radius: 3px; font-size: 0.9em; }
|
|
2543
|
+
pre code { background: none; padding: 0; }
|
|
2544
|
+
blockquote { border-left: 4px solid #ddd; margin: 0; padding-left: 1rem; color: #666; }
|
|
2545
|
+
</style>
|
|
2546
|
+
</head>
|
|
2547
|
+
<body>
|
|
2548
|
+
<h1>${title}</h1>
|
|
2549
|
+
<div id="content">${content.replace(/</g, "<").replace(/>/g, ">")}</div>
|
|
2550
|
+
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
|
|
2551
|
+
<script>
|
|
2552
|
+
document.getElementById('content').innerHTML = marked.parse(${JSON.stringify(
|
|
2553
|
+
content
|
|
2554
|
+
)});
|
|
2555
|
+
</script>
|
|
2556
|
+
</body>
|
|
2557
|
+
</html>
|
|
2558
|
+
`);
|
|
2559
|
+
newWindow.document.close();
|
|
2459
2560
|
}
|
|
2460
|
-
}
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
|
|
2561
|
+
};
|
|
2562
|
+
const persistentSummary = summary ? /* @__PURE__ */ jsx("div", { className: "p-2 text-white/80 border-b border-white/10 bg-primary-foreground text-xs", children: summary }) : void 0;
|
|
2563
|
+
const footerActions = content ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2564
|
+
/* @__PURE__ */ jsx(
|
|
2565
|
+
TooltipIconButton,
|
|
2566
|
+
{
|
|
2567
|
+
tooltip: isCopied ? "Copied!" : "Copy markdown",
|
|
2568
|
+
onClick: handleCopy,
|
|
2569
|
+
className: "flex items-center justify-center rounded-md p-1.5 text-white/70 hover:bg-white/10 transition-colors",
|
|
2570
|
+
children: isCopied ? /* @__PURE__ */ jsx(CheckIcon, { className: "h-3.5 w-3.5" }) : /* @__PURE__ */ jsx(CopyIcon, { className: "h-3.5 w-3.5" })
|
|
2571
|
+
}
|
|
2572
|
+
),
|
|
2573
|
+
/* @__PURE__ */ jsx(
|
|
2574
|
+
TooltipIconButton,
|
|
2575
|
+
{
|
|
2576
|
+
tooltip: "Open in new window",
|
|
2577
|
+
onClick: handleOpenFullScreen,
|
|
2578
|
+
className: "flex items-center justify-center rounded-md p-1.5 text-white/70 hover:bg-white/10 transition-colors",
|
|
2579
|
+
children: /* @__PURE__ */ jsx(ExternalLinkIcon, { className: "h-3.5 w-3.5" })
|
|
2580
|
+
}
|
|
2581
|
+
)
|
|
2582
|
+
] }) : void 0;
|
|
2583
|
+
return /* @__PURE__ */ jsx(
|
|
2584
|
+
ToolCard,
|
|
2585
|
+
{
|
|
2586
|
+
title,
|
|
2587
|
+
isStreaming,
|
|
2588
|
+
isError,
|
|
2589
|
+
icon: !isStreaming && !isError ? /* @__PURE__ */ jsx(FileTextIcon, { className: "h-4 w-4" }) : void 0,
|
|
2590
|
+
persistentContent: persistentSummary,
|
|
2591
|
+
footer: footerActions,
|
|
2592
|
+
children: content ? /* @__PURE__ */ jsx(MarkdownContent, { content }) : /* @__PURE__ */ jsx("p", { className: "text-muted-foreground italic", children: "Generating content..." })
|
|
2593
|
+
}
|
|
2594
|
+
);
|
|
2595
|
+
}
|
|
2596
|
+
});
|
|
2472
2597
|
function Dialog({
|
|
2473
2598
|
...props
|
|
2474
2599
|
}) {
|
|
@@ -3856,7 +3981,7 @@ var ThreadSuggestions = () => {
|
|
|
3856
3981
|
className: "fade-in slide-in-from-bottom-2 animate-in fill-mode-both duration-200",
|
|
3857
3982
|
style: { animationDelay: `${200 + index * 50}ms` },
|
|
3858
3983
|
children: /* @__PURE__ */ jsx(ThreadPrimitive.Suggestion, { prompt: suggestion.prompt, send: true, asChild: true, children: /* @__PURE__ */ jsx(
|
|
3859
|
-
|
|
3984
|
+
Button2,
|
|
3860
3985
|
{
|
|
3861
3986
|
variant: "ghost",
|
|
3862
3987
|
className: "aui-thread-welcome-suggestion h-auto w-full @md:flex-col flex-wrap items-start justify-start gap-1 rounded-2xl border text-left text-sm transition-colors hover:bg-muted hover:text-primary",
|
|
@@ -4062,7 +4187,7 @@ var ComposerAction = () => {
|
|
|
4062
4187
|
}
|
|
4063
4188
|
) }) }),
|
|
4064
4189
|
/* @__PURE__ */ jsx(AssistantIf, { condition: ({ thread }) => thread.isRunning, children: /* @__PURE__ */ jsx(ComposerPrimitive.Cancel, { asChild: true, children: /* @__PURE__ */ jsx(
|
|
4065
|
-
|
|
4190
|
+
Button2,
|
|
4066
4191
|
{
|
|
4067
4192
|
type: "button",
|
|
4068
4193
|
variant: "default",
|
|
@@ -4207,8 +4332,8 @@ var EditComposer = () => {
|
|
|
4207
4332
|
}
|
|
4208
4333
|
),
|
|
4209
4334
|
/* @__PURE__ */ jsxs("div", { className: "aui-edit-composer-footer mx-3 mb-3 flex items-center gap-2 self-end", children: [
|
|
4210
|
-
/* @__PURE__ */ jsx(ComposerPrimitive.Cancel, { asChild: true, children: /* @__PURE__ */ jsx(
|
|
4211
|
-
/* @__PURE__ */ jsx(ComposerPrimitive.Send, { asChild: true, children: /* @__PURE__ */ jsx(
|
|
4335
|
+
/* @__PURE__ */ jsx(ComposerPrimitive.Cancel, { asChild: true, children: /* @__PURE__ */ jsx(Button2, { variant: "ghost", size: "sm", children: "Cancel" }) }),
|
|
4336
|
+
/* @__PURE__ */ jsx(ComposerPrimitive.Send, { asChild: true, children: /* @__PURE__ */ jsx(Button2, { size: "sm", children: "Update" }) })
|
|
4212
4337
|
] })
|
|
4213
4338
|
] }) });
|
|
4214
4339
|
};
|
|
@@ -4257,7 +4382,7 @@ var ThreadList = () => {
|
|
|
4257
4382
|
ThreadListPrimitive.Items,
|
|
4258
4383
|
{
|
|
4259
4384
|
components: {
|
|
4260
|
-
ThreadListItem
|
|
4385
|
+
ThreadListItem: ThreadListItem2
|
|
4261
4386
|
}
|
|
4262
4387
|
}
|
|
4263
4388
|
),
|
|
@@ -4274,7 +4399,7 @@ var ThreadList = () => {
|
|
|
4274
4399
|
] })
|
|
4275
4400
|
] });
|
|
4276
4401
|
};
|
|
4277
|
-
var
|
|
4402
|
+
var ThreadListItem2 = () => {
|
|
4278
4403
|
return /* @__PURE__ */ jsxs(ThreadListItemPrimitive.Root, { className: "aui-thread-list-item group relative flex items-center gap-2 px-3 py-2 hover:bg-muted/50 data-[active]:bg-muted cursor-pointer transition-colors", children: [
|
|
4279
4404
|
/* @__PURE__ */ jsxs(ThreadListItemPrimitive.Trigger, { className: "flex flex-1 items-center gap-2 min-w-0", children: [
|
|
4280
4405
|
/* @__PURE__ */ jsx(MessageSquareIcon, { className: "h-4 w-4 flex-shrink-0 text-muted-foreground" }),
|
|
@@ -4334,114 +4459,13 @@ var ArchivedThreadListItem = () => {
|
|
|
4334
4459
|
] })
|
|
4335
4460
|
] });
|
|
4336
4461
|
};
|
|
4337
|
-
var categoryIcons = {
|
|
4338
|
-
audio: HeadphonesIcon,
|
|
4339
|
-
"audio-overview": HeadphonesIcon,
|
|
4340
|
-
"video-overview": VideoIcon,
|
|
4341
|
-
"mind-map": NetworkIcon,
|
|
4342
|
-
reports: FileTextIcon,
|
|
4343
|
-
flashcards: LayersIcon,
|
|
4344
|
-
quiz: HelpCircleIcon,
|
|
4345
|
-
"slide-deck": PresentationIcon,
|
|
4346
|
-
infographic: BarChart3Icon
|
|
4347
|
-
};
|
|
4348
|
-
var categoryColors = {
|
|
4349
|
-
audio: "bg-purple-100 text-purple-700 dark:bg-purple-900/30 dark:text-purple-300",
|
|
4350
|
-
"audio-overview": "bg-purple-100 text-purple-700 dark:bg-purple-900/30 dark:text-purple-300",
|
|
4351
|
-
"video-overview": "bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-300",
|
|
4352
|
-
"mind-map": "bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-300",
|
|
4353
|
-
reports: "bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-300",
|
|
4354
|
-
flashcards: "bg-yellow-100 text-yellow-700 dark:bg-yellow-900/30 dark:text-yellow-300",
|
|
4355
|
-
quiz: "bg-orange-100 text-orange-700 dark:bg-orange-900/30 dark:text-orange-300",
|
|
4356
|
-
"slide-deck": "bg-indigo-100 text-indigo-700 dark:bg-indigo-900/30 dark:text-indigo-300",
|
|
4357
|
-
infographic: "bg-teal-100 text-teal-700 dark:bg-teal-900/30 dark:text-teal-300"
|
|
4358
|
-
};
|
|
4359
|
-
var categoryLabels = {
|
|
4360
|
-
audio: "Audio",
|
|
4361
|
-
"audio-overview": "Audio Overview",
|
|
4362
|
-
"video-overview": "Video Overview",
|
|
4363
|
-
"mind-map": "Mind Map",
|
|
4364
|
-
reports: "Report",
|
|
4365
|
-
flashcards: "Flashcards",
|
|
4366
|
-
quiz: "Quiz",
|
|
4367
|
-
"slide-deck": "Slide Deck",
|
|
4368
|
-
infographic: "Infographic"
|
|
4369
|
-
};
|
|
4370
|
-
var ArtifactCard = ({
|
|
4371
|
-
category,
|
|
4372
|
-
title,
|
|
4373
|
-
content,
|
|
4374
|
-
isLoading,
|
|
4375
|
-
children
|
|
4376
|
-
}) => {
|
|
4377
|
-
const Icon = categoryIcons[category];
|
|
4378
|
-
const colorClass = categoryColors[category];
|
|
4379
|
-
const label = categoryLabels[category];
|
|
4380
|
-
return /* @__PURE__ */ jsxs("div", { className: "my-3 overflow-hidden rounded-xl border border-border bg-card shadow-sm", children: [
|
|
4381
|
-
/* @__PURE__ */ jsxs("div", { className: cn("flex items-center gap-3 px-4 py-3", colorClass), children: [
|
|
4382
|
-
/* @__PURE__ */ jsx("div", { className: "flex h-8 w-8 items-center justify-center rounded-lg bg-white/50 dark:bg-black/20", children: isLoading ? /* @__PURE__ */ jsx(Loader2Icon, { className: "h-4 w-4 animate-spin" }) : /* @__PURE__ */ jsx(Icon, { className: "h-4 w-4" }) }),
|
|
4383
|
-
/* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
4384
|
-
/* @__PURE__ */ jsx("p", { className: "text-xs font-medium opacity-80", children: label }),
|
|
4385
|
-
/* @__PURE__ */ jsx("h4", { className: "truncate font-semibold text-sm", children: title })
|
|
4386
|
-
] })
|
|
4387
|
-
] }),
|
|
4388
|
-
content && /* @__PURE__ */ jsx("div", { className: "px-4 py-3 text-sm text-muted-foreground", children: /* @__PURE__ */ jsx("div", { className: "line-clamp-4 whitespace-pre-wrap", children: content }) }),
|
|
4389
|
-
children,
|
|
4390
|
-
!isLoading && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-2 border-t border-border px-4 py-2", children: [
|
|
4391
|
-
/* @__PURE__ */ jsxs("button", { className: "flex items-center gap-1.5 rounded-md px-3 py-1.5 text-xs font-medium text-muted-foreground hover:bg-muted transition-colors", children: [
|
|
4392
|
-
/* @__PURE__ */ jsx(DownloadIcon, { className: "h-3 w-3" }),
|
|
4393
|
-
"Export"
|
|
4394
|
-
] }),
|
|
4395
|
-
/* @__PURE__ */ jsxs("button", { className: "flex items-center gap-1.5 rounded-md px-3 py-1.5 text-xs font-medium text-muted-foreground hover:bg-muted transition-colors", children: [
|
|
4396
|
-
/* @__PURE__ */ jsx(ExternalLinkIcon, { className: "h-3 w-3" }),
|
|
4397
|
-
"Open"
|
|
4398
|
-
] })
|
|
4399
|
-
] })
|
|
4400
|
-
] });
|
|
4401
|
-
};
|
|
4402
|
-
function createArtifactToolUI(category) {
|
|
4403
|
-
return makeAssistantToolUI({
|
|
4404
|
-
toolName: `create_${category.replace(/-/g, "_")}`,
|
|
4405
|
-
render: ({ args, result, status }) => {
|
|
4406
|
-
const isLoading = status.type === "running";
|
|
4407
|
-
return /* @__PURE__ */ jsx(
|
|
4408
|
-
ArtifactCard,
|
|
4409
|
-
{
|
|
4410
|
-
category,
|
|
4411
|
-
title: args.title || "Generating...",
|
|
4412
|
-
content: result?.content || args.content,
|
|
4413
|
-
isLoading
|
|
4414
|
-
}
|
|
4415
|
-
);
|
|
4416
|
-
}
|
|
4417
|
-
});
|
|
4418
|
-
}
|
|
4419
|
-
var AudioOverviewToolUI = createArtifactToolUI("audio-overview");
|
|
4420
|
-
var VideoOverviewToolUI = createArtifactToolUI("video-overview");
|
|
4421
|
-
var MindMapToolUI = createArtifactToolUI("mind-map");
|
|
4422
|
-
var ReportsToolUI = createArtifactToolUI("reports");
|
|
4423
|
-
var FlashcardsToolUI = createArtifactToolUI("flashcards");
|
|
4424
|
-
var QuizToolUI = createArtifactToolUI("quiz");
|
|
4425
|
-
var SlideDeckToolUI = createArtifactToolUI("slide-deck");
|
|
4426
|
-
var InfographicToolUI = createArtifactToolUI("infographic");
|
|
4427
|
-
var ArtifactToolUIs = () => {
|
|
4428
|
-
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
4429
|
-
/* @__PURE__ */ jsx(AudioOverviewToolUI, {}),
|
|
4430
|
-
/* @__PURE__ */ jsx(VideoOverviewToolUI, {}),
|
|
4431
|
-
/* @__PURE__ */ jsx(MindMapToolUI, {}),
|
|
4432
|
-
/* @__PURE__ */ jsx(ReportsToolUI, {}),
|
|
4433
|
-
/* @__PURE__ */ jsx(FlashcardsToolUI, {}),
|
|
4434
|
-
/* @__PURE__ */ jsx(QuizToolUI, {}),
|
|
4435
|
-
/* @__PURE__ */ jsx(SlideDeckToolUI, {}),
|
|
4436
|
-
/* @__PURE__ */ jsx(InfographicToolUI, {})
|
|
4437
|
-
] });
|
|
4438
|
-
};
|
|
4439
4462
|
var ChatWidget = ({
|
|
4440
4463
|
sidebarOpen = false,
|
|
4441
4464
|
onSidebarClose
|
|
4442
4465
|
}) => {
|
|
4443
4466
|
return /* @__PURE__ */ jsxs("div", { className: "relative flex flex-1 h-full w-full overflow-hidden bg-background", children: [
|
|
4444
4467
|
/* @__PURE__ */ jsx(ArtifactToolUIs, {}),
|
|
4468
|
+
/* @__PURE__ */ jsx(DetailedAnswerToolUI, {}),
|
|
4445
4469
|
/* @__PURE__ */ jsx("div", { className: "flex flex-1 flex-col min-w-0", children: /* @__PURE__ */ jsx("div", { className: "flex-1 overflow-hidden relative", children: /* @__PURE__ */ jsx(Thread, {}) }) }),
|
|
4446
4470
|
/* @__PURE__ */ jsx(AnimatePresence, { children: sidebarOpen && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
4447
4471
|
/* @__PURE__ */ jsx(
|
|
@@ -4471,27 +4495,6 @@ var ChatWidget = ({
|
|
|
4471
4495
|
] }) })
|
|
4472
4496
|
] });
|
|
4473
4497
|
};
|
|
4474
|
-
var ThreadListItem2 = () => {
|
|
4475
|
-
return /* @__PURE__ */ jsx(ThreadListItemPrimitive.Root, { className: "group relative flex items-center gap-2 px-2 py-1.5 hover:bg-muted/50 data-[active]:bg-muted cursor-pointer transition-colors rounded-sm", children: /* @__PURE__ */ jsx(ThreadListItemPrimitive.Trigger, { className: "flex flex-1 items-center gap-2 min-w-0", children: /* @__PURE__ */ jsx("span", { className: "truncate text-sm text-foreground", children: /* @__PURE__ */ jsx(ThreadListItemPrimitive.Title, { fallback: "New Chat" }) }) }) });
|
|
4476
|
-
};
|
|
4477
|
-
var ChatHistoryPopover = ({
|
|
4478
|
-
onSelectThread
|
|
4479
|
-
}) => {
|
|
4480
|
-
const handleThreadSelect = () => {
|
|
4481
|
-
onSelectThread?.();
|
|
4482
|
-
};
|
|
4483
|
-
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col", onClick: handleThreadSelect, children: [
|
|
4484
|
-
/* @__PURE__ */ jsx("div", { className: "px-2 py-1.5", children: /* @__PURE__ */ jsx(Text, { size: "xs", style: { color: "hsl(var(--muted-foreground))" }, children: "Previous 7 days" }) }),
|
|
4485
|
-
/* @__PURE__ */ jsx("div", { className: "max-h-[300px] overflow-y-auto", children: /* @__PURE__ */ jsx(
|
|
4486
|
-
ThreadListPrimitive.Items,
|
|
4487
|
-
{
|
|
4488
|
-
components: {
|
|
4489
|
-
ThreadListItem: ThreadListItem2
|
|
4490
|
-
}
|
|
4491
|
-
}
|
|
4492
|
-
) })
|
|
4493
|
-
] });
|
|
4494
|
-
};
|
|
4495
4498
|
var layoutOptions = [
|
|
4496
4499
|
{
|
|
4497
4500
|
value: "sidebar",
|