@agents24/chat-react 0.1.7 → 0.1.9
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 +25 -12
- package/dist/chunk-E3TJ3I6G.js +358 -0
- package/dist/chunk-E3TJ3I6G.js.map +1 -0
- package/dist/chunk-EWZO4QJI.js +140 -0
- package/dist/chunk-EWZO4QJI.js.map +1 -0
- package/dist/chunk-UU7OXHL3.js +11 -0
- package/dist/chunk-UU7OXHL3.js.map +1 -0
- package/dist/context-window.d.ts +38 -0
- package/dist/controller.d.ts +22 -0
- package/dist/index.cjs +392 -314
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +10 -530
- package/dist/index.js +41 -439
- package/dist/index.js.map +1 -1
- package/dist/latest-thread-scroller.d.ts +54 -0
- package/dist/model.d.ts +29 -0
- package/dist/renderers.d.ts +10 -0
- package/dist/sse.d.ts +3 -0
- package/dist/streaming-text.d.ts +24 -0
- package/dist/templates/agent-chat-shell.d.ts +25 -0
- package/dist/templates/index.cjs +523 -0
- package/dist/templates/index.cjs.map +1 -0
- package/dist/templates/index.d.ts +1 -0
- package/dist/templates/index.js +140 -0
- package/dist/templates/index.js.map +1 -0
- package/dist/transport.d.ts +29 -0
- package/dist/types.d.ts +312 -0
- package/dist/ui/adapters.d.ts +36 -0
- package/dist/ui/attachment.d.ts +23 -0
- package/dist/ui/bubble.d.ts +17 -0
- package/dist/ui/index.cjs +943 -0
- package/dist/ui/index.cjs.map +1 -0
- package/dist/ui/index.d.ts +7 -0
- package/dist/ui/index.js +734 -0
- package/dist/ui/index.js.map +1 -0
- package/dist/ui/marker.d.ts +11 -0
- package/dist/ui/message-response.d.ts +7 -0
- package/dist/ui/message.d.ts +10 -0
- package/dist/ui/utils.d.ts +2 -0
- package/dist/viewport.d.ts +2 -0
- package/package.json +22 -4
- package/dist/index.d.cts +0 -530
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/templates/index.ts","../../src/templates/agent-chat-shell.tsx","../../src/latest-thread-scroller.tsx","../../src/ui/utils.ts"],"sourcesContent":["export * from \"./agent-chat-shell\";\n","import * as React from \"react\";\n\nimport {\n LatestThreadScroller,\n type LatestThreadScrollerOutlineItem,\n} from \"../latest-thread-scroller\";\nimport type { ChatMessage } from \"../types\";\nimport { cn } from \"../ui/utils\";\n\nexport type AgentChatShellMessage = Pick<ChatMessage, \"id\" | \"role\" | \"content\"> & {\n [key: string]: unknown;\n};\n\nexport type AgentChatShellProps<TMessage extends AgentChatShellMessage> = {\n className?: string;\n contentClassName?: string;\n composer?: React.ReactNode;\n composerOverlayClassName?: string;\n composerOverlayHeight?: number;\n defaultComposerOverlayHeight?: number;\n dir?: \"ltr\" | \"rtl\";\n hideComposer?: boolean;\n isLoadingOlder?: boolean;\n messages: TMessage[];\n onLoadOlder?: (() => Promise<unknown> | unknown) | null;\n outlineItems?: LatestThreadScrollerOutlineItem[];\n outlineSide?: \"left\" | \"right\";\n renderMessage: (message: TMessage, index: number) => React.ReactNode;\n renderOlderLoader?: () => React.ReactNode;\n};\n\nconst defaultOutlineLabel = (content: unknown, index: number) => {\n const label = String(content || \"\").replace(/\\s+/g, \" \").trim();\n return label || `Turn ${index + 1}`;\n};\n\nconst defaultOutlinePreview = (content: unknown) =>\n String(content || \"\").replace(/\\s+/g, \" \").trim();\n\nexport function buildAgentChatOutlineItems<TMessage extends AgentChatShellMessage>(\n messages: TMessage[],\n getLabel: (message: TMessage, index: number) => string = (message, index) =>\n defaultOutlineLabel(message.content, index),\n getResponsePreview: (message: TMessage) => string = (message) =>\n defaultOutlinePreview(message.content)\n): LatestThreadScrollerOutlineItem[] {\n return messages.reduce((items, message) => {\n if (message.role === \"user\") {\n items.push({\n id: message.id,\n label: getLabel(message, items.length),\n messageIds: [message.id],\n });\n return items;\n }\n const currentItem = items[items.length - 1];\n currentItem?.messageIds?.push(message.id);\n if (\n currentItem &&\n !currentItem.responsePreview &&\n message.role === \"assistant\"\n ) {\n currentItem.responsePreview = getResponsePreview(message);\n }\n return items;\n }, [] as LatestThreadScrollerOutlineItem[]);\n}\n\nexport function AgentChatShell<TMessage extends AgentChatShellMessage>({\n className,\n composer,\n composerOverlayClassName,\n composerOverlayHeight,\n contentClassName,\n defaultComposerOverlayHeight = 192,\n dir = \"ltr\",\n hideComposer = false,\n isLoadingOlder = false,\n messages,\n onLoadOlder,\n outlineItems,\n outlineSide = \"left\",\n renderMessage,\n renderOlderLoader,\n}: AgentChatShellProps<TMessage>) {\n const overlayRef = React.useRef<HTMLDivElement | null>(null);\n const [measuredOverlayHeight, setMeasuredOverlayHeight] = React.useState(\n defaultComposerOverlayHeight\n );\n const olderPageRequestRef = React.useRef(false);\n const items = React.useMemo(\n () => outlineItems || buildAgentChatOutlineItems(messages),\n [messages, outlineItems]\n );\n\n React.useEffect(() => {\n const overlay = overlayRef.current;\n if (!overlay || hideComposer) return;\n const updateHeight = () => {\n setMeasuredOverlayHeight(Math.ceil(overlay.getBoundingClientRect().height));\n };\n updateHeight();\n const observer = new ResizeObserver(updateHeight);\n observer.observe(overlay);\n return () => observer.disconnect();\n }, [hideComposer]);\n\n const handleScroll = React.useCallback(\n (event: React.UIEvent<HTMLDivElement>) => {\n if (\n !onLoadOlder ||\n isLoadingOlder ||\n olderPageRequestRef.current ||\n event.currentTarget.scrollTop > 48\n ) {\n return;\n }\n olderPageRequestRef.current = true;\n void Promise.resolve(onLoadOlder()).finally(() => {\n olderPageRequestRef.current = false;\n });\n },\n [isLoadingOlder, onLoadOlder]\n );\n\n const bottomPadding = hideComposer\n ? 32\n : (composerOverlayHeight ?? measuredOverlayHeight) + 72;\n\n return (\n <div className={cn(\"relative flex h-full min-h-0 w-full flex-col\", className)} dir={dir}>\n <LatestThreadScroller.Provider>\n <LatestThreadScroller.Root>\n <LatestThreadScroller.Viewport onScroll={handleScroll}>\n <LatestThreadScroller.Content\n className={cn(\n \"mx-auto flex min-h-full w-full max-w-3xl flex-col gap-8 px-4 pt-12\",\n contentClassName\n )}\n style={{ paddingBottom: bottomPadding }}\n >\n {isLoadingOlder ? renderOlderLoader?.() : null}\n {messages.map((message, index) => (\n <LatestThreadScroller.Item\n key={message.id}\n messageId={message.id}\n scrollAnchor={message.role === \"user\"}\n >\n {renderMessage(message, index)}\n </LatestThreadScroller.Item>\n ))}\n </LatestThreadScroller.Content>\n </LatestThreadScroller.Viewport>\n <LatestThreadScroller.Outline\n dir={dir}\n items={items}\n side={outlineSide}\n />\n </LatestThreadScroller.Root>\n\n {!hideComposer && composer ? (\n <div\n ref={overlayRef}\n className={cn(\n \"pointer-events-none absolute inset-x-0 bottom-0 z-20 overflow-visible px-4 pb-4 pt-10\",\n composerOverlayClassName\n )}\n style={{\n background:\n \"linear-gradient(to bottom, transparent 0%, color-mix(in oklch, var(--chat-background, var(--background)) 85%, transparent) 45%, var(--chat-background, var(--background)) 65%, var(--chat-background, var(--background)) 100%)\",\n }}\n >\n <div className=\"pointer-events-auto absolute inset-x-0 top-0 flex -translate-y-full justify-center pb-3\">\n <LatestThreadScroller.Button />\n </div>\n <div className=\"pointer-events-auto mx-auto w-full max-w-3xl\">\n {composer}\n </div>\n </div>\n ) : null}\n </LatestThreadScroller.Provider>\n </div>\n );\n}\n","import * as React from \"react\";\nimport {\n MessageScroller,\n useMessageScroller,\n useMessageScrollerVisibility,\n} from \"@shadcn/react/message-scroller\";\n\nconst cx = (...values: Array<string | false | null | undefined>) =>\n values.filter(Boolean).join(\" \");\n\ntype MessageScrollerProviderProps = React.ComponentProps<\n typeof MessageScroller.Provider\n>;\ntype MessageScrollerRootProps = React.ComponentProps<typeof MessageScroller.Root>;\ntype MessageScrollerViewportProps = React.ComponentProps<\n typeof MessageScroller.Viewport\n>;\ntype MessageScrollerContentProps = React.ComponentProps<\n typeof MessageScroller.Content\n>;\ntype MessageScrollerItemProps = React.ComponentProps<typeof MessageScroller.Item>;\ntype MessageScrollerButtonProps = React.ComponentProps<typeof MessageScroller.Button>;\n\ntype LatestThreadScrollerLayoutContextValue = {\n contentElement: HTMLElement | null;\n rootElement: HTMLElement | null;\n setContentElement: (node: HTMLElement | null) => void;\n setRootElement: (node: HTMLElement | null) => void;\n};\n\nconst LatestThreadScrollerLayoutContext =\n React.createContext<LatestThreadScrollerLayoutContextValue | null>(null);\n\nconst useLatestThreadScrollerLayout = () =>\n React.useContext(LatestThreadScrollerLayoutContext);\n\nexport type LatestThreadScrollerProviderProps = MessageScrollerProviderProps;\n\nexport function LatestThreadScrollerProvider({\n autoScroll = true,\n defaultScrollPosition = \"last-anchor\",\n scrollPreviousItemPeek = 64,\n ...props\n}: LatestThreadScrollerProviderProps) {\n return (\n <MessageScroller.Provider\n autoScroll={autoScroll}\n defaultScrollPosition={defaultScrollPosition}\n scrollPreviousItemPeek={scrollPreviousItemPeek}\n {...props}\n />\n );\n}\n\nexport type LatestThreadScrollerRootProps = MessageScrollerRootProps;\n\nexport function LatestThreadScrollerRoot({\n className,\n ref,\n ...props\n}: LatestThreadScrollerRootProps) {\n const [rootElement, setRootElement] = React.useState<HTMLElement | null>(null);\n const [contentElement, setContentElement] =\n React.useState<HTMLElement | null>(null);\n const layoutContext = React.useMemo<LatestThreadScrollerLayoutContextValue>(\n () => ({\n contentElement,\n rootElement,\n setContentElement,\n setRootElement,\n }),\n [contentElement, rootElement]\n );\n const setRef = React.useCallback(\n (node: HTMLDivElement | null) => {\n setRootElement(node);\n if (typeof ref === \"function\") {\n ref(node);\n } else if (ref) {\n ref.current = node;\n }\n },\n [ref]\n );\n\n return (\n <LatestThreadScrollerLayoutContext.Provider value={layoutContext}>\n <MessageScroller.Root\n ref={setRef}\n className={cx(\n \"relative flex size-full min-h-0 flex-1 flex-col overflow-hidden\",\n className\n )}\n {...props}\n />\n </LatestThreadScrollerLayoutContext.Provider>\n );\n}\n\nexport type LatestThreadScrollerViewportProps =\n MessageScrollerViewportProps & {\n onViewportChange?: (node: HTMLElement | null) => void;\n };\n\nexport function LatestThreadScrollerViewport({\n className,\n onViewportChange,\n preserveScrollOnPrepend = true,\n ref,\n ...props\n}: LatestThreadScrollerViewportProps) {\n const setRef = React.useCallback(\n (node: HTMLDivElement | null) => {\n if (typeof ref === \"function\") {\n ref(node);\n } else if (ref) {\n ref.current = node;\n }\n onViewportChange?.(node);\n },\n [onViewportChange, ref]\n );\n\n return (\n <MessageScroller.Viewport\n ref={setRef}\n className={cx(\n \"size-full min-h-0 min-w-0 flex-1 overflow-y-auto overscroll-contain\",\n className\n )}\n preserveScrollOnPrepend={preserveScrollOnPrepend}\n {...props}\n />\n );\n}\n\nexport type LatestThreadScrollerContentProps = MessageScrollerContentProps;\n\nexport function LatestThreadScrollerContent({\n className,\n ref,\n ...props\n}: LatestThreadScrollerContentProps) {\n const layout = useLatestThreadScrollerLayout();\n const setRef = React.useCallback(\n (node: HTMLDivElement | null) => {\n layout?.setContentElement(node);\n if (typeof ref === \"function\") {\n ref(node);\n } else if (ref) {\n ref.current = node;\n }\n },\n [layout, ref]\n );\n\n return (\n <MessageScroller.Content\n ref={setRef}\n data-agents24-latest-thread-content=\"\"\n className={cx(\"flex h-max min-h-full flex-col gap-8 p-4\", className)}\n {...props}\n />\n );\n}\n\nexport type LatestThreadScrollerItemProps = Omit<\n MessageScrollerItemProps,\n \"messageId\"\n> & {\n messageId: string;\n};\n\nexport function LatestThreadScrollerItem({\n className,\n messageId,\n ...props\n}: LatestThreadScrollerItemProps) {\n return (\n <MessageScroller.Item\n className={cx(\n \"min-w-0 shrink-0 overflow-visible\",\n className\n )}\n messageId={messageId}\n {...props}\n />\n );\n}\n\nexport type LatestThreadScrollerButtonProps = Omit<\n MessageScrollerButtonProps,\n \"render\"\n> & {\n className?: string;\n render?: MessageScrollerButtonProps[\"render\"];\n};\n\nexport function LatestThreadScrollerButton({\n children,\n className,\n direction = \"end\",\n render,\n ...props\n}: LatestThreadScrollerButtonProps) {\n if (render) {\n return (\n <MessageScroller.Button\n direction={direction}\n render={render}\n {...props}\n />\n );\n }\n\n return (\n <MessageScroller.Button\n direction={direction}\n render={(buttonProps) => (\n <button\n {...(buttonProps as Record<string, unknown>)}\n aria-label={\n direction === \"end\"\n ? \"Scroll to latest message\"\n : \"Scroll to first message\"\n }\n className={cx(\n \"absolute bottom-4 left-1/2 z-50 flex size-9 -translate-x-1/2 items-center justify-center rounded-full border border-border bg-background text-foreground shadow-md transition-all duration-200 data-[active=false]:pointer-events-none data-[active=false]:translate-y-2 data-[active=false]:opacity-0 data-[active=true]:translate-y-0 data-[active=true]:opacity-100\",\n className\n )}\n type=\"button\"\n >\n {children ?? (direction === \"end\" ? \"↓\" : \"↑\")}\n </button>\n )}\n {...props}\n />\n );\n}\n\nexport type LatestThreadScrollerOutlineItem = {\n id: string;\n label: string;\n messageIds?: string[];\n responsePreview?: string;\n};\n\nexport type LatestThreadScrollerOutlineProps = {\n cardClassName?: string;\n className?: string;\n contentMaxWidth?: number;\n dir?: \"ltr\" | \"rtl\";\n items: LatestThreadScrollerOutlineItem[];\n minContainerWidthForRail?: number;\n minSideGutterForRail?: number;\n side?: \"left\" | \"right\";\n};\n\nexport function LatestThreadScrollerOutline({\n cardClassName,\n className,\n contentMaxWidth = 768,\n dir = \"ltr\",\n items,\n minContainerWidthForRail = 0,\n minSideGutterForRail = 48,\n side,\n}: LatestThreadScrollerOutlineProps) {\n const navRef = React.useRef<HTMLElement | null>(null);\n const layout = useLatestThreadScrollerLayout();\n const [hasSideRoom, setHasSideRoom] = React.useState(false);\n const [hoveredIndex, setHoveredIndex] = React.useState<number | null>(null);\n const { scrollToMessage } = useMessageScroller();\n const { currentAnchorId, visibleMessageIds } = useMessageScrollerVisibility();\n const visibleMessageIdSet = React.useMemo(\n () => new Set(visibleMessageIds),\n [visibleMessageIds]\n );\n const focusIndex = hoveredIndex ?? -1;\n const railSide = side ?? (dir === \"rtl\" ? \"right\" : \"left\");\n\n React.useEffect(() => {\n const root = layout?.rootElement ?? navRef.current?.parentElement;\n if (!root) return;\n\n const updateSideRoom = () => {\n const rootRect = root.getBoundingClientRect();\n const rootWidth = rootRect.width;\n const content = layout?.contentElement;\n const sideGutter = content\n ? Math.max(\n 0,\n railSide === \"left\"\n ? content.getBoundingClientRect().left - rootRect.left\n : rootRect.right - content.getBoundingClientRect().right\n )\n : Math.max(0, (rootWidth - contentMaxWidth) / 2);\n const nextHasSideRoom =\n rootWidth >= minContainerWidthForRail &&\n sideGutter >= minSideGutterForRail;\n setHasSideRoom((current) =>\n current === nextHasSideRoom ? current : nextHasSideRoom\n );\n };\n\n updateSideRoom();\n const resizeObserver = new ResizeObserver(updateSideRoom);\n resizeObserver.observe(root);\n const content = layout?.contentElement;\n if (content) {\n resizeObserver.observe(content);\n }\n return () => resizeObserver.disconnect();\n }, [\n contentMaxWidth,\n layout?.contentElement,\n layout?.rootElement,\n minContainerWidthForRail,\n minSideGutterForRail,\n railSide,\n ]);\n\n if (items.length < 2) {\n return null;\n }\n\n return (\n <nav\n ref={navRef}\n aria-label=\"Transcript outline\"\n className={cx(\n \"pointer-events-none absolute top-[46%] z-10 max-h-[min(18rem,calc(100%-10rem))] w-16 -translate-y-1/2 overflow-visible\",\n hasSideRoom ? \"hidden md:block\" : \"hidden\",\n railSide === \"left\" ? \"left-1\" : \"right-1\",\n className\n )}\n dir={dir}\n >\n <div className=\"pointer-events-auto flex flex-col gap-0 py-1\">\n {items.map((item, index) => {\n const itemMessageIds =\n item.messageIds && item.messageIds.length > 0\n ? item.messageIds\n : [item.id];\n const active = itemMessageIds.some(\n (messageId) =>\n visibleMessageIdSet.has(messageId) || messageId === currentAnchorId\n );\n const distance =\n focusIndex >= 0 ? Math.abs(index - focusIndex) : Number.POSITIVE_INFINITY;\n const isFocused = distance === 0;\n const isNear = distance === 1;\n const isNextNear = distance === 2;\n const barWidth = isFocused\n ? 50\n : isNear\n ? 36\n : isNextNear\n ? 23\n : 10;\n const barOpacity = isFocused ? 1 : isNear ? 0.78 : isNextNear ? 0.58 : 0.36;\n const fallbackLabel = `Turn ${index + 1}`;\n const previewLabel =\n item.label && item.label !== fallbackLabel ? item.label : \"\";\n const responsePreview = (item.responsePreview || \"\").trim();\n\n return (\n <button\n key={item.id}\n type=\"button\"\n data-active={active}\n dir=\"ltr\"\n className={cx(\n \"group relative flex h-2 w-16 items-center rounded-sm outline-none\",\n railSide === \"left\" ? \"justify-start\" : \"justify-end\"\n )}\n aria-label={`Jump to ${item.label || fallbackLabel}`}\n onBlur={() => setHoveredIndex(null)}\n onFocus={() => setHoveredIndex(index)}\n onMouseEnter={() => setHoveredIndex(index)}\n onMouseLeave={() => setHoveredIndex(null)}\n onClick={() =>\n scrollToMessage(item.id, {\n align: \"start\",\n behavior: \"smooth\",\n })\n }\n >\n <span\n className=\"h-0.5 rounded-full bg-muted-foreground/55 transition-[width,background-color,opacity] duration-150 ease-out group-hover:bg-foreground group-focus-visible:bg-foreground group-data-[active=true]:bg-foreground\"\n style={{\n opacity: barOpacity,\n width: barWidth,\n }}\n />\n {previewLabel ? (\n <span\n dir={dir}\n className={cx(\n \"pointer-events-none absolute top-1/2 z-20 max-h-32 w-64 -translate-y-1/2 overflow-hidden rounded-lg border border-border/80 bg-background p-3 text-start opacity-0 shadow-lg transition-all duration-200 group-hover:pointer-events-auto group-hover:opacity-100 group-focus-visible:pointer-events-auto group-focus-visible:opacity-100\",\n railSide === \"left\"\n ? \"left-full ml-2 -translate-x-1 group-hover:translate-x-0 group-focus-visible:translate-x-0\"\n : \"right-full mr-2 translate-x-1 group-hover:translate-x-0 group-focus-visible:translate-x-0\",\n cardClassName\n )}\n >\n <span\n className=\"block overflow-hidden text-sm leading-5 text-foreground\"\n style={{\n display: \"-webkit-box\",\n WebkitBoxOrient: \"vertical\",\n WebkitLineClamp: responsePreview ? 2 : 4,\n }}\n >\n {previewLabel}\n </span>\n {responsePreview ? (\n <span\n className=\"mt-1 block overflow-hidden text-sm leading-5 text-muted-foreground\"\n style={{\n display: \"-webkit-box\",\n WebkitBoxOrient: \"vertical\",\n WebkitLineClamp: 2,\n }}\n >\n {responsePreview}\n </span>\n ) : null}\n </span>\n ) : null}\n </button>\n );\n })}\n </div>\n </nav>\n );\n}\n\nexport const LatestThreadScroller = {\n Provider: LatestThreadScrollerProvider,\n Root: LatestThreadScrollerRoot,\n Viewport: LatestThreadScrollerViewport,\n Content: LatestThreadScrollerContent,\n Item: LatestThreadScrollerItem,\n Button: LatestThreadScrollerButton,\n Outline: LatestThreadScrollerOutline,\n};\n","import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...values: ClassValue[]) {\n return twMerge(clsx(values));\n}\n"],"mappings":"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","names":["React","content","import_jsx_runtime"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./agent-chat-shell";
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import {
|
|
2
|
+
LatestThreadScroller
|
|
3
|
+
} from "../chunk-E3TJ3I6G.js";
|
|
4
|
+
import {
|
|
5
|
+
cn
|
|
6
|
+
} from "../chunk-UU7OXHL3.js";
|
|
7
|
+
|
|
8
|
+
// src/templates/agent-chat-shell.tsx
|
|
9
|
+
import * as React from "react";
|
|
10
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
11
|
+
var defaultOutlineLabel = (content, index) => {
|
|
12
|
+
const label = String(content || "").replace(/\s+/g, " ").trim();
|
|
13
|
+
return label || `Turn ${index + 1}`;
|
|
14
|
+
};
|
|
15
|
+
var defaultOutlinePreview = (content) => String(content || "").replace(/\s+/g, " ").trim();
|
|
16
|
+
function buildAgentChatOutlineItems(messages, getLabel = (message, index) => defaultOutlineLabel(message.content, index), getResponsePreview = (message) => defaultOutlinePreview(message.content)) {
|
|
17
|
+
return messages.reduce((items, message) => {
|
|
18
|
+
if (message.role === "user") {
|
|
19
|
+
items.push({
|
|
20
|
+
id: message.id,
|
|
21
|
+
label: getLabel(message, items.length),
|
|
22
|
+
messageIds: [message.id]
|
|
23
|
+
});
|
|
24
|
+
return items;
|
|
25
|
+
}
|
|
26
|
+
const currentItem = items[items.length - 1];
|
|
27
|
+
currentItem?.messageIds?.push(message.id);
|
|
28
|
+
if (currentItem && !currentItem.responsePreview && message.role === "assistant") {
|
|
29
|
+
currentItem.responsePreview = getResponsePreview(message);
|
|
30
|
+
}
|
|
31
|
+
return items;
|
|
32
|
+
}, []);
|
|
33
|
+
}
|
|
34
|
+
function AgentChatShell({
|
|
35
|
+
className,
|
|
36
|
+
composer,
|
|
37
|
+
composerOverlayClassName,
|
|
38
|
+
composerOverlayHeight,
|
|
39
|
+
contentClassName,
|
|
40
|
+
defaultComposerOverlayHeight = 192,
|
|
41
|
+
dir = "ltr",
|
|
42
|
+
hideComposer = false,
|
|
43
|
+
isLoadingOlder = false,
|
|
44
|
+
messages,
|
|
45
|
+
onLoadOlder,
|
|
46
|
+
outlineItems,
|
|
47
|
+
outlineSide = "left",
|
|
48
|
+
renderMessage,
|
|
49
|
+
renderOlderLoader
|
|
50
|
+
}) {
|
|
51
|
+
const overlayRef = React.useRef(null);
|
|
52
|
+
const [measuredOverlayHeight, setMeasuredOverlayHeight] = React.useState(
|
|
53
|
+
defaultComposerOverlayHeight
|
|
54
|
+
);
|
|
55
|
+
const olderPageRequestRef = React.useRef(false);
|
|
56
|
+
const items = React.useMemo(
|
|
57
|
+
() => outlineItems || buildAgentChatOutlineItems(messages),
|
|
58
|
+
[messages, outlineItems]
|
|
59
|
+
);
|
|
60
|
+
React.useEffect(() => {
|
|
61
|
+
const overlay = overlayRef.current;
|
|
62
|
+
if (!overlay || hideComposer) return;
|
|
63
|
+
const updateHeight = () => {
|
|
64
|
+
setMeasuredOverlayHeight(Math.ceil(overlay.getBoundingClientRect().height));
|
|
65
|
+
};
|
|
66
|
+
updateHeight();
|
|
67
|
+
const observer = new ResizeObserver(updateHeight);
|
|
68
|
+
observer.observe(overlay);
|
|
69
|
+
return () => observer.disconnect();
|
|
70
|
+
}, [hideComposer]);
|
|
71
|
+
const handleScroll = React.useCallback(
|
|
72
|
+
(event) => {
|
|
73
|
+
if (!onLoadOlder || isLoadingOlder || olderPageRequestRef.current || event.currentTarget.scrollTop > 48) {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
olderPageRequestRef.current = true;
|
|
77
|
+
void Promise.resolve(onLoadOlder()).finally(() => {
|
|
78
|
+
olderPageRequestRef.current = false;
|
|
79
|
+
});
|
|
80
|
+
},
|
|
81
|
+
[isLoadingOlder, onLoadOlder]
|
|
82
|
+
);
|
|
83
|
+
const bottomPadding = hideComposer ? 32 : (composerOverlayHeight ?? measuredOverlayHeight) + 72;
|
|
84
|
+
return /* @__PURE__ */ jsx("div", { className: cn("relative flex h-full min-h-0 w-full flex-col", className), dir, children: /* @__PURE__ */ jsxs(LatestThreadScroller.Provider, { children: [
|
|
85
|
+
/* @__PURE__ */ jsxs(LatestThreadScroller.Root, { children: [
|
|
86
|
+
/* @__PURE__ */ jsx(LatestThreadScroller.Viewport, { onScroll: handleScroll, children: /* @__PURE__ */ jsxs(
|
|
87
|
+
LatestThreadScroller.Content,
|
|
88
|
+
{
|
|
89
|
+
className: cn(
|
|
90
|
+
"mx-auto flex min-h-full w-full max-w-3xl flex-col gap-8 px-4 pt-12",
|
|
91
|
+
contentClassName
|
|
92
|
+
),
|
|
93
|
+
style: { paddingBottom: bottomPadding },
|
|
94
|
+
children: [
|
|
95
|
+
isLoadingOlder ? renderOlderLoader?.() : null,
|
|
96
|
+
messages.map((message, index) => /* @__PURE__ */ jsx(
|
|
97
|
+
LatestThreadScroller.Item,
|
|
98
|
+
{
|
|
99
|
+
messageId: message.id,
|
|
100
|
+
scrollAnchor: message.role === "user",
|
|
101
|
+
children: renderMessage(message, index)
|
|
102
|
+
},
|
|
103
|
+
message.id
|
|
104
|
+
))
|
|
105
|
+
]
|
|
106
|
+
}
|
|
107
|
+
) }),
|
|
108
|
+
/* @__PURE__ */ jsx(
|
|
109
|
+
LatestThreadScroller.Outline,
|
|
110
|
+
{
|
|
111
|
+
dir,
|
|
112
|
+
items,
|
|
113
|
+
side: outlineSide
|
|
114
|
+
}
|
|
115
|
+
)
|
|
116
|
+
] }),
|
|
117
|
+
!hideComposer && composer ? /* @__PURE__ */ jsxs(
|
|
118
|
+
"div",
|
|
119
|
+
{
|
|
120
|
+
ref: overlayRef,
|
|
121
|
+
className: cn(
|
|
122
|
+
"pointer-events-none absolute inset-x-0 bottom-0 z-20 overflow-visible px-4 pb-4 pt-10",
|
|
123
|
+
composerOverlayClassName
|
|
124
|
+
),
|
|
125
|
+
style: {
|
|
126
|
+
background: "linear-gradient(to bottom, transparent 0%, color-mix(in oklch, var(--chat-background, var(--background)) 85%, transparent) 45%, var(--chat-background, var(--background)) 65%, var(--chat-background, var(--background)) 100%)"
|
|
127
|
+
},
|
|
128
|
+
children: [
|
|
129
|
+
/* @__PURE__ */ jsx("div", { className: "pointer-events-auto absolute inset-x-0 top-0 flex -translate-y-full justify-center pb-3", children: /* @__PURE__ */ jsx(LatestThreadScroller.Button, {}) }),
|
|
130
|
+
/* @__PURE__ */ jsx("div", { className: "pointer-events-auto mx-auto w-full max-w-3xl", children: composer })
|
|
131
|
+
]
|
|
132
|
+
}
|
|
133
|
+
) : null
|
|
134
|
+
] }) });
|
|
135
|
+
}
|
|
136
|
+
export {
|
|
137
|
+
AgentChatShell,
|
|
138
|
+
buildAgentChatOutlineItems
|
|
139
|
+
};
|
|
140
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/templates/agent-chat-shell.tsx"],"sourcesContent":["import * as React from \"react\";\n\nimport {\n LatestThreadScroller,\n type LatestThreadScrollerOutlineItem,\n} from \"../latest-thread-scroller\";\nimport type { ChatMessage } from \"../types\";\nimport { cn } from \"../ui/utils\";\n\nexport type AgentChatShellMessage = Pick<ChatMessage, \"id\" | \"role\" | \"content\"> & {\n [key: string]: unknown;\n};\n\nexport type AgentChatShellProps<TMessage extends AgentChatShellMessage> = {\n className?: string;\n contentClassName?: string;\n composer?: React.ReactNode;\n composerOverlayClassName?: string;\n composerOverlayHeight?: number;\n defaultComposerOverlayHeight?: number;\n dir?: \"ltr\" | \"rtl\";\n hideComposer?: boolean;\n isLoadingOlder?: boolean;\n messages: TMessage[];\n onLoadOlder?: (() => Promise<unknown> | unknown) | null;\n outlineItems?: LatestThreadScrollerOutlineItem[];\n outlineSide?: \"left\" | \"right\";\n renderMessage: (message: TMessage, index: number) => React.ReactNode;\n renderOlderLoader?: () => React.ReactNode;\n};\n\nconst defaultOutlineLabel = (content: unknown, index: number) => {\n const label = String(content || \"\").replace(/\\s+/g, \" \").trim();\n return label || `Turn ${index + 1}`;\n};\n\nconst defaultOutlinePreview = (content: unknown) =>\n String(content || \"\").replace(/\\s+/g, \" \").trim();\n\nexport function buildAgentChatOutlineItems<TMessage extends AgentChatShellMessage>(\n messages: TMessage[],\n getLabel: (message: TMessage, index: number) => string = (message, index) =>\n defaultOutlineLabel(message.content, index),\n getResponsePreview: (message: TMessage) => string = (message) =>\n defaultOutlinePreview(message.content)\n): LatestThreadScrollerOutlineItem[] {\n return messages.reduce((items, message) => {\n if (message.role === \"user\") {\n items.push({\n id: message.id,\n label: getLabel(message, items.length),\n messageIds: [message.id],\n });\n return items;\n }\n const currentItem = items[items.length - 1];\n currentItem?.messageIds?.push(message.id);\n if (\n currentItem &&\n !currentItem.responsePreview &&\n message.role === \"assistant\"\n ) {\n currentItem.responsePreview = getResponsePreview(message);\n }\n return items;\n }, [] as LatestThreadScrollerOutlineItem[]);\n}\n\nexport function AgentChatShell<TMessage extends AgentChatShellMessage>({\n className,\n composer,\n composerOverlayClassName,\n composerOverlayHeight,\n contentClassName,\n defaultComposerOverlayHeight = 192,\n dir = \"ltr\",\n hideComposer = false,\n isLoadingOlder = false,\n messages,\n onLoadOlder,\n outlineItems,\n outlineSide = \"left\",\n renderMessage,\n renderOlderLoader,\n}: AgentChatShellProps<TMessage>) {\n const overlayRef = React.useRef<HTMLDivElement | null>(null);\n const [measuredOverlayHeight, setMeasuredOverlayHeight] = React.useState(\n defaultComposerOverlayHeight\n );\n const olderPageRequestRef = React.useRef(false);\n const items = React.useMemo(\n () => outlineItems || buildAgentChatOutlineItems(messages),\n [messages, outlineItems]\n );\n\n React.useEffect(() => {\n const overlay = overlayRef.current;\n if (!overlay || hideComposer) return;\n const updateHeight = () => {\n setMeasuredOverlayHeight(Math.ceil(overlay.getBoundingClientRect().height));\n };\n updateHeight();\n const observer = new ResizeObserver(updateHeight);\n observer.observe(overlay);\n return () => observer.disconnect();\n }, [hideComposer]);\n\n const handleScroll = React.useCallback(\n (event: React.UIEvent<HTMLDivElement>) => {\n if (\n !onLoadOlder ||\n isLoadingOlder ||\n olderPageRequestRef.current ||\n event.currentTarget.scrollTop > 48\n ) {\n return;\n }\n olderPageRequestRef.current = true;\n void Promise.resolve(onLoadOlder()).finally(() => {\n olderPageRequestRef.current = false;\n });\n },\n [isLoadingOlder, onLoadOlder]\n );\n\n const bottomPadding = hideComposer\n ? 32\n : (composerOverlayHeight ?? measuredOverlayHeight) + 72;\n\n return (\n <div className={cn(\"relative flex h-full min-h-0 w-full flex-col\", className)} dir={dir}>\n <LatestThreadScroller.Provider>\n <LatestThreadScroller.Root>\n <LatestThreadScroller.Viewport onScroll={handleScroll}>\n <LatestThreadScroller.Content\n className={cn(\n \"mx-auto flex min-h-full w-full max-w-3xl flex-col gap-8 px-4 pt-12\",\n contentClassName\n )}\n style={{ paddingBottom: bottomPadding }}\n >\n {isLoadingOlder ? renderOlderLoader?.() : null}\n {messages.map((message, index) => (\n <LatestThreadScroller.Item\n key={message.id}\n messageId={message.id}\n scrollAnchor={message.role === \"user\"}\n >\n {renderMessage(message, index)}\n </LatestThreadScroller.Item>\n ))}\n </LatestThreadScroller.Content>\n </LatestThreadScroller.Viewport>\n <LatestThreadScroller.Outline\n dir={dir}\n items={items}\n side={outlineSide}\n />\n </LatestThreadScroller.Root>\n\n {!hideComposer && composer ? (\n <div\n ref={overlayRef}\n className={cn(\n \"pointer-events-none absolute inset-x-0 bottom-0 z-20 overflow-visible px-4 pb-4 pt-10\",\n composerOverlayClassName\n )}\n style={{\n background:\n \"linear-gradient(to bottom, transparent 0%, color-mix(in oklch, var(--chat-background, var(--background)) 85%, transparent) 45%, var(--chat-background, var(--background)) 65%, var(--chat-background, var(--background)) 100%)\",\n }}\n >\n <div className=\"pointer-events-auto absolute inset-x-0 top-0 flex -translate-y-full justify-center pb-3\">\n <LatestThreadScroller.Button />\n </div>\n <div className=\"pointer-events-auto mx-auto w-full max-w-3xl\">\n {composer}\n </div>\n </div>\n ) : null}\n </LatestThreadScroller.Provider>\n </div>\n );\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { ChatSubmitInput, ChatTransport } from "./types";
|
|
2
|
+
type MaybePromise<T> = T | Promise<T>;
|
|
3
|
+
export type FetchChatTransportRoutes = {
|
|
4
|
+
listThreads: () => string;
|
|
5
|
+
getThread: (input: {
|
|
6
|
+
threadId: string;
|
|
7
|
+
limit?: number;
|
|
8
|
+
beforeTurnIndex?: number | null;
|
|
9
|
+
includeRunEvents?: boolean;
|
|
10
|
+
}) => string;
|
|
11
|
+
streamMessage: () => string;
|
|
12
|
+
attachRun: (input: {
|
|
13
|
+
runId: string;
|
|
14
|
+
}) => string;
|
|
15
|
+
cancelRun: (input: {
|
|
16
|
+
runId: string;
|
|
17
|
+
}) => string;
|
|
18
|
+
deleteThread?: (input: {
|
|
19
|
+
threadId: string;
|
|
20
|
+
}) => string;
|
|
21
|
+
};
|
|
22
|
+
export type FetchChatTransportOptions = {
|
|
23
|
+
routes: FetchChatTransportRoutes;
|
|
24
|
+
fetchImpl?: typeof fetch;
|
|
25
|
+
headers?: () => MaybePromise<HeadersInit>;
|
|
26
|
+
streamBody?: (input: ChatSubmitInput) => unknown;
|
|
27
|
+
};
|
|
28
|
+
export declare const createFetchChatTransport: ({ routes, fetchImpl, headers, streamBody, }: FetchChatTransportOptions) => ChatTransport;
|
|
29
|
+
export {};
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
import type { ReactNode, RefObject } from "react";
|
|
2
|
+
import type { ContextWindow } from "./context-window";
|
|
3
|
+
export type ChatRunStatus = "queued" | "running" | "completed" | "cancelled" | "failed" | string;
|
|
4
|
+
export type ChatContextWindow = ContextWindow;
|
|
5
|
+
export type ChatCitation = {
|
|
6
|
+
title: string;
|
|
7
|
+
url: string;
|
|
8
|
+
description: string;
|
|
9
|
+
sourceRef?: string;
|
|
10
|
+
ref?: string;
|
|
11
|
+
firstRef?: string;
|
|
12
|
+
totalSegments?: number;
|
|
13
|
+
rangeRef?: string;
|
|
14
|
+
};
|
|
15
|
+
export type ChatAttachment = {
|
|
16
|
+
url?: string;
|
|
17
|
+
filename?: string;
|
|
18
|
+
mediaType?: string;
|
|
19
|
+
contentType?: string;
|
|
20
|
+
[key: string]: unknown;
|
|
21
|
+
};
|
|
22
|
+
export type ChatReasoningStep = {
|
|
23
|
+
label: string;
|
|
24
|
+
status: "active" | "complete" | "pending";
|
|
25
|
+
icon?: unknown;
|
|
26
|
+
description?: string;
|
|
27
|
+
citations?: ChatCitation[];
|
|
28
|
+
query?: string;
|
|
29
|
+
sources?: Array<Record<string, unknown>>;
|
|
30
|
+
};
|
|
31
|
+
export type ChatToolState = "input-streaming" | "input-available" | "output-available" | "output-error" | "cancelled";
|
|
32
|
+
export type ToolPresentation = {
|
|
33
|
+
title?: string | null;
|
|
34
|
+
activity?: string | null;
|
|
35
|
+
detail?: string | null;
|
|
36
|
+
category?: string | null;
|
|
37
|
+
groupKey?: string | null;
|
|
38
|
+
groupLabel?: string | null;
|
|
39
|
+
showOutput?: boolean;
|
|
40
|
+
outputView?: Record<string, unknown> | null;
|
|
41
|
+
[key: string]: unknown;
|
|
42
|
+
};
|
|
43
|
+
export type ChatTextPart = {
|
|
44
|
+
id: string;
|
|
45
|
+
type: "text";
|
|
46
|
+
kind: "text";
|
|
47
|
+
text: string;
|
|
48
|
+
raw?: Record<string, unknown>;
|
|
49
|
+
};
|
|
50
|
+
export type ChatToolPart = {
|
|
51
|
+
id: string;
|
|
52
|
+
type: `tool-${string}`;
|
|
53
|
+
kind: "tool";
|
|
54
|
+
toolName: string;
|
|
55
|
+
toolCallId?: string | null;
|
|
56
|
+
state: ChatToolState;
|
|
57
|
+
input?: unknown;
|
|
58
|
+
output?: unknown;
|
|
59
|
+
errorText?: string | null;
|
|
60
|
+
presentation?: ToolPresentation | null;
|
|
61
|
+
raw: Record<string, unknown>;
|
|
62
|
+
};
|
|
63
|
+
export type ChatReasoningPart = {
|
|
64
|
+
id: string;
|
|
65
|
+
type: "reasoning";
|
|
66
|
+
kind: "reasoning";
|
|
67
|
+
label?: string | null;
|
|
68
|
+
text?: string | null;
|
|
69
|
+
status?: string | null;
|
|
70
|
+
raw: Record<string, unknown>;
|
|
71
|
+
};
|
|
72
|
+
export type ChatUiBlocksPart = {
|
|
73
|
+
id: string;
|
|
74
|
+
type: "ui-blocks";
|
|
75
|
+
kind: "ui-blocks";
|
|
76
|
+
state: ChatToolState;
|
|
77
|
+
toolCallId?: string | null;
|
|
78
|
+
contractVersion?: string | null;
|
|
79
|
+
bundle?: Record<string, unknown> | null;
|
|
80
|
+
errorText?: string | null;
|
|
81
|
+
raw: Record<string, unknown>;
|
|
82
|
+
};
|
|
83
|
+
export type ChatApprovalPart = {
|
|
84
|
+
id: string;
|
|
85
|
+
type: "approval";
|
|
86
|
+
kind: "approval";
|
|
87
|
+
raw: Record<string, unknown>;
|
|
88
|
+
};
|
|
89
|
+
export type ChatErrorPart = {
|
|
90
|
+
id: string;
|
|
91
|
+
type: "error";
|
|
92
|
+
kind: "error";
|
|
93
|
+
errorText: string;
|
|
94
|
+
raw: Record<string, unknown>;
|
|
95
|
+
};
|
|
96
|
+
export type ChatDataPart = {
|
|
97
|
+
id: string;
|
|
98
|
+
type: "data";
|
|
99
|
+
kind: "data";
|
|
100
|
+
name: string;
|
|
101
|
+
data: Record<string, unknown>;
|
|
102
|
+
raw: Record<string, unknown>;
|
|
103
|
+
};
|
|
104
|
+
export type ChatPart = ChatTextPart | ChatToolPart | ChatReasoningPart | ChatUiBlocksPart | ChatApprovalPart | ChatErrorPart | ChatDataPart;
|
|
105
|
+
export type ToolRenderer = (props: {
|
|
106
|
+
part: ChatToolPart;
|
|
107
|
+
message: ChatMessage;
|
|
108
|
+
}) => ReactNode;
|
|
109
|
+
export type Agents24ChatRenderOptions = {
|
|
110
|
+
renderPart?: (part: ChatPart, message: ChatMessage) => ReactNode;
|
|
111
|
+
toolRenderers?: Partial<Record<`tool-${string}`, ToolRenderer>>;
|
|
112
|
+
fallbackToolRenderer?: ToolRenderer;
|
|
113
|
+
};
|
|
114
|
+
export type ChatMessage = {
|
|
115
|
+
id: string;
|
|
116
|
+
role: "user" | "assistant";
|
|
117
|
+
runId?: string | null;
|
|
118
|
+
content: string;
|
|
119
|
+
createdAt: Date;
|
|
120
|
+
isFinal?: boolean;
|
|
121
|
+
parts: ChatPart[];
|
|
122
|
+
attachments?: ChatAttachment[];
|
|
123
|
+
citations?: ChatCitation[];
|
|
124
|
+
reasoningSteps?: ChatReasoningStep[];
|
|
125
|
+
thinkingDurationMs?: number;
|
|
126
|
+
liked?: boolean;
|
|
127
|
+
disliked?: boolean;
|
|
128
|
+
messageIndex?: number;
|
|
129
|
+
isVoice?: boolean;
|
|
130
|
+
tokenUsage?: {
|
|
131
|
+
inputTokens?: number | null;
|
|
132
|
+
outputTokens?: number | null;
|
|
133
|
+
totalTokens?: number | null;
|
|
134
|
+
usageSource?: string | null;
|
|
135
|
+
};
|
|
136
|
+
};
|
|
137
|
+
export type ChatRuntimeEvent = {
|
|
138
|
+
version?: string;
|
|
139
|
+
seq?: number;
|
|
140
|
+
ts?: string;
|
|
141
|
+
event: string;
|
|
142
|
+
run_id?: string;
|
|
143
|
+
stage?: string;
|
|
144
|
+
payload?: Record<string, unknown>;
|
|
145
|
+
diagnostics?: Array<Record<string, unknown>>;
|
|
146
|
+
};
|
|
147
|
+
export type ChatActiveRun = {
|
|
148
|
+
run_id?: string | null;
|
|
149
|
+
status?: string | null;
|
|
150
|
+
started_at?: string | null;
|
|
151
|
+
created_at?: string | null;
|
|
152
|
+
};
|
|
153
|
+
export type ChatThreadSummary = {
|
|
154
|
+
id: string;
|
|
155
|
+
title?: string | null;
|
|
156
|
+
status?: string | null;
|
|
157
|
+
surface?: string | null;
|
|
158
|
+
agent_id?: string | null;
|
|
159
|
+
last_run_id?: string | null;
|
|
160
|
+
last_run_status?: string | null;
|
|
161
|
+
active_run?: ChatActiveRun | null;
|
|
162
|
+
activeRun?: ChatActiveRun | null;
|
|
163
|
+
updated_at?: string | null;
|
|
164
|
+
last_activity_at?: string | null;
|
|
165
|
+
created_at?: string | null;
|
|
166
|
+
messages?: ChatMessage[];
|
|
167
|
+
isHydrated?: boolean;
|
|
168
|
+
hasOlderTurns?: boolean;
|
|
169
|
+
nextBeforeTurnIndex?: number | null;
|
|
170
|
+
lastRunId?: string | null;
|
|
171
|
+
lastRunStatus?: string | null;
|
|
172
|
+
lastEventSeq?: number | null;
|
|
173
|
+
isRunning?: boolean;
|
|
174
|
+
[key: string]: unknown;
|
|
175
|
+
};
|
|
176
|
+
export type ChatThreadTurn = {
|
|
177
|
+
id?: string;
|
|
178
|
+
run_id?: string;
|
|
179
|
+
turn_index?: number;
|
|
180
|
+
status?: string | null;
|
|
181
|
+
user_input_text?: string | null;
|
|
182
|
+
assistant_output_text?: string | null;
|
|
183
|
+
final_output?: unknown;
|
|
184
|
+
response_blocks?: Array<Record<string, unknown>>;
|
|
185
|
+
run_events?: ChatRuntimeEvent[];
|
|
186
|
+
context_window?: unknown;
|
|
187
|
+
run_usage?: {
|
|
188
|
+
source?: string | null;
|
|
189
|
+
input_tokens?: number | null;
|
|
190
|
+
output_tokens?: number | null;
|
|
191
|
+
total_tokens?: number | null;
|
|
192
|
+
} | null;
|
|
193
|
+
attachments?: Array<Record<string, unknown>>;
|
|
194
|
+
created_at?: string | null;
|
|
195
|
+
completed_at?: string | null;
|
|
196
|
+
};
|
|
197
|
+
export type ChatThreadDetail = ChatThreadSummary & {
|
|
198
|
+
turns?: ChatThreadTurn[];
|
|
199
|
+
context_window?: unknown;
|
|
200
|
+
paging?: {
|
|
201
|
+
has_more?: boolean;
|
|
202
|
+
next_before_turn_index?: number | null;
|
|
203
|
+
};
|
|
204
|
+
};
|
|
205
|
+
export type ChatSubmitInput = {
|
|
206
|
+
text: string;
|
|
207
|
+
threadId?: string | null;
|
|
208
|
+
files?: ChatAttachment[];
|
|
209
|
+
signal?: AbortSignal;
|
|
210
|
+
state?: Record<string, unknown>;
|
|
211
|
+
[key: string]: unknown;
|
|
212
|
+
};
|
|
213
|
+
export type ChatSubmitMessage = {
|
|
214
|
+
text: string;
|
|
215
|
+
files?: ChatAttachment[];
|
|
216
|
+
state?: Record<string, unknown>;
|
|
217
|
+
[key: string]: unknown;
|
|
218
|
+
};
|
|
219
|
+
export type ChatTransport = {
|
|
220
|
+
listThreads: (input?: {
|
|
221
|
+
signal?: AbortSignal;
|
|
222
|
+
}) => Promise<{
|
|
223
|
+
items: ChatThreadSummary[];
|
|
224
|
+
total?: number;
|
|
225
|
+
}>;
|
|
226
|
+
getThread: (input: {
|
|
227
|
+
threadId: string;
|
|
228
|
+
limit?: number;
|
|
229
|
+
beforeTurnIndex?: number | null;
|
|
230
|
+
includeRunEvents?: boolean;
|
|
231
|
+
signal?: AbortSignal;
|
|
232
|
+
}) => Promise<ChatThreadDetail>;
|
|
233
|
+
streamMessage: (input: ChatSubmitInput, onEvent: (event: ChatRuntimeEvent) => void | Promise<void>) => Promise<ChatStreamResult>;
|
|
234
|
+
attachRun: (input: {
|
|
235
|
+
runId: string;
|
|
236
|
+
signal?: AbortSignal;
|
|
237
|
+
}, onEvent: (event: ChatRuntimeEvent) => void | Promise<void>) => Promise<ChatStreamResult>;
|
|
238
|
+
cancelRun: (input: {
|
|
239
|
+
runId: string;
|
|
240
|
+
assistantOutputText?: string;
|
|
241
|
+
}) => Promise<{
|
|
242
|
+
run_id?: string;
|
|
243
|
+
status?: string;
|
|
244
|
+
}>;
|
|
245
|
+
deleteThread?: (input: {
|
|
246
|
+
threadId: string;
|
|
247
|
+
}) => Promise<{
|
|
248
|
+
deleted?: boolean;
|
|
249
|
+
}>;
|
|
250
|
+
uploadAttachment?: (input: {
|
|
251
|
+
file: File;
|
|
252
|
+
signal?: AbortSignal;
|
|
253
|
+
}) => Promise<ChatAttachment>;
|
|
254
|
+
};
|
|
255
|
+
export type ChatStreamResult = {
|
|
256
|
+
threadId?: string | null;
|
|
257
|
+
runId?: string | null;
|
|
258
|
+
};
|
|
259
|
+
export type StoredChatThread = ChatThreadSummary & {
|
|
260
|
+
messages: ChatMessage[];
|
|
261
|
+
isHydrated?: boolean;
|
|
262
|
+
hasOlderTurns?: boolean;
|
|
263
|
+
nextBeforeTurnIndex?: number | null;
|
|
264
|
+
};
|
|
265
|
+
export type ChatStorageAdapter = {
|
|
266
|
+
listThreads: () => StoredChatThread[];
|
|
267
|
+
setThreads: (threads: StoredChatThread[]) => void;
|
|
268
|
+
getThread: (threadId: string) => StoredChatThread | undefined;
|
|
269
|
+
upsertThread: (thread: StoredChatThread) => void;
|
|
270
|
+
deleteThread?: (threadId: string) => void;
|
|
271
|
+
getActiveThreadId?: () => string | null;
|
|
272
|
+
setActiveThreadId?: (threadId: string | null) => void;
|
|
273
|
+
};
|
|
274
|
+
export type ChatController = {
|
|
275
|
+
threads: StoredChatThread[];
|
|
276
|
+
activeThreadId: string | null;
|
|
277
|
+
activeThread: StoredChatThread | null;
|
|
278
|
+
messages: ChatMessage[];
|
|
279
|
+
streamingContent: string;
|
|
280
|
+
streamingMessageId: string | null;
|
|
281
|
+
contextStatus: ChatContextWindow | null;
|
|
282
|
+
currentReasoning: ChatReasoningStep[];
|
|
283
|
+
isLoading: boolean;
|
|
284
|
+
isLoadingHistory: boolean;
|
|
285
|
+
isLoadingOlder: boolean;
|
|
286
|
+
isRefreshingThreads: boolean;
|
|
287
|
+
hasOlderTurns: boolean;
|
|
288
|
+
liked: Record<string, boolean>;
|
|
289
|
+
disliked: Record<string, boolean>;
|
|
290
|
+
copiedMessageId: string | null;
|
|
291
|
+
lastThinkingDurationMs: number | null;
|
|
292
|
+
activeRunId: string | null;
|
|
293
|
+
handleSubmit: (message: ChatSubmitMessage) => Promise<void>;
|
|
294
|
+
handleStop: () => void;
|
|
295
|
+
handleCopy: (content: string, messageId: string) => void;
|
|
296
|
+
handleLike: (msg: ChatMessage) => Promise<void>;
|
|
297
|
+
handleDislike: (msg: ChatMessage) => Promise<void>;
|
|
298
|
+
handleRetry: (msg: ChatMessage) => Promise<void>;
|
|
299
|
+
handleSourceClick: (citations: ChatMessage["citations"]) => void;
|
|
300
|
+
upsertLiveVoiceMessage: (input: {
|
|
301
|
+
role: "user" | "assistant";
|
|
302
|
+
content: string;
|
|
303
|
+
isFinal?: boolean;
|
|
304
|
+
citations?: ChatCitation[];
|
|
305
|
+
reasoningSteps?: ChatReasoningStep[];
|
|
306
|
+
}) => void;
|
|
307
|
+
startNewThread: () => void;
|
|
308
|
+
loadThreadById: (threadId: string) => Promise<void>;
|
|
309
|
+
loadOlderTurns: () => Promise<void>;
|
|
310
|
+
refresh: () => Promise<void>;
|
|
311
|
+
textareaRef: RefObject<HTMLTextAreaElement | null>;
|
|
312
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import type { ChatAttachment as Agents24ChatAttachment, ChatMessage as Agents24ChatMessage } from "../types";
|
|
3
|
+
import { Attachment, AttachmentGroup } from "./attachment";
|
|
4
|
+
import { BubbleContent } from "./bubble";
|
|
5
|
+
import { Message } from "./message";
|
|
6
|
+
export type ChatMessageRole = Agents24ChatMessage["role"] | "system" | "data";
|
|
7
|
+
export type ChatMessageProps = Omit<React.ComponentProps<typeof Message>, "align"> & {
|
|
8
|
+
from: ChatMessageRole;
|
|
9
|
+
align?: "start" | "end";
|
|
10
|
+
};
|
|
11
|
+
export declare function ChatMessage(input: ChatMessageProps): React.ReactElement;
|
|
12
|
+
export type ChatMessageContentProps = React.ComponentProps<typeof BubbleContent> & {
|
|
13
|
+
from?: ChatMessageRole;
|
|
14
|
+
};
|
|
15
|
+
export declare function ChatMessageContent({ className, ...props }: ChatMessageContentProps): React.ReactElement;
|
|
16
|
+
export type ChatMessageActionsProps = React.ComponentProps<"div">;
|
|
17
|
+
export declare function ChatMessageActions({ className, ...props }: ChatMessageActionsProps): React.ReactElement;
|
|
18
|
+
export type ChatMessageActionProps = React.ComponentProps<"button"> & {
|
|
19
|
+
label?: string;
|
|
20
|
+
tooltip?: React.ReactNode;
|
|
21
|
+
};
|
|
22
|
+
export declare function ChatMessageAction({ children, className, label, tooltip, type, ...props }: ChatMessageActionProps): React.ReactElement;
|
|
23
|
+
export type ChatAttachmentData = Agents24ChatAttachment & {
|
|
24
|
+
type?: string;
|
|
25
|
+
name?: string;
|
|
26
|
+
mediaType?: string;
|
|
27
|
+
contentType?: string;
|
|
28
|
+
};
|
|
29
|
+
export type ChatAttachmentProps = React.ComponentProps<typeof Attachment> & {
|
|
30
|
+
data: ChatAttachmentData;
|
|
31
|
+
onRemove?: () => void;
|
|
32
|
+
};
|
|
33
|
+
export declare function ChatAttachment({ data, onRemove, orientation, ...props }: ChatAttachmentProps): React.ReactElement;
|
|
34
|
+
export type ChatAttachmentsProps = React.ComponentProps<typeof AttachmentGroup>;
|
|
35
|
+
export declare function ChatAttachments({ children, className, ...props }: ChatAttachmentsProps): React.ReactElement | null;
|
|
36
|
+
export { ChatAttachment as MessageAttachment, ChatAttachments as MessageAttachments, ChatMessage as Message, ChatMessageAction as MessageAction, ChatMessageActions as MessageActions, ChatMessageContent as MessageContent, };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { type VariantProps } from "class-variance-authority";
|
|
3
|
+
declare const attachmentVariants: (props?: ({
|
|
4
|
+
size?: "default" | "sm" | "xs" | null | undefined;
|
|
5
|
+
orientation?: "horizontal" | "vertical" | null | undefined;
|
|
6
|
+
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
7
|
+
declare function Attachment({ className, state, size, orientation, ...props }: React.ComponentProps<"div"> & VariantProps<typeof attachmentVariants> & {
|
|
8
|
+
state?: "idle" | "uploading" | "processing" | "error" | "done";
|
|
9
|
+
}): React.JSX.Element;
|
|
10
|
+
declare const attachmentMediaVariants: (props?: ({
|
|
11
|
+
variant?: "image" | "icon" | null | undefined;
|
|
12
|
+
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
13
|
+
declare function AttachmentMedia({ className, variant, ...props }: React.ComponentProps<"div"> & VariantProps<typeof attachmentMediaVariants>): React.JSX.Element;
|
|
14
|
+
declare function AttachmentContent({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
|
|
15
|
+
declare function AttachmentTitle({ className, ...props }: React.ComponentProps<"span">): React.JSX.Element;
|
|
16
|
+
declare function AttachmentDescription({ className, ...props }: React.ComponentProps<"span">): React.JSX.Element;
|
|
17
|
+
declare function AttachmentActions({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
|
|
18
|
+
declare function AttachmentAction({ className, type, ...props }: React.ComponentProps<"button">): React.JSX.Element;
|
|
19
|
+
declare function AttachmentTrigger({ className, asChild, type, ...props }: React.ComponentProps<"button"> & {
|
|
20
|
+
asChild?: boolean;
|
|
21
|
+
}): React.JSX.Element;
|
|
22
|
+
declare function AttachmentGroup({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
|
|
23
|
+
export { Attachment, AttachmentGroup, AttachmentMedia, AttachmentContent, AttachmentTitle, AttachmentDescription, AttachmentActions, AttachmentAction, AttachmentTrigger, attachmentVariants, attachmentMediaVariants, };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { type VariantProps } from "class-variance-authority";
|
|
3
|
+
declare function BubbleGroup({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
|
|
4
|
+
declare const bubbleVariants: (props?: ({
|
|
5
|
+
variant?: "default" | "secondary" | "muted" | "tinted" | "outline" | "ghost" | "destructive" | null | undefined;
|
|
6
|
+
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
7
|
+
declare function Bubble({ variant, align, className, ...props }: React.ComponentProps<"div"> & VariantProps<typeof bubbleVariants> & {
|
|
8
|
+
align?: "start" | "end";
|
|
9
|
+
}): React.JSX.Element;
|
|
10
|
+
declare function BubbleContent({ asChild, className, ...props }: React.ComponentProps<"div"> & {
|
|
11
|
+
asChild?: boolean;
|
|
12
|
+
}): React.JSX.Element;
|
|
13
|
+
declare function BubbleReactions({ side, align, className, ...props }: React.ComponentProps<"div"> & {
|
|
14
|
+
align?: "start" | "end";
|
|
15
|
+
side?: "top" | "bottom";
|
|
16
|
+
}): React.JSX.Element;
|
|
17
|
+
export { BubbleGroup, Bubble, BubbleContent, BubbleReactions, bubbleVariants };
|