@agents24/chat-react 0.1.9 → 0.1.10

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.
@@ -1 +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":[]}
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 AgentChatShellScrollState = {\n canScroll: boolean;\n isScrolled: boolean;\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 emptyInputAttachmentCount?: number;\n emptyTitle?: string;\n hideComposer?: boolean;\n isLoadingOlder?: boolean;\n messages: TMessage[];\n onLoadOlder?: (() => Promise<unknown> | unknown) | null;\n onScrollStateChange?: (state: AgentChatShellScrollState) => void;\n outlineItems?: LatestThreadScrollerOutlineItem[];\n outlineSide?: \"left\" | \"right\";\n renderEmptyState?: (input: { composer?: React.ReactNode; title: string }) => React.ReactNode;\n renderMessage: (message: TMessage, index: number) => React.ReactNode;\n renderOlderLoader?: () => React.ReactNode;\n};\n\nexport function getAgentChatShellScrollState(\n viewport: Pick<HTMLElement, \"clientHeight\" | \"scrollHeight\" | \"scrollTop\">\n): AgentChatShellScrollState {\n const canScroll = viewport.scrollHeight - viewport.clientHeight > 1;\n return {\n canScroll,\n isScrolled: canScroll && viewport.scrollTop > 4,\n };\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 emptyInputAttachmentCount = 0,\n emptyTitle = \"Ready when you are.\",\n hideComposer = false,\n isLoadingOlder = false,\n messages,\n onLoadOlder,\n onScrollStateChange,\n outlineItems,\n outlineSide = \"left\",\n renderEmptyState,\n renderMessage,\n renderOlderLoader,\n}: AgentChatShellProps<TMessage>) {\n const overlayRef = React.useRef<HTMLDivElement | null>(null);\n const viewportRef = React.useRef<HTMLElement | null>(null);\n const contentRef = React.useRef<HTMLDivElement | null>(null);\n const lastScrollStateRef = React.useRef<AgentChatShellScrollState | 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 const updateScrollState = React.useCallback(() => {\n const viewport = viewportRef.current;\n if (!viewport || !onScrollStateChange) return;\n const next = getAgentChatShellScrollState(viewport);\n const previous = lastScrollStateRef.current;\n if (\n previous &&\n previous.canScroll === next.canScroll &&\n previous.isScrolled === next.isScrolled\n ) {\n return;\n }\n lastScrollStateRef.current = next;\n onScrollStateChange(next);\n }, [onScrollStateChange]);\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 React.useEffect(() => {\n if (!onScrollStateChange) return;\n updateScrollState();\n const viewport = viewportRef.current;\n const content = contentRef.current;\n if (!viewport || typeof ResizeObserver === \"undefined\") return;\n const observer = new ResizeObserver(updateScrollState);\n observer.observe(viewport);\n if (content) observer.observe(content);\n return () => observer.disconnect();\n }, [messages, onScrollStateChange, updateScrollState]);\n\n const handleScroll = React.useCallback(\n (event: React.UIEvent<HTMLDivElement>) => {\n updateScrollState();\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, updateScrollState]\n );\n\n const bottomPadding = hideComposer\n ? 32\n : (composerOverlayHeight ?? measuredOverlayHeight) + 72;\n const isEmptyState = messages.length === 0;\n\n if (isEmptyState) {\n return (\n <div className={cn(\"relative flex h-full min-h-0 w-full flex-col overflow-visible px-4\", className)} dir={dir}>\n {renderEmptyState ? (\n renderEmptyState({ composer: hideComposer ? undefined : composer, title: emptyTitle })\n ) : (\n <div className=\"relative z-10 flex h-full flex-1 flex-col justify-center p-0 pt-13\">\n <div className=\"flex w-full flex-col items-center pb-34 text-center animate-in fade-in slide-in-from-bottom-4 duration-500\">\n <p\n className={cn(\n \"pb-6 text-3xl font-semibold transition-transform duration-200\",\n emptyInputAttachmentCount > 0 && \"-translate-y-12\"\n )}\n >\n {emptyTitle}\n </p>\n {!hideComposer && composer ? (\n <div className=\"mx-auto w-full max-w-3xl px-4\">{composer}</div>\n ) : null}\n </div>\n </div>\n )}\n </div>\n );\n }\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\n onScroll={handleScroll}\n onViewportChange={(node) => {\n viewportRef.current = node;\n updateScrollState();\n }}\n >\n <LatestThreadScroller.Content\n ref={contentRef}\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 px-4\">\n {composer}\n </div>\n </div>\n ) : null}\n </LatestThreadScroller.Provider>\n </div>\n );\n}\n"],"mappings":"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","names":[]}
@@ -18,6 +18,16 @@ export type FetchChatTransportRoutes = {
18
18
  deleteThread?: (input: {
19
19
  threadId: string;
20
20
  }) => string;
21
+ threadEvents?: (input: {
22
+ cursor?: number | null;
23
+ }) => string;
24
+ resumeRun?: (input: {
25
+ runId: string;
26
+ }) => string;
27
+ startMcpAuth?: (input: {
28
+ runId: string;
29
+ serverId: string;
30
+ }) => string;
21
31
  };
22
32
  export type FetchChatTransportOptions = {
23
33
  routes: FetchChatTransportRoutes;
@@ -25,5 +35,9 @@ export type FetchChatTransportOptions = {
25
35
  headers?: () => MaybePromise<HeadersInit>;
26
36
  streamBody?: (input: ChatSubmitInput) => unknown;
27
37
  };
38
+ export declare class ChatTransportError extends Error {
39
+ status: number;
40
+ constructor(message: string, status: number);
41
+ }
28
42
  export declare const createFetchChatTransport: ({ routes, fetchImpl, headers, streamBody, }: FetchChatTransportOptions) => ChatTransport;
29
43
  export {};
package/dist/types.d.ts CHANGED
@@ -80,10 +80,13 @@ export type ChatUiBlocksPart = {
80
80
  errorText?: string | null;
81
81
  raw: Record<string, unknown>;
82
82
  };
83
- export type ChatApprovalPart = {
83
+ export type ChatHitlPart = {
84
84
  id: string;
85
- type: "approval";
86
- kind: "approval";
85
+ type: "hitl";
86
+ kind: "hitl";
87
+ hitl: Record<string, unknown>;
88
+ interruptId?: string | null;
89
+ hitlKind?: string | null;
87
90
  raw: Record<string, unknown>;
88
91
  };
89
92
  export type ChatErrorPart = {
@@ -101,7 +104,7 @@ export type ChatDataPart = {
101
104
  data: Record<string, unknown>;
102
105
  raw: Record<string, unknown>;
103
106
  };
104
- export type ChatPart = ChatTextPart | ChatToolPart | ChatReasoningPart | ChatUiBlocksPart | ChatApprovalPart | ChatErrorPart | ChatDataPart;
107
+ export type ChatPart = ChatTextPart | ChatToolPart | ChatReasoningPart | ChatUiBlocksPart | ChatHitlPart | ChatErrorPart | ChatDataPart;
105
108
  export type ToolRenderer = (props: {
106
109
  part: ChatToolPart;
107
110
  message: ChatMessage;
@@ -173,6 +176,22 @@ export type ChatThreadSummary = {
173
176
  isRunning?: boolean;
174
177
  [key: string]: unknown;
175
178
  };
179
+ export type ChatThreadSummaryEvent = {
180
+ schema_version?: string;
181
+ event: "thread.summary.updated";
182
+ cursor?: number;
183
+ thread: ChatThreadSummary;
184
+ } | {
185
+ schema_version?: string;
186
+ event: "thread.deleted";
187
+ cursor?: number;
188
+ thread_id: string;
189
+ } | {
190
+ schema_version?: string;
191
+ event: "snapshot_required";
192
+ cursor?: number;
193
+ reason?: string;
194
+ };
176
195
  export type ChatThreadTurn = {
177
196
  id?: string;
178
197
  run_id?: string;
@@ -216,6 +235,32 @@ export type ChatSubmitMessage = {
216
235
  state?: Record<string, unknown>;
217
236
  [key: string]: unknown;
218
237
  };
238
+ export type ChatHitlDecisionType = "approve" | "edit" | "reject" | "respond" | "connect" | string;
239
+ export type ChatHitlResumeDecision = {
240
+ type: ChatHitlDecisionType;
241
+ action_id?: string | null;
242
+ message?: string;
243
+ response?: string;
244
+ edited_action?: Record<string, unknown>;
245
+ [key: string]: unknown;
246
+ };
247
+ export type ChatHitlResumeInput = {
248
+ runId: string;
249
+ interruptId: string;
250
+ decisions: ChatHitlResumeDecision[];
251
+ client?: Record<string, unknown>;
252
+ };
253
+ export type ChatMcpAuthStartInput = {
254
+ runId: string;
255
+ interruptId?: string | null;
256
+ serverId: string;
257
+ principalType?: string | null;
258
+ principalId?: string | null;
259
+ client?: Record<string, unknown>;
260
+ };
261
+ export type ChatMcpAuthStartResult = {
262
+ authorization_url: string;
263
+ };
219
264
  export type ChatTransport = {
220
265
  listThreads: (input?: {
221
266
  signal?: AbortSignal;
@@ -251,6 +296,16 @@ export type ChatTransport = {
251
296
  file: File;
252
297
  signal?: AbortSignal;
253
298
  }) => Promise<ChatAttachment>;
299
+ resumeHitl?: (input: ChatHitlResumeInput) => Promise<{
300
+ run_id?: string;
301
+ status?: string;
302
+ thread_id?: string | null;
303
+ }>;
304
+ startMcpAuth?: (input: ChatMcpAuthStartInput) => Promise<ChatMcpAuthStartResult>;
305
+ subscribeThreadEvents?: (input: {
306
+ cursor?: number | null;
307
+ signal?: AbortSignal;
308
+ }, onEvent: (event: ChatThreadSummaryEvent) => void | Promise<void>) => Promise<void>;
254
309
  };
255
310
  export type ChatStreamResult = {
256
311
  threadId?: string | null;
@@ -284,6 +339,7 @@ export type ChatController = {
284
339
  isLoadingHistory: boolean;
285
340
  isLoadingOlder: boolean;
286
341
  isRefreshingThreads: boolean;
342
+ isSelectingThread: boolean;
287
343
  hasOlderTurns: boolean;
288
344
  liked: Record<string, boolean>;
289
345
  disliked: Record<string, boolean>;
@@ -291,6 +347,7 @@ export type ChatController = {
291
347
  lastThinkingDurationMs: number | null;
292
348
  activeRunId: string | null;
293
349
  handleSubmit: (message: ChatSubmitMessage) => Promise<void>;
350
+ attachRun: (runId: string, threadId?: string | null) => Promise<void>;
294
351
  handleStop: () => void;
295
352
  handleCopy: (content: string, messageId: string) => void;
296
353
  handleLike: (msg: ChatMessage) => Promise<void>;
@@ -1,7 +1,6 @@
1
1
  import * as React from "react";
2
2
  import type { ChatAttachment as Agents24ChatAttachment, ChatMessage as Agents24ChatMessage } from "../types";
3
3
  import { Attachment, AttachmentGroup } from "./attachment";
4
- import { BubbleContent } from "./bubble";
5
4
  import { Message } from "./message";
6
5
  export type ChatMessageRole = Agents24ChatMessage["role"] | "system" | "data";
7
6
  export type ChatMessageProps = Omit<React.ComponentProps<typeof Message>, "align"> & {
@@ -9,7 +8,7 @@ export type ChatMessageProps = Omit<React.ComponentProps<typeof Message>, "align
9
8
  align?: "start" | "end";
10
9
  };
11
10
  export declare function ChatMessage(input: ChatMessageProps): React.ReactElement;
12
- export type ChatMessageContentProps = React.ComponentProps<typeof BubbleContent> & {
11
+ export type ChatMessageContentProps = React.ComponentProps<"div"> & {
13
12
  from?: ChatMessageRole;
14
13
  };
15
14
  export declare function ChatMessageContent({ className, ...props }: ChatMessageContentProps): React.ReactElement;
@@ -0,0 +1,16 @@
1
+ import * as React from "react";
2
+ import type { ChatMessage } from "../types";
3
+ export type AgentChatMessageActionHandlers = {
4
+ copied?: boolean;
5
+ disliked?: boolean;
6
+ liked?: boolean;
7
+ onCopy?: (content: string, messageId: string) => void;
8
+ onDislike?: (message: ChatMessage) => void | Promise<void>;
9
+ onLike?: (message: ChatMessage) => void | Promise<void>;
10
+ onRetry?: (message: ChatMessage) => void | Promise<void>;
11
+ };
12
+ export type AgentChatDefaultActionsProps = {
13
+ handlers?: AgentChatMessageActionHandlers;
14
+ message: ChatMessage;
15
+ };
16
+ export declare function AgentChatDefaultActions({ handlers, message, }: AgentChatDefaultActionsProps): React.JSX.Element | null;
@@ -0,0 +1,28 @@
1
+ import * as React from "react";
2
+ import type { ChatAttachment } from "../types";
3
+ export type AgentChatComposerFile = ChatAttachment & {
4
+ id: string;
5
+ type: "file";
6
+ url: string;
7
+ filename: string;
8
+ mediaType: string;
9
+ };
10
+ export type AgentChatComposerSubmit = {
11
+ text: string;
12
+ files: AgentChatComposerFile[];
13
+ };
14
+ export type AgentChatComposerProps = {
15
+ accept?: string;
16
+ allowAttachments?: boolean;
17
+ attachmentLayout?: "flow" | "overlay";
18
+ className?: string;
19
+ disabled?: boolean;
20
+ inputToolbarContent?: React.ReactNode;
21
+ isRunning?: boolean;
22
+ onAttachmentCountChange?: (count: number) => void;
23
+ onStop?: () => void;
24
+ onSubmit: (message: AgentChatComposerSubmit) => Promise<void> | void;
25
+ placeholder?: string;
26
+ textareaRef?: React.Ref<HTMLTextAreaElement>;
27
+ };
28
+ export declare function AgentChatComposer({ accept, allowAttachments, attachmentLayout, className, disabled, inputToolbarContent, isRunning, onAttachmentCountChange, onStop, onSubmit, placeholder, textareaRef, }: AgentChatComposerProps): React.JSX.Element;
@@ -0,0 +1,40 @@
1
+ import * as React from "react";
2
+ import type { ChatHitlPart, ChatMessage, ChatPart } from "../types";
3
+ import { type AgentChatMessageActionHandlers } from "./agent-chat-actions";
4
+ import { type AgentChatPartActionState } from "./agent-response-timeline";
5
+ export type AgentChatUserMessageContentProps = {
6
+ collapsedLines?: number;
7
+ collapseThreshold?: number | null;
8
+ content: string;
9
+ showLessLabel?: string;
10
+ showMoreLabel?: string;
11
+ };
12
+ export type AgentChatMessageProps = {
13
+ actionHandlers?: AgentChatMessageActionHandlers;
14
+ actions?: React.ReactNode;
15
+ actionsClassName?: string;
16
+ className?: string;
17
+ contentClassName?: string;
18
+ dir?: "ltr" | "rtl";
19
+ getHitlActionState?: (part: ChatHitlPart) => AgentChatPartActionState | undefined;
20
+ message: ChatMessage;
21
+ onHitlAction?: (part: ChatHitlPart, decision: string) => void;
22
+ renderAssistantContent?: (input: {
23
+ isStreaming: boolean;
24
+ message: ChatMessage;
25
+ }) => React.ReactNode;
26
+ renderPart?: (part: ChatPart, message: ChatMessage) => React.ReactNode;
27
+ renderUserContent?: (input: {
28
+ message: ChatMessage;
29
+ }) => React.ReactNode;
30
+ showAssistantAttachments?: boolean;
31
+ streamingMessageId?: string | null;
32
+ userMessageCollapsedLines?: number;
33
+ userMessageContent?: string;
34
+ userMessageCollapseThreshold?: number | null;
35
+ userMessageShowLessLabel?: string;
36
+ userMessageShowMoreLabel?: string;
37
+ };
38
+ export declare function shouldCollapseUserMessage(content: string, threshold?: number | null | undefined): boolean;
39
+ export declare function AgentChatUserMessageContent({ collapsedLines, collapseThreshold, content, showLessLabel, showMoreLabel, }: AgentChatUserMessageContentProps): React.JSX.Element;
40
+ export declare function AgentChatMessage({ actionHandlers, actions, actionsClassName, className, contentClassName, dir, getHitlActionState, message, onHitlAction, renderAssistantContent, renderPart, renderUserContent, showAssistantAttachments, streamingMessageId, userMessageCollapsedLines, userMessageContent, userMessageCollapseThreshold, userMessageShowLessLabel, userMessageShowMoreLabel, }: AgentChatMessageProps): React.JSX.Element;
@@ -0,0 +1,24 @@
1
+ import * as React from "react";
2
+ import type { ChatHitlPart, ChatMessage, ChatPart } from "../types";
3
+ import { type McpConnectRequiredStatus } from "./mcp-connect-required-card";
4
+ export type AgentChatPartActionState = {
5
+ status?: McpConnectRequiredStatus | string;
6
+ error?: string | null;
7
+ };
8
+ export type AgentResponseTimelineProps = {
9
+ getHitlActionState?: (part: ChatHitlPart) => AgentChatPartActionState | undefined;
10
+ isLoading?: boolean;
11
+ message: ChatMessage;
12
+ onHitlAction?: (part: ChatHitlPart, decision: string) => void;
13
+ renderPart?: (part: ChatPart, message: ChatMessage) => React.ReactNode;
14
+ };
15
+ declare function DefaultPartRow({ activeToolId, getHitlActionState, isLoading, message, onHitlAction, part, }: {
16
+ activeToolId?: string | null;
17
+ getHitlActionState?: AgentResponseTimelineProps["getHitlActionState"];
18
+ isLoading?: boolean;
19
+ message: ChatMessage;
20
+ onHitlAction?: AgentResponseTimelineProps["onHitlAction"];
21
+ part: ChatPart;
22
+ }): React.JSX.Element | null;
23
+ export declare function AgentResponseTimeline({ getHitlActionState, isLoading, message, onHitlAction, renderPart, }: AgentResponseTimelineProps): React.JSX.Element;
24
+ export { DefaultPartRow as AgentChatPartRow };