+
+
- ) : null,
- Footer: () => (
-
- {/* Live tool calls during streaming */}
- {toolCalls.length > 0 && (
-
- {toolCalls.map((tc) => (
-
-
- toggleToolCall(tc.toolCallId)}
- />
-
-
- ))}
-
- )}
-
- {streamingContent && (
-
- )}
-
- {isSending && !streamingContent && toolCalls.length === 0 && (
-
- )}
+
+ Start a conversation
+
+
+ Send a message to start chatting with {agent.name}.
+
- ),
- }}
- itemContent={(_index, message) => {
- // Parse tool output safely
- const getToolOutput = () => {
- if (message.toolResult) return message.toolResult;
- try {
- return JSON.parse(message.content || '{}');
- } catch {
- return { result: message.content };
- }
- };
-
- // Build a lookup map for tool call inputs from ASSISTANT messages
- // This allows us to show the input args when rendering TOOL messages
- const getToolCallInput = (toolCallId: string): unknown => {
- for (const msg of messages) {
- if (msg.role === 'ASSISTANT' && msg.toolCalls) {
- const tc = msg.toolCalls.find((t) => t.toolCallId === toolCallId);
- if (tc) return tc.args;
- }
- }
- return undefined;
- };
-
- // Check if a tool call has a corresponding TOOL message (meaning it completed)
- const hasToolResult = (toolCallId: string): boolean => {
- return messages.some((m) => m.role === 'TOOL' && m.toolCallId === toolCallId);
- };
-
- return (
-
- {/* TOOL message - shows the result of a tool call */}
- {message.role === 'TOOL' && (
-
-
- toggleToolCall(message.toolCallId || message.id)}
- />
-
-
- )}
-
- {/* USER message */}
- {message.role === 'USER' && (
-
- )}
-
- {/* ASSISTANT message - may contain text and/or tool calls */}
- {message.role === 'ASSISTANT' && (
-
- {/* Assistant text content */}
- {message.content && (
-
-
-
{message.content}
- {/* Token usage for debugging */}
- {(message.inputTokens || message.outputTokens) && (
-
- {message.inputTokens && In: {message.inputTokens}}
- {message.inputTokens && message.outputTokens && (
- •
- )}
- {message.outputTokens && (
- Out: {message.outputTokens}
- )}
-
- )}
+
+ ) : (
+
+ hasMoreMessages ? (
+
+ {isLoadingMore ? (
+
+
+ Loading older messages...
-
- )}
-
- {/* Show tool calls from this assistant message that don't have results yet */}
- {message.toolCalls &&
- message.toolCalls
- .filter((tc) => !hasToolResult(tc.toolCallId))
- .map((tc) => (
+ ) : (
+
+ )}
+
+ ) : null,
+ Footer: () => (
+
+ {/* Live tool calls during streaming */}
+ {toolCalls.length > 0 && (
+
+ {toolCalls.map((tc) => (
toggleToolCall(tc.toolCallId)}
/>
))}
+
+ )}
+
+ {streamingContent && (
+
+ )}
+
+ {isSending && !streamingContent && toolCalls.length === 0 && (
+
+ )}
- )}
-
- );
- }}
- />
- )}
-
+ ),
+ }}
+ itemContent={(_index, message) => {
+ // Parse tool output safely
+ const getToolOutput = () => {
+ if (message.toolResult) return message.toolResult;
+ try {
+ return JSON.parse(message.content || '{}');
+ } catch {
+ return { result: message.content };
+ }
+ };
- {/* Error Message */}
- {error && (
-
- )}
+ // Build a lookup map for tool call inputs from ASSISTANT messages
+ // This allows us to show the input args when rendering TOOL messages
+ // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: Helper in virtuoso render callback
+ const getToolCallInput = (toolCallId: string): unknown => {
+ for (const msg of messages) {
+ if (msg.role === 'ASSISTANT' && msg.toolCalls) {
+ const tc = msg.toolCalls.find((t) => t.toolCallId === toolCallId);
+ if (tc) return tc.args;
+ }
+ }
+ return undefined;
+ };
- {/* Input Area */}
-
-
-
-
- Press Enter to send, Shift+Enter for new line
-
-
+ // Check if a tool call has a corresponding TOOL message (meaning it completed)
+ const hasToolResult = (toolCallId: string): boolean => {
+ return messages.some(
+ (m) => m.role === 'TOOL' && m.toolCallId === toolCallId
+ );
+ };
+
+ return (
+
+ {/* TOOL message - shows the result of a tool call */}
+ {message.role === 'TOOL' && (
+
+
+ toggleToolCall(message.toolCallId || message.id)}
+ />
+
+
+ )}
+
+ {/* USER message */}
+ {message.role === 'USER' && (
+
+ )}
+
+ {/* ASSISTANT message - may contain text and/or tool calls */}
+ {message.role === 'ASSISTANT' && (
+
+ {/* Assistant text content */}
+ {message.content && (
+
+
+
{message.content}
+ {/* Token usage for debugging */}
+ {(message.inputTokens || message.outputTokens) && (
+
+ {message.inputTokens && (
+ In: {message.inputTokens}
+ )}
+ {message.inputTokens && message.outputTokens && (
+ •
+ )}
+ {message.outputTokens && (
+ Out: {message.outputTokens}
+ )}
+
+ )}
+
+
+ )}
+
+ {/* Show tool calls from this assistant message that don't have results yet */}
+ {message.toolCalls
+ ?.filter((tc) => !hasToolResult(tc.toolCallId))
+ .map((tc) => (
+
+
+ toggleToolCall(tc.toolCallId)}
+ />
+
+
+ ))}
+
+ )}
+
+ );
+ }}
+ />
+ )}
+
+
+ {/* Error Message */}
+ {error && (
+
+
+
+
+ Press Enter to send, Shift+Enter for new line
+
+