@tanstack/ai-devtools-core 0.2.3 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import { ContentPartSource } from '@tanstack/ai';
|
|
1
2
|
import { ParentComponent } from 'solid-js';
|
|
2
3
|
interface MessagePart {
|
|
3
|
-
type: 'text' | 'tool-call' | 'tool-result' | 'thinking';
|
|
4
|
+
type: 'text' | 'tool-call' | 'tool-result' | 'thinking' | 'image' | 'audio' | 'video' | 'document';
|
|
4
5
|
content?: string;
|
|
5
6
|
toolCallId?: string;
|
|
6
7
|
toolName?: string;
|
|
@@ -8,6 +9,8 @@ interface MessagePart {
|
|
|
8
9
|
state?: string;
|
|
9
10
|
output?: unknown;
|
|
10
11
|
error?: string;
|
|
12
|
+
source?: ContentPartSource;
|
|
13
|
+
metadata?: unknown;
|
|
11
14
|
}
|
|
12
15
|
export interface ToolCall {
|
|
13
16
|
id: string;
|
|
@@ -329,11 +329,22 @@ const AIProvider = (props) => {
|
|
|
329
329
|
error: part.error
|
|
330
330
|
};
|
|
331
331
|
}
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
332
|
+
if (part.type === "thinking") {
|
|
333
|
+
return {
|
|
334
|
+
type: "thinking",
|
|
335
|
+
content: part.content
|
|
336
|
+
};
|
|
337
|
+
}
|
|
338
|
+
if (part.type === "image" || part.type === "audio" || part.type === "video" || // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
339
|
+
part.type === "document") {
|
|
340
|
+
return {
|
|
341
|
+
type: part.type,
|
|
342
|
+
source: part.source,
|
|
343
|
+
metadata: part.metadata
|
|
344
|
+
};
|
|
345
|
+
}
|
|
346
|
+
return null;
|
|
347
|
+
}).filter((part) => part !== null);
|
|
337
348
|
const toolCalls = e.payload.toolCalls?.map((toolCall) => ({
|
|
338
349
|
id: toolCall.id,
|
|
339
350
|
name: toolCall.function.name,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ai-context.js","sources":["../../../src/store/ai-context.tsx"],"sourcesContent":["import { batch, createContext, onCleanup, onMount, useContext } from 'solid-js'\nimport { createStore, produce } from 'solid-js/store'\nimport { aiEventClient } from '@tanstack/ai/event-client'\nimport type { ParentComponent } from 'solid-js'\n\ninterface MessagePart {\n type: 'text' | 'tool-call' | 'tool-result' | 'thinking'\n content?: string\n toolCallId?: string\n toolName?: string\n arguments?: string\n state?: string\n output?: unknown\n error?: string\n}\n\nexport interface ToolCall {\n id: string\n name: string\n arguments: string\n state: string\n result?: unknown\n approvalRequired?: boolean\n approvalId?: string\n /** Duration of tool execution in milliseconds */\n duration?: number\n}\n\ninterface TokenUsage {\n promptTokens: number\n completionTokens: number\n totalTokens: number\n}\n\nexport interface Message {\n id: string\n role: 'user' | 'assistant' | 'system' | 'tool'\n content: string\n timestamp: number\n parts?: Array<MessagePart>\n toolCalls?: Array<ToolCall>\n /** Consolidated chunks - consecutive same-type chunks are merged into one entry */\n chunks?: Array<Chunk>\n /** Total number of raw chunks received (before consolidation) */\n totalChunkCount?: number\n model?: string\n usage?: TokenUsage\n thinkingContent?: string\n /** Source of the message: 'client' for aggregated client-side data, 'server' for individual server chunks */\n source?: 'client' | 'server'\n}\n\n/**\n * Consolidated chunk - represents one or more raw chunks of the same type.\n * Consecutive content/thinking chunks are merged into a single entry with accumulated content.\n */\nexport interface Chunk {\n id: string\n type:\n | 'content'\n | 'tool_call'\n | 'tool_result'\n | 'done'\n | 'error'\n | 'approval'\n | 'thinking'\n timestamp: number\n messageId?: string\n /** Accumulated content from all merged chunks */\n content?: string\n /** The last delta received (kept for debugging) */\n delta?: string\n toolName?: string\n toolCallId?: string\n finishReason?: string\n error?: string\n approvalId?: string\n input?: unknown\n /** Tool arguments for tool_call chunks */\n arguments?: string\n /** Tool result data for tool_result chunks */\n result?: unknown\n /** Duration in ms for tool execution */\n duration?: number\n /** Number of raw chunks that were merged into this consolidated chunk */\n chunkCount: number\n /** Whether this is a client-side tool execution */\n isClientTool?: boolean\n}\n\nexport interface SummarizeOperation {\n id: string\n model: string\n inputLength: number\n outputLength?: number\n duration?: number\n timestamp: number\n status: 'started' | 'completed'\n}\n\nexport interface ActivityEvent {\n id: string\n name: string\n timestamp: number\n payload: unknown\n}\n\nexport interface Conversation {\n id: string\n type: 'client' | 'server'\n label: string\n messages: Array<Message>\n chunks: Array<Chunk>\n model?: string\n provider?: string\n status: 'active' | 'completed' | 'error'\n startedAt: number\n completedAt?: number\n usage?: TokenUsage\n iterationCount?: number\n toolNames?: Array<string>\n options?: Record<string, unknown>\n modelOptions?: Record<string, unknown>\n systemPrompts?: Array<string>\n /** Flags for which operation types this conversation has */\n hasChat?: boolean\n hasSummarize?: boolean\n hasImage?: boolean\n hasSpeech?: boolean\n hasTranscription?: boolean\n hasVideo?: boolean\n /** Summarize operations in this conversation */\n summaries?: Array<SummarizeOperation>\n imageEvents?: Array<ActivityEvent>\n speechEvents?: Array<ActivityEvent>\n transcriptionEvents?: Array<ActivityEvent>\n videoEvents?: Array<ActivityEvent>\n}\n\ninterface AIStoreState {\n conversations: Record<string, Conversation>\n activeConversationId: string | null\n}\n\ninterface AIContextValue {\n state: AIStoreState\n clearAllConversations: () => void\n selectConversation: (id: string) => void\n}\n\nconst AIContext = createContext<AIContextValue>()\n\nexport function useAIStore(): AIContextValue {\n const context = useContext(AIContext)\n if (!context) {\n throw new Error('useAIStore must be used within an AIProvider')\n }\n return context\n}\n\nexport const AIProvider: ParentComponent = (props) => {\n const [state, setState] = createStore<AIStoreState>({\n conversations: {},\n activeConversationId: null,\n })\n\n const streamToConversation = new Map<string, string>()\n const requestToConversation = new Map<string, string>()\n\n // Batching system for high-frequency chunk updates with consolidated chunk merging\n // Stores: conversationId -> { chunks to merge, totalNewChunks count }\n const pendingConversationChunks = new Map<\n string,\n { chunks: Array<Chunk>; newChunkCount: number }\n >()\n // Stores: conversationId -> messageIndex -> { chunks to merge, totalNewChunks count }\n const pendingMessageChunks = new Map<\n string,\n Map<number, { chunks: Array<Chunk>; newChunkCount: number }>\n >()\n let batchScheduled = false\n\n function scheduleBatchFlush(): void {\n if (batchScheduled) return\n batchScheduled = true\n queueMicrotask(flushPendingChunks)\n }\n\n /** Check if a chunk type can be merged with consecutive same-type chunks */\n function isMergeableChunkType(type: Chunk['type']): boolean {\n return type === 'content' || type === 'thinking'\n }\n\n /** Merge pending chunks into existing chunks array, consolidating consecutive same-type chunks */\n function mergeChunks(existing: Array<Chunk>, pending: Array<Chunk>): void {\n for (const chunk of pending) {\n const lastChunk = existing[existing.length - 1]\n\n // If last chunk exists, is the same type, and both are mergeable types, merge them\n if (\n lastChunk &&\n lastChunk.type === chunk.type &&\n isMergeableChunkType(chunk.type) &&\n lastChunk.messageId === chunk.messageId\n ) {\n // Merge: use the new chunk's content (it's already accumulated), update delta, increment count\n lastChunk.content = chunk.content || lastChunk.content\n lastChunk.delta = chunk.delta\n lastChunk.chunkCount += chunk.chunkCount\n } else {\n // Different type or not mergeable - add as new entry\n existing.push(chunk)\n }\n }\n }\n\n function flushPendingChunks(): void {\n batchScheduled = false\n\n batch(() => {\n // Flush conversation-level chunks\n for (const [\n conversationId,\n { chunks, newChunkCount },\n ] of pendingConversationChunks) {\n const conv = state.conversations[conversationId]\n if (conv) {\n setState(\n 'conversations',\n conversationId,\n 'chunks',\n produce((arr: Array<Chunk>) => {\n mergeChunks(arr, chunks)\n }),\n )\n }\n }\n pendingConversationChunks.clear()\n\n // Flush message-level chunks\n for (const [conversationId, messageMap] of pendingMessageChunks) {\n const conv = state.conversations[conversationId]\n if (!conv) continue\n\n for (const [messageIndex, { chunks, newChunkCount }] of messageMap) {\n const message = conv.messages[messageIndex]\n if (message) {\n // Update chunks array with merging\n setState(\n 'conversations',\n conversationId,\n 'messages',\n messageIndex,\n 'chunks',\n produce((arr: Array<Chunk> | undefined) => {\n if (!arr) {\n // First time - just set the chunks (they're already consolidated in pending)\n return chunks\n }\n mergeChunks(arr, chunks)\n return arr\n }),\n )\n // Update total chunk count\n const currentTotal = message.totalChunkCount || 0\n setState(\n 'conversations',\n conversationId,\n 'messages',\n messageIndex,\n 'totalChunkCount',\n currentTotal + newChunkCount,\n )\n }\n }\n }\n pendingMessageChunks.clear()\n })\n }\n\n function queueChunk(conversationId: string, chunk: Chunk): void {\n if (!pendingConversationChunks.has(conversationId)) {\n pendingConversationChunks.set(conversationId, {\n chunks: [],\n newChunkCount: 0,\n })\n }\n const pending = pendingConversationChunks.get(conversationId)!\n\n // Pre-merge in pending buffer to reduce array operations during flush\n const lastPending = pending.chunks[pending.chunks.length - 1]\n if (\n lastPending &&\n lastPending.type === chunk.type &&\n isMergeableChunkType(chunk.type) &&\n lastPending.messageId === chunk.messageId\n ) {\n // Merge into pending buffer - only append delta (incremental content)\n // Use the new chunk's content as the accumulated content (it's already accumulated)\n lastPending.content = chunk.content || lastPending.content\n lastPending.delta = chunk.delta\n lastPending.chunkCount += chunk.chunkCount\n } else {\n pending.chunks.push(chunk)\n }\n pending.newChunkCount += chunk.chunkCount\n scheduleBatchFlush()\n }\n\n function queueMessageChunk(\n conversationId: string,\n messageIndex: number,\n chunk: Chunk,\n ): void {\n if (!pendingMessageChunks.has(conversationId)) {\n pendingMessageChunks.set(conversationId, new Map())\n }\n const messageMap = pendingMessageChunks.get(conversationId)!\n if (!messageMap.has(messageIndex)) {\n messageMap.set(messageIndex, { chunks: [], newChunkCount: 0 })\n }\n const pending = messageMap.get(messageIndex)!\n\n // Pre-merge in pending buffer\n const lastPending = pending.chunks[pending.chunks.length - 1]\n if (\n lastPending &&\n lastPending.type === chunk.type &&\n isMergeableChunkType(chunk.type) &&\n lastPending.messageId === chunk.messageId\n ) {\n // Merge into pending buffer - only append delta (incremental content)\n // Use the new chunk's content as the accumulated content (it's already accumulated)\n lastPending.content = chunk.content || lastPending.content\n lastPending.delta = chunk.delta\n lastPending.chunkCount += chunk.chunkCount\n } else {\n pending.chunks.push(chunk)\n }\n pending.newChunkCount += chunk.chunkCount\n scheduleBatchFlush()\n }\n\n // Optimized helper functions using path-based updates\n function getOrCreateConversation(\n id: string,\n type: 'client' | 'server',\n label: string,\n ): void {\n if (!state.conversations[id]) {\n setState('conversations', id, {\n id,\n type,\n label,\n messages: [],\n chunks: [],\n imageEvents: [],\n speechEvents: [],\n transcriptionEvents: [],\n videoEvents: [],\n status: 'active',\n startedAt: Date.now(),\n })\n if (!state.activeConversationId) {\n setState('activeConversationId', id)\n }\n }\n }\n\n function addMessage(conversationId: string, message: Message): void {\n const conv = state.conversations[conversationId]\n if (!conv) return\n setState(\n 'conversations',\n conversationId,\n 'messages',\n conv.messages.length,\n message,\n )\n }\n\n function addChunkToMessage(conversationId: string, chunk: Chunk): void {\n const conv = state.conversations[conversationId]\n if (!conv) return\n\n if (chunk.messageId) {\n const messageIndex = conv.messages.findIndex(\n (msg) => msg.id === chunk.messageId,\n )\n\n if (messageIndex !== -1) {\n queueMessageChunk(conversationId, messageIndex, chunk)\n return\n } else {\n // Create new message with the chunk\n const newMessage: Message = {\n id: chunk.messageId,\n role: 'assistant',\n content: '',\n timestamp: chunk.timestamp,\n model: conv.model,\n chunks: [chunk],\n }\n setState(\n 'conversations',\n conversationId,\n 'messages',\n conv.messages.length,\n newMessage,\n )\n return\n }\n }\n\n // Find last assistant message\n for (let i = conv.messages.length - 1; i >= 0; i--) {\n const message = conv.messages[i]\n if (message && message.role === 'assistant') {\n queueMessageChunk(conversationId, i, chunk)\n return\n }\n }\n\n // Fallback: add to conversation's main chunks array if no assistant message found\n addChunk(conversationId, chunk)\n }\n\n function updateMessageUsage(\n conversationId: string,\n messageId: string | undefined,\n cumulativeUsage: TokenUsage,\n ): void {\n const conv = state.conversations[conversationId]\n if (!conv) return\n\n // Calculate the sum of usage from all previous messages (excluding the target message)\n let previousPromptTokens = 0\n let previousCompletionTokens = 0\n\n // Find the target message index\n let targetMessageIndex = -1\n if (messageId) {\n targetMessageIndex = conv.messages.findIndex(\n (msg) => msg.id === messageId,\n )\n } else {\n // Find last assistant message\n for (let i = conv.messages.length - 1; i >= 0; i--) {\n if (conv.messages[i]?.role === 'assistant') {\n targetMessageIndex = i\n break\n }\n }\n }\n\n if (targetMessageIndex === -1) return\n\n // Sum up usage from all previous assistant messages\n for (let i = 0; i < targetMessageIndex; i++) {\n const msg = conv.messages[i]\n if (msg?.role === 'assistant' && msg.usage) {\n previousPromptTokens += msg.usage.promptTokens\n previousCompletionTokens += msg.usage.completionTokens\n }\n }\n\n // Calculate delta usage for this message\n const deltaUsage: TokenUsage = {\n promptTokens: Math.max(\n 0,\n cumulativeUsage.promptTokens - previousPromptTokens,\n ),\n completionTokens: Math.max(\n 0,\n cumulativeUsage.completionTokens - previousCompletionTokens,\n ),\n totalTokens: 0,\n }\n deltaUsage.totalTokens =\n deltaUsage.promptTokens + deltaUsage.completionTokens\n\n setState(\n 'conversations',\n conversationId,\n 'messages',\n targetMessageIndex,\n 'usage',\n deltaUsage,\n )\n }\n\n // Public actions\n function clearAllConversations() {\n setState('conversations', {})\n setState('activeConversationId', null)\n streamToConversation.clear()\n requestToConversation.clear()\n pendingConversationChunks.clear()\n pendingMessageChunks.clear()\n }\n\n function selectConversation(id: string) {\n setState('activeConversationId', id)\n }\n\n // Additional optimized helper functions\n function updateConversation(\n conversationId: string,\n updates: Partial<Conversation>,\n ): void {\n if (!state.conversations[conversationId]) return\n for (const [key, value] of Object.entries(updates)) {\n setState(\n 'conversations',\n conversationId,\n key as keyof Conversation,\n value as Conversation[keyof Conversation],\n )\n }\n }\n\n function updateMessage(\n conversationId: string,\n messageIndex: number,\n updates: Partial<Message>,\n ): void {\n const conv = state.conversations[conversationId]\n if (!conv || !conv.messages[messageIndex]) return\n for (const [key, value] of Object.entries(updates)) {\n setState(\n 'conversations',\n conversationId,\n 'messages',\n messageIndex,\n key as keyof Message,\n value as Message[keyof Message],\n )\n }\n }\n\n function updateToolCall(\n conversationId: string,\n messageIndex: number,\n toolCallIndex: number,\n updates: Partial<ToolCall>,\n ): void {\n const conv = state.conversations[conversationId]\n if (!conv?.messages[messageIndex]?.toolCalls?.[toolCallIndex]) return\n setState(\n 'conversations',\n conversationId,\n 'messages',\n messageIndex,\n 'toolCalls',\n toolCallIndex,\n produce((tc: ToolCall) => Object.assign(tc, updates)),\n )\n }\n\n function setToolCalls(\n conversationId: string,\n messageIndex: number,\n toolCalls: Array<ToolCall>,\n ): void {\n if (!state.conversations[conversationId]?.messages[messageIndex]) return\n setState(\n 'conversations',\n conversationId,\n 'messages',\n messageIndex,\n 'toolCalls',\n toolCalls,\n )\n }\n\n function addChunk(conversationId: string, chunk: Chunk): void {\n if (!state.conversations[conversationId]) return\n queueChunk(conversationId, chunk)\n }\n\n function addActivityEvent(\n conversationId: string,\n activity:\n | 'imageEvents'\n | 'speechEvents'\n | 'transcriptionEvents'\n | 'videoEvents',\n event: ActivityEvent,\n ): void {\n if (!state.conversations[conversationId]) return\n\n setState(\n 'conversations',\n conversationId,\n activity,\n produce((events: Array<ActivityEvent> | undefined) => {\n if (!events) return [event]\n events.push(event)\n return events\n }),\n )\n\n const activityFlagMap: Record<typeof activity, keyof Conversation> = {\n imageEvents: 'hasImage',\n speechEvents: 'hasSpeech',\n transcriptionEvents: 'hasTranscription',\n videoEvents: 'hasVideo',\n }\n\n setState('conversations', conversationId, activityFlagMap[activity], true)\n }\n\n /**\n * For server conversations, ensure a message exists for the given messageId.\n * This creates a placeholder message that will be updated as chunks arrive.\n */\n function ensureMessageForChunk(\n conversationId: string,\n messageId: string | undefined,\n timestamp: number,\n ): void {\n if (!messageId) return\n const conv = state.conversations[conversationId]\n if (!conv || conv.type === 'client') return\n\n // Check if message already exists\n const existingMessage = conv.messages.find((m) => m.id === messageId)\n if (existingMessage) return\n\n // Create a new message for this messageId (server-side message)\n addMessage(conversationId, {\n id: messageId,\n role: 'assistant',\n content: '',\n timestamp,\n source: 'server',\n })\n }\n\n // Register all event listeners on mount\n onMount(() => {\n const cleanupFns: Array<() => void> = []\n\n // ============= Client Events =============\n\n cleanupFns.push(\n aiEventClient.on('client:created', (e) => {\n const clientId = e.payload.clientId\n getOrCreateConversation(\n clientId,\n 'client',\n `Client Chat (${clientId.substring(0, 8)})`,\n )\n updateConversation(clientId, { model: undefined, provider: 'Client' })\n }),\n )\n\n // ============= Message Events =============\n\n cleanupFns.push(\n aiEventClient.on('text:message:created', (e) => {\n const { clientId, streamId, messageId, role, content, timestamp } =\n e.payload\n const conversationId =\n clientId ||\n (streamId ? streamToConversation.get(streamId) : undefined)\n\n if (!conversationId) return\n if (role === 'tool' || role === 'system') return\n\n if (!state.conversations[conversationId]) {\n getOrCreateConversation(\n conversationId,\n clientId ? 'client' : 'server',\n clientId\n ? `Client Chat (${conversationId.substring(0, 8)})`\n : `Server Chat (${conversationId.substring(0, 8)})`,\n )\n }\n\n const conv = state.conversations[conversationId]\n if (!conv) return\n\n const existingIndex = conv.messages.findIndex(\n (message) => message.id === messageId,\n )\n\n const parts = e.payload.parts?.map((part) => {\n if (part.type === 'text') {\n return { type: 'text', content: part.content } satisfies MessagePart\n }\n if (part.type === 'tool-call') {\n return {\n type: 'tool-call',\n toolCallId: part.id,\n toolName: part.name,\n arguments: part.arguments,\n state: part.state,\n output: part.output,\n content: part.approval\n ? JSON.stringify(part.approval)\n : undefined,\n } satisfies MessagePart\n }\n if (part.type === 'tool-result') {\n return {\n type: 'tool-result',\n toolCallId: part.toolCallId,\n content: part.content,\n state: part.state,\n error: part.error,\n } satisfies MessagePart\n }\n return {\n type: 'thinking',\n content: part.content,\n } satisfies MessagePart\n })\n\n const toolCalls = e.payload.toolCalls?.map((toolCall) => ({\n id: toolCall.id,\n name: toolCall.function.name,\n arguments: toolCall.function.arguments,\n state: 'input-complete',\n }))\n\n const source = e.payload.source ?? (clientId ? 'client' : 'server')\n\n if (role === 'user' && conv.type === 'client' && source === 'server') {\n return\n }\n\n // Skip empty assistant messages from client - the real content comes from server\n if (\n role === 'assistant' &&\n source === 'client' &&\n !content &&\n (!toolCalls || toolCalls.length === 0)\n ) {\n return\n }\n\n const messagePayload: Message = {\n id: messageId,\n role,\n content,\n timestamp,\n parts,\n toolCalls,\n source,\n }\n\n if (existingIndex >= 0) {\n updateMessage(conversationId, existingIndex, messagePayload)\n } else {\n addMessage(conversationId, messagePayload)\n }\n\n updateConversation(conversationId, { status: 'active', hasChat: true })\n }),\n )\n\n cleanupFns.push(\n aiEventClient.on('text:message:user', (e) => {\n const { clientId, streamId, messageId, content, timestamp } = e.payload\n const conversationId =\n clientId ||\n (streamId ? streamToConversation.get(streamId) : undefined)\n if (!conversationId) return\n\n const conv = state.conversations[conversationId]\n if (!conv) return\n\n const existingIndex = conv.messages.findIndex(\n (message) => message.id === messageId,\n )\n\n if (existingIndex >= 0) return\n\n const source = e.payload.source ?? (clientId ? 'client' : 'server')\n\n if (conv.type === 'client' && source === 'server') {\n return\n }\n\n addMessage(conversationId, {\n id: messageId,\n role: 'user',\n content,\n timestamp,\n source,\n })\n }),\n )\n\n cleanupFns.push(\n aiEventClient.on('client:loading:changed', (e) => {\n const clientId = e.payload.clientId\n if (state.conversations[clientId]) {\n updateConversation(clientId, {\n status: e.payload.isLoading ? 'active' : 'completed',\n })\n }\n }),\n )\n\n cleanupFns.push(\n aiEventClient.on('client:stopped', (e) => {\n const clientId = e.payload.clientId\n if (state.conversations[clientId]) {\n updateConversation(clientId, {\n status: 'completed',\n completedAt: e.payload.timestamp,\n })\n }\n }),\n )\n\n cleanupFns.push(\n aiEventClient.on('client:messages:cleared', (e) => {\n const clientId = e.payload.clientId\n if (state.conversations[clientId]) {\n updateConversation(clientId, {\n messages: [],\n chunks: [],\n usage: undefined,\n })\n }\n }),\n )\n\n cleanupFns.push(\n aiEventClient.on('client:reloaded', (e) => {\n const clientId = e.payload.clientId\n const conv = state.conversations[clientId]\n if (conv) {\n updateConversation(clientId, {\n messages: conv.messages.slice(0, e.payload.fromMessageIndex),\n status: 'active',\n })\n }\n }),\n )\n\n cleanupFns.push(\n aiEventClient.on('client:error:changed', (e) => {\n const clientId = e.payload.clientId\n if (state.conversations[clientId] && e.payload.error) {\n updateConversation(clientId, { status: 'error' })\n }\n }),\n )\n\n // ============= Tool Events =============\n\n cleanupFns.push(\n aiEventClient.on('tools:result:added', (e) => {\n const {\n clientId,\n toolCallId,\n toolName,\n output,\n state: resultState,\n timestamp,\n } = e.payload\n\n if (!clientId) return\n if (!state.conversations[clientId]) return\n\n const conv = state.conversations[clientId]\n\n // Always create a chunk for the tool result\n const chunk: Chunk = {\n id: `chunk-tool-result-${toolCallId}-${Date.now()}`,\n type: 'tool_result',\n toolCallId,\n toolName,\n result: output,\n timestamp,\n chunkCount: 1,\n isClientTool: true,\n }\n\n // Find the message with the tool call and update it\n for (\n let messageIndex = conv.messages.length - 1;\n messageIndex >= 0;\n messageIndex--\n ) {\n const message = conv.messages[messageIndex]\n if (!message?.toolCalls) continue\n\n const toolCallIndex = message.toolCalls.findIndex(\n (t: ToolCall) => t.id === toolCallId,\n )\n if (toolCallIndex >= 0) {\n // Update the tool call state\n updateToolCall(clientId, messageIndex, toolCallIndex, {\n result: output,\n state: resultState === 'output-error' ? 'error' : 'complete',\n })\n\n // Add chunk with message ID\n chunk.messageId = message.id\n addChunkToMessage(clientId, chunk)\n return\n }\n }\n\n // If we couldn't find the message with toolCalls, still add the chunk\n // This handles cases where the message hasn't been processed yet\n // or the tool call is a client-only tool\n addChunkToMessage(clientId, chunk)\n }),\n )\n\n cleanupFns.push(\n aiEventClient.on('tools:approval:responded', (e) => {\n const { clientId, toolCallId, approved } = e.payload\n\n if (!clientId) return\n if (!state.conversations[clientId]) return\n\n const conv = state.conversations[clientId]\n\n for (\n let messageIndex = conv.messages.length - 1;\n messageIndex >= 0;\n messageIndex--\n ) {\n const message = conv.messages[messageIndex]\n if (!message?.toolCalls) continue\n\n const toolCallIndex = message.toolCalls.findIndex(\n (t: ToolCall) => t.id === toolCallId,\n )\n if (toolCallIndex >= 0) {\n updateToolCall(clientId, messageIndex, toolCallIndex, {\n state: approved ? 'approved' : 'denied',\n approvalRequired: false,\n })\n return\n }\n }\n }),\n )\n\n cleanupFns.push(\n aiEventClient.on('tools:call:updated', (e) => {\n const {\n clientId,\n streamId,\n messageId,\n toolCallId,\n toolName,\n state: toolCallState,\n arguments: args,\n } = e.payload\n\n const conversationId =\n clientId ||\n (streamId ? streamToConversation.get(streamId) : undefined)\n if (!conversationId || !state.conversations[conversationId]) return\n\n const conv = state.conversations[conversationId]\n const messageIndex = conv.messages.findIndex(\n (m: Message) => m.id === messageId,\n )\n if (messageIndex === -1) return\n\n const message = conv.messages[messageIndex]\n if (!message) return\n\n const toolCalls = message.toolCalls || []\n const existingToolIndex = toolCalls.findIndex(\n (t: ToolCall) => t.id === toolCallId,\n )\n\n const toolCall: ToolCall = {\n id: toolCallId,\n name: toolName,\n arguments: args,\n state: toolCallState,\n }\n\n if (existingToolIndex >= 0) {\n updateToolCall(\n conversationId,\n messageIndex,\n existingToolIndex,\n toolCall,\n )\n } else {\n setToolCalls(conversationId, messageIndex, [...toolCalls, toolCall])\n }\n }),\n )\n\n cleanupFns.push(\n aiEventClient.on('tools:input:available', (e) => {\n const {\n streamId,\n messageId,\n toolCallId,\n toolName,\n input,\n timestamp,\n clientId,\n } = e.payload\n\n const conversationId =\n clientId ||\n (streamId ? streamToConversation.get(streamId) : undefined)\n if (!conversationId) return\n\n const chunk: Chunk = {\n id: `chunk-${Date.now()}-${Math.random()}`,\n type: 'tool_call',\n messageId: messageId,\n toolCallId,\n toolName,\n arguments: JSON.stringify(input),\n timestamp,\n chunkCount: 1,\n }\n\n const conv = state.conversations[conversationId]\n if (conv?.type === 'client') {\n addChunkToMessage(conversationId, chunk)\n } else {\n addChunk(conversationId, chunk)\n }\n }),\n )\n\n cleanupFns.push(\n aiEventClient.on('tools:call:completed', (e) => {\n const {\n streamId,\n toolCallId,\n toolName,\n result,\n duration,\n messageId,\n timestamp,\n clientId,\n } = e.payload\n\n const conversationId =\n clientId ||\n (streamId ? streamToConversation.get(streamId) : undefined)\n if (!conversationId || !state.conversations[conversationId]) return\n\n const conv = state.conversations[conversationId]\n\n const chunk: Chunk = {\n id: `chunk-tool-result-${toolCallId}-${Date.now()}`,\n type: 'tool_result',\n messageId: messageId,\n toolCallId,\n toolName,\n result,\n duration,\n timestamp,\n chunkCount: 1,\n }\n\n if (conv.type === 'client' && messageId) {\n const messageIndex = conv.messages.findIndex(\n (m) => m.id === messageId,\n )\n if (messageIndex !== -1) {\n queueMessageChunk(conversationId, messageIndex, chunk)\n } else {\n for (let i = conv.messages.length - 1; i >= 0; i--) {\n if (conv.messages[i]?.role === 'assistant') {\n queueMessageChunk(conversationId, i, chunk)\n break\n }\n }\n }\n } else {\n addChunk(conversationId, chunk)\n }\n\n for (let i = conv.messages.length - 1; i >= 0; i--) {\n const message = conv.messages[i]\n if (!message?.toolCalls) continue\n\n const toolCallIndex = message.toolCalls.findIndex(\n (t) => t.id === toolCallId,\n )\n if (toolCallIndex >= 0) {\n updateToolCall(conversationId, i, toolCallIndex, {\n duration,\n result,\n })\n return\n }\n }\n }),\n )\n\n // ============= Stream Events =============\n\n cleanupFns.push(\n aiEventClient.on('text:chunk:content', (e) => {\n const streamId = e.payload.streamId\n const conversationId = streamToConversation.get(streamId)\n if (!conversationId) return\n\n const chunk: Chunk = {\n id: `chunk-${Date.now()}-${Math.random()}`,\n type: 'content',\n messageId: e.payload.messageId,\n content: e.payload.content,\n delta: e.payload.delta,\n timestamp: e.payload.timestamp,\n chunkCount: 1,\n }\n\n const conv = state.conversations[conversationId]\n if (conv?.type === 'client') {\n addChunkToMessage(conversationId, chunk)\n } else {\n ensureMessageForChunk(\n conversationId,\n e.payload.messageId,\n e.payload.timestamp,\n )\n addChunk(conversationId, chunk)\n }\n\n if (e.payload.messageId) {\n const messageIndex = conv?.messages.findIndex(\n (msg) => msg.id === e.payload.messageId,\n )\n if (messageIndex !== undefined && messageIndex >= 0) {\n updateMessage(conversationId, messageIndex, {\n content: e.payload.content,\n })\n }\n }\n }),\n )\n\n cleanupFns.push(\n aiEventClient.on('text:chunk:tool-call', (e) => {\n const streamId = e.payload.streamId\n const conversationId = streamToConversation.get(streamId)\n if (!conversationId) return\n\n const chunk: Chunk = {\n id: `chunk-${Date.now()}-${Math.random()}`,\n type: 'tool_call',\n messageId: e.payload.messageId,\n toolCallId: e.payload.toolCallId,\n toolName: e.payload.toolName,\n arguments: e.payload.arguments,\n timestamp: e.payload.timestamp,\n chunkCount: 1,\n }\n\n const conv = state.conversations[conversationId]\n if (conv?.type === 'client') {\n addChunkToMessage(conversationId, chunk)\n } else {\n ensureMessageForChunk(\n conversationId,\n e.payload.messageId,\n e.payload.timestamp,\n )\n addChunk(conversationId, chunk)\n }\n\n if (e.payload.messageId) {\n const messageIndex = conv?.messages.findIndex(\n (msg) => msg.id === e.payload.messageId,\n )\n if (messageIndex !== undefined && messageIndex >= 0) {\n const message = conv?.messages[messageIndex]\n if (!message) return\n\n const toolCalls = message.toolCalls || []\n const existingToolIndex = toolCalls.findIndex(\n (t: ToolCall) => t.id === e.payload.toolCallId,\n )\n\n const toolCall: ToolCall = {\n id: e.payload.toolCallId,\n name: e.payload.toolName,\n arguments: e.payload.arguments,\n state: 'input-streaming',\n }\n\n if (existingToolIndex >= 0) {\n updateToolCall(\n conversationId,\n messageIndex,\n existingToolIndex,\n toolCall,\n )\n } else {\n setToolCalls(conversationId, messageIndex, [\n ...toolCalls,\n toolCall,\n ])\n }\n }\n }\n }),\n )\n\n cleanupFns.push(\n aiEventClient.on('text:chunk:tool-result', (e) => {\n const streamId = e.payload.streamId\n const conversationId = streamToConversation.get(streamId)\n if (!conversationId) return\n\n const chunk: Chunk = {\n id: `chunk-${Date.now()}-${Math.random()}`,\n type: 'tool_result',\n messageId: e.payload.messageId,\n toolCallId: e.payload.toolCallId,\n result: e.payload.result,\n timestamp: e.payload.timestamp,\n chunkCount: 1,\n }\n\n const conv = state.conversations[conversationId]\n if (conv?.type === 'client') {\n addChunkToMessage(conversationId, chunk)\n } else {\n ensureMessageForChunk(\n conversationId,\n e.payload.messageId,\n e.payload.timestamp,\n )\n addChunk(conversationId, chunk)\n }\n\n // Also update the toolCalls array with the result\n if (conv && e.payload.toolCallId) {\n for (let i = conv.messages.length - 1; i >= 0; i--) {\n const message = conv.messages[i]\n if (!message?.toolCalls) continue\n\n const toolCallIndex = message.toolCalls.findIndex(\n (t) => t.id === e.payload.toolCallId,\n )\n if (toolCallIndex >= 0) {\n updateToolCall(conversationId, i, toolCallIndex, {\n result: e.payload.result,\n state: 'complete',\n })\n break\n }\n }\n }\n }),\n )\n\n cleanupFns.push(\n aiEventClient.on('text:chunk:thinking', (e) => {\n const streamId = e.payload.streamId\n const conversationId = streamToConversation.get(streamId)\n if (!conversationId) return\n\n const chunk: Chunk = {\n id: `chunk-${Date.now()}-${Math.random()}`,\n type: 'thinking',\n messageId: e.payload.messageId,\n content: e.payload.content,\n delta: e.payload.delta,\n timestamp: e.payload.timestamp,\n chunkCount: 1,\n }\n\n const conv = state.conversations[conversationId]\n if (conv?.type === 'client') {\n addChunkToMessage(conversationId, chunk)\n\n if (e.payload.messageId) {\n const messageIndex = conv.messages.findIndex(\n (msg) => msg.id === e.payload.messageId,\n )\n if (messageIndex !== -1) {\n updateMessage(conversationId, messageIndex, {\n thinkingContent: e.payload.content,\n })\n }\n }\n } else {\n ensureMessageForChunk(\n conversationId,\n e.payload.messageId,\n e.payload.timestamp,\n )\n addChunk(conversationId, chunk)\n }\n }),\n )\n\n cleanupFns.push(\n aiEventClient.on('text:chunk:done', (e) => {\n const streamId = e.payload.streamId\n const conversationId = streamToConversation.get(streamId)\n if (!conversationId) return\n\n const chunk: Chunk = {\n id: `chunk-${Date.now()}-${Math.random()}`,\n type: 'done',\n messageId: e.payload.messageId,\n finishReason: e.payload.finishReason || undefined,\n timestamp: e.payload.timestamp,\n chunkCount: 1,\n }\n\n if (e.payload.usage) {\n updateConversation(conversationId, { usage: e.payload.usage })\n updateMessageUsage(\n conversationId,\n e.payload.messageId,\n e.payload.usage,\n )\n }\n\n const conv = state.conversations[conversationId]\n if (conv?.type === 'client') {\n addChunkToMessage(conversationId, chunk)\n } else {\n ensureMessageForChunk(\n conversationId,\n e.payload.messageId,\n e.payload.timestamp,\n )\n addChunk(conversationId, chunk)\n }\n\n updateConversation(conversationId, {\n status: 'completed',\n completedAt: e.payload.timestamp,\n })\n }),\n )\n\n cleanupFns.push(\n aiEventClient.on('text:chunk:error', (e) => {\n const streamId = e.payload.streamId\n const conversationId = streamToConversation.get(streamId)\n if (!conversationId) return\n\n const chunk: Chunk = {\n id: `chunk-${Date.now()}-${Math.random()}`,\n type: 'error',\n messageId: e.payload.messageId,\n error: e.payload.error,\n timestamp: e.payload.timestamp,\n chunkCount: 1,\n }\n\n const conv = state.conversations[conversationId]\n if (conv?.type === 'client') {\n addChunkToMessage(conversationId, chunk)\n } else {\n ensureMessageForChunk(\n conversationId,\n e.payload.messageId,\n e.payload.timestamp,\n )\n addChunk(conversationId, chunk)\n }\n\n updateConversation(conversationId, {\n status: 'error',\n completedAt: e.payload.timestamp,\n })\n }),\n )\n\n cleanupFns.push(\n aiEventClient.on('tools:approval:requested', (e) => {\n const {\n streamId,\n messageId,\n toolCallId,\n toolName,\n input,\n approvalId,\n timestamp,\n clientId,\n } = e.payload\n\n const conversationId =\n clientId || streamToConversation.get(streamId) || ''\n if (!conversationId) return\n\n const conv = state.conversations[conversationId]\n if (!conv) return\n\n const chunk: Chunk = {\n id: `chunk-${Date.now()}-${Math.random()}`,\n type: 'approval',\n messageId: messageId,\n toolCallId,\n toolName,\n approvalId,\n input,\n timestamp,\n chunkCount: 1,\n }\n\n if (conv.type === 'client') {\n addChunkToMessage(conversationId, chunk)\n } else {\n addChunk(conversationId, chunk)\n }\n\n for (let i = conv.messages.length - 1; i >= 0; i--) {\n const message = conv.messages[i]\n if (!message) continue\n\n if (message.role === 'assistant' && message.toolCalls) {\n const toolCallIndex = message.toolCalls.findIndex(\n (t: ToolCall) => t.id === toolCallId,\n )\n if (toolCallIndex >= 0) {\n updateToolCall(conversationId, i, toolCallIndex, {\n approvalRequired: true,\n approvalId,\n state: 'approval-requested',\n })\n return\n }\n }\n }\n }),\n )\n\n // ============= Chat Events (for usage tracking) =============\n\n cleanupFns.push(\n aiEventClient.on('text:request:started', (e) => {\n const streamId = e.payload.streamId\n const model = e.payload.model\n const provider = e.payload.provider\n const clientId = e.payload.clientId\n\n if (clientId && state.conversations[clientId]) {\n streamToConversation.set(streamId, clientId)\n requestToConversation.set(e.payload.requestId, clientId)\n updateConversation(clientId, {\n status: 'active',\n ...e.payload,\n systemPrompts: e.payload.systemPrompts,\n hasChat: true,\n })\n return\n }\n\n const activeClient = Object.values(state.conversations).find(\n (c) => c.type === 'client' && c.status === 'active' && !c.model,\n )\n\n if (activeClient) {\n streamToConversation.set(streamId, activeClient.id)\n requestToConversation.set(e.payload.requestId, activeClient.id)\n updateConversation(activeClient.id, {\n ...e.payload,\n systemPrompts: e.payload.systemPrompts,\n hasChat: true,\n })\n } else {\n const existingServerConv = Object.values(state.conversations).find(\n (c) => c.type === 'server' && c.model === model,\n )\n\n if (existingServerConv) {\n streamToConversation.set(streamId, existingServerConv.id)\n requestToConversation.set(\n e.payload.requestId,\n existingServerConv.id,\n )\n updateConversation(existingServerConv.id, {\n status: 'active',\n ...e.payload,\n systemPrompts: e.payload.systemPrompts,\n hasChat: true,\n })\n } else {\n const serverId = `server-${model}`\n getOrCreateConversation(serverId, 'server', `${model} Server`)\n streamToConversation.set(streamId, serverId)\n requestToConversation.set(e.payload.requestId, serverId)\n updateConversation(serverId, {\n ...e.payload,\n systemPrompts: e.payload.systemPrompts,\n hasChat: true,\n })\n }\n }\n }),\n )\n\n cleanupFns.push(\n aiEventClient.on('text:request:completed', (e) => {\n const { requestId, usage } = e.payload\n\n const conversationId = requestToConversation.get(requestId)\n if (conversationId && state.conversations[conversationId]) {\n const updates: Partial<Conversation> = {\n status: 'completed',\n completedAt: e.payload.timestamp,\n }\n if (usage) {\n updates.usage = usage\n }\n updateConversation(conversationId, updates)\n if (usage) {\n updateMessageUsage(conversationId, e.payload.messageId, usage)\n }\n }\n }),\n )\n\n cleanupFns.push(\n aiEventClient.on('text:usage', (e) => {\n const { requestId, usage, messageId } = e.payload\n\n const conversationId = requestToConversation.get(requestId)\n if (conversationId && state.conversations[conversationId]) {\n updateConversation(conversationId, { usage })\n updateMessageUsage(conversationId, messageId, usage)\n }\n }),\n )\n\n // ============= Summarize Events =============\n\n cleanupFns.push(\n aiEventClient.on('summarize:request:started', (e) => {\n const { requestId, model, inputLength, timestamp, clientId } = e.payload\n\n // Try to find an active conversation to attach to, or create a new one\n let conversationId = clientId\n if (!conversationId || !state.conversations[conversationId]) {\n // Find most recent active client conversation\n const activeClients = Object.values(state.conversations)\n .filter((c) => c.type === 'client' && c.status === 'active')\n .sort((a, b) => b.startedAt - a.startedAt)\n\n if (activeClients.length > 0 && activeClients[0]) {\n conversationId = activeClients[0].id\n } else {\n // Create a new conversation for summaries\n conversationId = `summarize-${requestId}`\n getOrCreateConversation(\n conversationId,\n 'server',\n `Summarize (${model})`,\n )\n updateConversation(conversationId, { model })\n }\n }\n\n requestToConversation.set(requestId, conversationId)\n\n const summarizeOp: SummarizeOperation = {\n id: requestId,\n model,\n inputLength,\n timestamp,\n status: 'started',\n }\n\n const conv = state.conversations[conversationId]\n if (conv) {\n const summaries = conv.summaries || []\n setState('conversations', conversationId, 'summaries', [\n ...summaries,\n summarizeOp,\n ])\n setState('conversations', conversationId, 'hasSummarize', true)\n }\n }),\n )\n\n cleanupFns.push(\n aiEventClient.on('summarize:request:completed', (e) => {\n const { requestId, outputLength, duration } = e.payload\n\n const conversationId = requestToConversation.get(requestId)\n if (!conversationId || !state.conversations[conversationId]) return\n\n const conv = state.conversations[conversationId]\n if (!conv.summaries) return\n\n const summaryIndex = conv.summaries.findIndex(\n (op) => op.id === requestId,\n )\n if (summaryIndex >= 0) {\n setState(\n 'conversations',\n conversationId,\n 'summaries',\n summaryIndex,\n produce((op: SummarizeOperation) => {\n op.duration = duration\n op.outputLength = outputLength\n op.status = 'completed'\n }),\n )\n }\n }),\n )\n\n // ============= Image Events =============\n\n cleanupFns.push(\n aiEventClient.on('image:request:started', (e) => {\n const { requestId, clientId, timestamp } = e.payload\n\n let conversationId = clientId\n if (!conversationId || !state.conversations[conversationId]) {\n conversationId = `image-${requestId}`\n getOrCreateConversation(\n conversationId,\n 'server',\n `Image (${requestId.substring(0, 8)})`,\n )\n }\n\n addActivityEvent(conversationId, 'imageEvents', {\n id: requestId,\n name: 'image:request:started',\n timestamp,\n payload: e.payload,\n })\n }),\n )\n\n cleanupFns.push(\n aiEventClient.on('image:request:completed', (e) => {\n const { requestId, clientId, timestamp } = e.payload\n\n let conversationId = clientId\n if (!conversationId || !state.conversations[conversationId]) {\n conversationId = `image-${requestId}`\n getOrCreateConversation(\n conversationId,\n 'server',\n `Image (${requestId.substring(0, 8)})`,\n )\n }\n\n addActivityEvent(conversationId, 'imageEvents', {\n id: requestId,\n name: 'image:request:completed',\n timestamp,\n payload: e.payload,\n })\n }),\n )\n\n cleanupFns.push(\n aiEventClient.on('image:usage', (e) => {\n const { requestId, clientId, timestamp } = e.payload\n\n let conversationId = clientId\n if (!conversationId || !state.conversations[conversationId]) {\n conversationId = `image-${requestId}`\n getOrCreateConversation(\n conversationId,\n 'server',\n `Image (${requestId.substring(0, 8)})`,\n )\n }\n\n addActivityEvent(conversationId, 'imageEvents', {\n id: requestId,\n name: 'image:usage',\n timestamp,\n payload: e.payload,\n })\n }),\n )\n\n // ============= Speech Events =============\n\n cleanupFns.push(\n aiEventClient.on('speech:request:started', (e) => {\n const { requestId, clientId, timestamp } = e.payload\n\n let conversationId = clientId\n if (!conversationId || !state.conversations[conversationId]) {\n conversationId = `speech-${requestId}`\n getOrCreateConversation(\n conversationId,\n 'server',\n `Speech (${requestId.substring(0, 8)})`,\n )\n }\n\n addActivityEvent(conversationId, 'speechEvents', {\n id: requestId,\n name: 'speech:request:started',\n timestamp,\n payload: e.payload,\n })\n }),\n )\n\n cleanupFns.push(\n aiEventClient.on('speech:request:completed', (e) => {\n const { requestId, clientId, timestamp } = e.payload\n\n let conversationId = clientId\n if (!conversationId || !state.conversations[conversationId]) {\n conversationId = `speech-${requestId}`\n getOrCreateConversation(\n conversationId,\n 'server',\n `Speech (${requestId.substring(0, 8)})`,\n )\n }\n\n addActivityEvent(conversationId, 'speechEvents', {\n id: requestId,\n name: 'speech:request:completed',\n timestamp,\n payload: e.payload,\n })\n }),\n )\n\n cleanupFns.push(\n aiEventClient.on('speech:usage', (e) => {\n const { requestId, clientId, timestamp } = e.payload\n\n let conversationId = clientId\n if (!conversationId || !state.conversations[conversationId]) {\n conversationId = `speech-${requestId}`\n getOrCreateConversation(\n conversationId,\n 'server',\n `Speech (${requestId.substring(0, 8)})`,\n )\n }\n\n addActivityEvent(conversationId, 'speechEvents', {\n id: requestId,\n name: 'speech:usage',\n timestamp,\n payload: e.payload,\n })\n }),\n )\n\n // ============= Transcription Events =============\n\n cleanupFns.push(\n aiEventClient.on('transcription:request:started', (e) => {\n const { requestId, clientId, timestamp } = e.payload\n\n let conversationId = clientId\n if (!conversationId || !state.conversations[conversationId]) {\n conversationId = `transcription-${requestId}`\n getOrCreateConversation(\n conversationId,\n 'server',\n `Transcription (${requestId.substring(0, 8)})`,\n )\n }\n\n addActivityEvent(conversationId, 'transcriptionEvents', {\n id: requestId,\n name: 'transcription:request:started',\n timestamp,\n payload: e.payload,\n })\n }),\n )\n\n cleanupFns.push(\n aiEventClient.on('transcription:request:completed', (e) => {\n const { requestId, clientId, timestamp } = e.payload\n\n let conversationId = clientId\n if (!conversationId || !state.conversations[conversationId]) {\n conversationId = `transcription-${requestId}`\n getOrCreateConversation(\n conversationId,\n 'server',\n `Transcription (${requestId.substring(0, 8)})`,\n )\n }\n\n addActivityEvent(conversationId, 'transcriptionEvents', {\n id: requestId,\n name: 'transcription:request:completed',\n timestamp,\n payload: e.payload,\n })\n }),\n )\n\n cleanupFns.push(\n aiEventClient.on('transcription:usage', (e) => {\n const { requestId, clientId, timestamp } = e.payload\n\n let conversationId = clientId\n if (!conversationId || !state.conversations[conversationId]) {\n conversationId = `transcription-${requestId}`\n getOrCreateConversation(\n conversationId,\n 'server',\n `Transcription (${requestId.substring(0, 8)})`,\n )\n }\n\n addActivityEvent(conversationId, 'transcriptionEvents', {\n id: requestId,\n name: 'transcription:usage',\n timestamp,\n payload: e.payload,\n })\n }),\n )\n\n // ============= Video Events =============\n\n cleanupFns.push(\n aiEventClient.on('video:request:started', (e) => {\n const { requestId, clientId, timestamp } = e.payload\n\n let conversationId = clientId\n if (!conversationId || !state.conversations[conversationId]) {\n conversationId = `video-${requestId}`\n getOrCreateConversation(\n conversationId,\n 'server',\n `Video (${requestId.substring(0, 8)})`,\n )\n }\n\n addActivityEvent(conversationId, 'videoEvents', {\n id: requestId,\n name: 'video:request:started',\n timestamp,\n payload: e.payload,\n })\n }),\n )\n\n cleanupFns.push(\n aiEventClient.on('video:request:completed', (e) => {\n const { requestId, clientId, timestamp } = e.payload\n\n let conversationId = clientId\n if (!conversationId || !state.conversations[conversationId]) {\n conversationId = `video-${requestId}`\n getOrCreateConversation(\n conversationId,\n 'server',\n `Video (${requestId.substring(0, 8)})`,\n )\n }\n\n addActivityEvent(conversationId, 'videoEvents', {\n id: requestId,\n name: 'video:request:completed',\n timestamp,\n payload: e.payload,\n })\n }),\n )\n\n cleanupFns.push(\n aiEventClient.on('video:usage', (e) => {\n const { requestId, clientId, timestamp } = e.payload\n\n let conversationId = clientId\n if (!conversationId || !state.conversations[conversationId]) {\n conversationId = `video-${requestId}`\n getOrCreateConversation(\n conversationId,\n 'server',\n `Video (${requestId.substring(0, 8)})`,\n )\n }\n\n addActivityEvent(conversationId, 'videoEvents', {\n id: requestId,\n name: 'video:usage',\n timestamp,\n payload: e.payload,\n })\n }),\n )\n\n // Cleanup all listeners on unmount\n onCleanup(() => {\n for (const cleanup of cleanupFns) {\n cleanup()\n }\n streamToConversation.clear()\n requestToConversation.clear()\n })\n })\n\n const contextValue: AIContextValue = {\n state,\n clearAllConversations,\n selectConversation,\n }\n\n return (\n <AIContext.Provider value={contextValue}>\n {props.children}\n </AIContext.Provider>\n )\n}\n"],"names":["AIContext","createContext","useAIStore","context","useContext","Error","AIProvider","props","state","setState","createStore","conversations","activeConversationId","streamToConversation","Map","requestToConversation","pendingConversationChunks","pendingMessageChunks","batchScheduled","scheduleBatchFlush","queueMicrotask","flushPendingChunks","isMergeableChunkType","type","mergeChunks","existing","pending","chunk","lastChunk","length","messageId","content","delta","chunkCount","push","batch","conversationId","chunks","newChunkCount","conv","produce","arr","clear","messageMap","messageIndex","message","messages","currentTotal","totalChunkCount","queueChunk","has","set","get","lastPending","queueMessageChunk","getOrCreateConversation","id","label","imageEvents","speechEvents","transcriptionEvents","videoEvents","status","startedAt","Date","now","addMessage","addChunkToMessage","findIndex","msg","newMessage","role","timestamp","model","i","addChunk","updateMessageUsage","cumulativeUsage","previousPromptTokens","previousCompletionTokens","targetMessageIndex","usage","promptTokens","completionTokens","deltaUsage","Math","max","totalTokens","clearAllConversations","selectConversation","updateConversation","updates","key","value","Object","entries","updateMessage","updateToolCall","toolCallIndex","toolCalls","tc","assign","setToolCalls","addActivityEvent","activity","event","events","activityFlagMap","ensureMessageForChunk","existingMessage","find","m","source","onMount","cleanupFns","aiEventClient","on","e","clientId","payload","substring","undefined","provider","streamId","existingIndex","parts","map","part","toolCallId","toolName","name","arguments","output","approval","JSON","stringify","error","toolCall","function","messagePayload","hasChat","isLoading","completedAt","slice","fromMessageIndex","resultState","result","isClientTool","t","approved","approvalRequired","toolCallState","args","existingToolIndex","input","random","duration","thinkingContent","finishReason","approvalId","requestId","systemPrompts","activeClient","values","c","existingServerConv","serverId","inputLength","activeClients","filter","sort","a","b","summarizeOp","summaries","outputLength","summaryIndex","op","onCleanup","cleanup","contextValue","_$createComponent","Provider","children"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ai-context.js","sources":["../../../src/store/ai-context.tsx"],"sourcesContent":["import { batch, createContext, onCleanup, onMount, useContext } from 'solid-js'\nimport { createStore, produce } from 'solid-js/store'\nimport { aiEventClient } from '@tanstack/ai/event-client'\nimport type { ContentPartSource } from '@tanstack/ai'\nimport type { ParentComponent } from 'solid-js'\n\ninterface MessagePart {\n type:\n | 'text'\n | 'tool-call'\n | 'tool-result'\n | 'thinking'\n | 'image'\n | 'audio'\n | 'video'\n | 'document'\n content?: string\n toolCallId?: string\n toolName?: string\n arguments?: string\n state?: string\n output?: unknown\n error?: string\n // Multimodal content fields\n source?: ContentPartSource\n metadata?: unknown\n}\n\nexport interface ToolCall {\n id: string\n name: string\n arguments: string\n state: string\n result?: unknown\n approvalRequired?: boolean\n approvalId?: string\n /** Duration of tool execution in milliseconds */\n duration?: number\n}\n\ninterface TokenUsage {\n promptTokens: number\n completionTokens: number\n totalTokens: number\n}\n\nexport interface Message {\n id: string\n role: 'user' | 'assistant' | 'system' | 'tool'\n content: string\n timestamp: number\n parts?: Array<MessagePart>\n toolCalls?: Array<ToolCall>\n /** Consolidated chunks - consecutive same-type chunks are merged into one entry */\n chunks?: Array<Chunk>\n /** Total number of raw chunks received (before consolidation) */\n totalChunkCount?: number\n model?: string\n usage?: TokenUsage\n thinkingContent?: string\n /** Source of the message: 'client' for aggregated client-side data, 'server' for individual server chunks */\n source?: 'client' | 'server'\n}\n\n/**\n * Consolidated chunk - represents one or more raw chunks of the same type.\n * Consecutive content/thinking chunks are merged into a single entry with accumulated content.\n */\nexport interface Chunk {\n id: string\n type:\n | 'content'\n | 'tool_call'\n | 'tool_result'\n | 'done'\n | 'error'\n | 'approval'\n | 'thinking'\n timestamp: number\n messageId?: string\n /** Accumulated content from all merged chunks */\n content?: string\n /** The last delta received (kept for debugging) */\n delta?: string\n toolName?: string\n toolCallId?: string\n finishReason?: string\n error?: string\n approvalId?: string\n input?: unknown\n /** Tool arguments for tool_call chunks */\n arguments?: string\n /** Tool result data for tool_result chunks */\n result?: unknown\n /** Duration in ms for tool execution */\n duration?: number\n /** Number of raw chunks that were merged into this consolidated chunk */\n chunkCount: number\n /** Whether this is a client-side tool execution */\n isClientTool?: boolean\n}\n\nexport interface SummarizeOperation {\n id: string\n model: string\n inputLength: number\n outputLength?: number\n duration?: number\n timestamp: number\n status: 'started' | 'completed'\n}\n\nexport interface ActivityEvent {\n id: string\n name: string\n timestamp: number\n payload: unknown\n}\n\nexport interface Conversation {\n id: string\n type: 'client' | 'server'\n label: string\n messages: Array<Message>\n chunks: Array<Chunk>\n model?: string\n provider?: string\n status: 'active' | 'completed' | 'error'\n startedAt: number\n completedAt?: number\n usage?: TokenUsage\n iterationCount?: number\n toolNames?: Array<string>\n options?: Record<string, unknown>\n modelOptions?: Record<string, unknown>\n systemPrompts?: Array<string>\n /** Flags for which operation types this conversation has */\n hasChat?: boolean\n hasSummarize?: boolean\n hasImage?: boolean\n hasSpeech?: boolean\n hasTranscription?: boolean\n hasVideo?: boolean\n /** Summarize operations in this conversation */\n summaries?: Array<SummarizeOperation>\n imageEvents?: Array<ActivityEvent>\n speechEvents?: Array<ActivityEvent>\n transcriptionEvents?: Array<ActivityEvent>\n videoEvents?: Array<ActivityEvent>\n}\n\ninterface AIStoreState {\n conversations: Record<string, Conversation>\n activeConversationId: string | null\n}\n\ninterface AIContextValue {\n state: AIStoreState\n clearAllConversations: () => void\n selectConversation: (id: string) => void\n}\n\nconst AIContext = createContext<AIContextValue>()\n\nexport function useAIStore(): AIContextValue {\n const context = useContext(AIContext)\n if (!context) {\n throw new Error('useAIStore must be used within an AIProvider')\n }\n return context\n}\n\nexport const AIProvider: ParentComponent = (props) => {\n const [state, setState] = createStore<AIStoreState>({\n conversations: {},\n activeConversationId: null,\n })\n\n const streamToConversation = new Map<string, string>()\n const requestToConversation = new Map<string, string>()\n\n // Batching system for high-frequency chunk updates with consolidated chunk merging\n // Stores: conversationId -> { chunks to merge, totalNewChunks count }\n const pendingConversationChunks = new Map<\n string,\n { chunks: Array<Chunk>; newChunkCount: number }\n >()\n // Stores: conversationId -> messageIndex -> { chunks to merge, totalNewChunks count }\n const pendingMessageChunks = new Map<\n string,\n Map<number, { chunks: Array<Chunk>; newChunkCount: number }>\n >()\n let batchScheduled = false\n\n function scheduleBatchFlush(): void {\n if (batchScheduled) return\n batchScheduled = true\n queueMicrotask(flushPendingChunks)\n }\n\n /** Check if a chunk type can be merged with consecutive same-type chunks */\n function isMergeableChunkType(type: Chunk['type']): boolean {\n return type === 'content' || type === 'thinking'\n }\n\n /** Merge pending chunks into existing chunks array, consolidating consecutive same-type chunks */\n function mergeChunks(existing: Array<Chunk>, pending: Array<Chunk>): void {\n for (const chunk of pending) {\n const lastChunk = existing[existing.length - 1]\n\n // If last chunk exists, is the same type, and both are mergeable types, merge them\n if (\n lastChunk &&\n lastChunk.type === chunk.type &&\n isMergeableChunkType(chunk.type) &&\n lastChunk.messageId === chunk.messageId\n ) {\n // Merge: use the new chunk's content (it's already accumulated), update delta, increment count\n lastChunk.content = chunk.content || lastChunk.content\n lastChunk.delta = chunk.delta\n lastChunk.chunkCount += chunk.chunkCount\n } else {\n // Different type or not mergeable - add as new entry\n existing.push(chunk)\n }\n }\n }\n\n function flushPendingChunks(): void {\n batchScheduled = false\n\n batch(() => {\n // Flush conversation-level chunks\n for (const [\n conversationId,\n { chunks, newChunkCount },\n ] of pendingConversationChunks) {\n const conv = state.conversations[conversationId]\n if (conv) {\n setState(\n 'conversations',\n conversationId,\n 'chunks',\n produce((arr: Array<Chunk>) => {\n mergeChunks(arr, chunks)\n }),\n )\n }\n }\n pendingConversationChunks.clear()\n\n // Flush message-level chunks\n for (const [conversationId, messageMap] of pendingMessageChunks) {\n const conv = state.conversations[conversationId]\n if (!conv) continue\n\n for (const [messageIndex, { chunks, newChunkCount }] of messageMap) {\n const message = conv.messages[messageIndex]\n if (message) {\n // Update chunks array with merging\n setState(\n 'conversations',\n conversationId,\n 'messages',\n messageIndex,\n 'chunks',\n produce((arr: Array<Chunk> | undefined) => {\n if (!arr) {\n // First time - just set the chunks (they're already consolidated in pending)\n return chunks\n }\n mergeChunks(arr, chunks)\n return arr\n }),\n )\n // Update total chunk count\n const currentTotal = message.totalChunkCount || 0\n setState(\n 'conversations',\n conversationId,\n 'messages',\n messageIndex,\n 'totalChunkCount',\n currentTotal + newChunkCount,\n )\n }\n }\n }\n pendingMessageChunks.clear()\n })\n }\n\n function queueChunk(conversationId: string, chunk: Chunk): void {\n if (!pendingConversationChunks.has(conversationId)) {\n pendingConversationChunks.set(conversationId, {\n chunks: [],\n newChunkCount: 0,\n })\n }\n const pending = pendingConversationChunks.get(conversationId)!\n\n // Pre-merge in pending buffer to reduce array operations during flush\n const lastPending = pending.chunks[pending.chunks.length - 1]\n if (\n lastPending &&\n lastPending.type === chunk.type &&\n isMergeableChunkType(chunk.type) &&\n lastPending.messageId === chunk.messageId\n ) {\n // Merge into pending buffer - only append delta (incremental content)\n // Use the new chunk's content as the accumulated content (it's already accumulated)\n lastPending.content = chunk.content || lastPending.content\n lastPending.delta = chunk.delta\n lastPending.chunkCount += chunk.chunkCount\n } else {\n pending.chunks.push(chunk)\n }\n pending.newChunkCount += chunk.chunkCount\n scheduleBatchFlush()\n }\n\n function queueMessageChunk(\n conversationId: string,\n messageIndex: number,\n chunk: Chunk,\n ): void {\n if (!pendingMessageChunks.has(conversationId)) {\n pendingMessageChunks.set(conversationId, new Map())\n }\n const messageMap = pendingMessageChunks.get(conversationId)!\n if (!messageMap.has(messageIndex)) {\n messageMap.set(messageIndex, { chunks: [], newChunkCount: 0 })\n }\n const pending = messageMap.get(messageIndex)!\n\n // Pre-merge in pending buffer\n const lastPending = pending.chunks[pending.chunks.length - 1]\n if (\n lastPending &&\n lastPending.type === chunk.type &&\n isMergeableChunkType(chunk.type) &&\n lastPending.messageId === chunk.messageId\n ) {\n // Merge into pending buffer - only append delta (incremental content)\n // Use the new chunk's content as the accumulated content (it's already accumulated)\n lastPending.content = chunk.content || lastPending.content\n lastPending.delta = chunk.delta\n lastPending.chunkCount += chunk.chunkCount\n } else {\n pending.chunks.push(chunk)\n }\n pending.newChunkCount += chunk.chunkCount\n scheduleBatchFlush()\n }\n\n // Optimized helper functions using path-based updates\n function getOrCreateConversation(\n id: string,\n type: 'client' | 'server',\n label: string,\n ): void {\n if (!state.conversations[id]) {\n setState('conversations', id, {\n id,\n type,\n label,\n messages: [],\n chunks: [],\n imageEvents: [],\n speechEvents: [],\n transcriptionEvents: [],\n videoEvents: [],\n status: 'active',\n startedAt: Date.now(),\n })\n if (!state.activeConversationId) {\n setState('activeConversationId', id)\n }\n }\n }\n\n function addMessage(conversationId: string, message: Message): void {\n const conv = state.conversations[conversationId]\n if (!conv) return\n setState(\n 'conversations',\n conversationId,\n 'messages',\n conv.messages.length,\n message,\n )\n }\n\n function addChunkToMessage(conversationId: string, chunk: Chunk): void {\n const conv = state.conversations[conversationId]\n if (!conv) return\n\n if (chunk.messageId) {\n const messageIndex = conv.messages.findIndex(\n (msg) => msg.id === chunk.messageId,\n )\n\n if (messageIndex !== -1) {\n queueMessageChunk(conversationId, messageIndex, chunk)\n return\n } else {\n // Create new message with the chunk\n const newMessage: Message = {\n id: chunk.messageId,\n role: 'assistant',\n content: '',\n timestamp: chunk.timestamp,\n model: conv.model,\n chunks: [chunk],\n }\n setState(\n 'conversations',\n conversationId,\n 'messages',\n conv.messages.length,\n newMessage,\n )\n return\n }\n }\n\n // Find last assistant message\n for (let i = conv.messages.length - 1; i >= 0; i--) {\n const message = conv.messages[i]\n if (message && message.role === 'assistant') {\n queueMessageChunk(conversationId, i, chunk)\n return\n }\n }\n\n // Fallback: add to conversation's main chunks array if no assistant message found\n addChunk(conversationId, chunk)\n }\n\n function updateMessageUsage(\n conversationId: string,\n messageId: string | undefined,\n cumulativeUsage: TokenUsage,\n ): void {\n const conv = state.conversations[conversationId]\n if (!conv) return\n\n // Calculate the sum of usage from all previous messages (excluding the target message)\n let previousPromptTokens = 0\n let previousCompletionTokens = 0\n\n // Find the target message index\n let targetMessageIndex = -1\n if (messageId) {\n targetMessageIndex = conv.messages.findIndex(\n (msg) => msg.id === messageId,\n )\n } else {\n // Find last assistant message\n for (let i = conv.messages.length - 1; i >= 0; i--) {\n if (conv.messages[i]?.role === 'assistant') {\n targetMessageIndex = i\n break\n }\n }\n }\n\n if (targetMessageIndex === -1) return\n\n // Sum up usage from all previous assistant messages\n for (let i = 0; i < targetMessageIndex; i++) {\n const msg = conv.messages[i]\n if (msg?.role === 'assistant' && msg.usage) {\n previousPromptTokens += msg.usage.promptTokens\n previousCompletionTokens += msg.usage.completionTokens\n }\n }\n\n // Calculate delta usage for this message\n const deltaUsage: TokenUsage = {\n promptTokens: Math.max(\n 0,\n cumulativeUsage.promptTokens - previousPromptTokens,\n ),\n completionTokens: Math.max(\n 0,\n cumulativeUsage.completionTokens - previousCompletionTokens,\n ),\n totalTokens: 0,\n }\n deltaUsage.totalTokens =\n deltaUsage.promptTokens + deltaUsage.completionTokens\n\n setState(\n 'conversations',\n conversationId,\n 'messages',\n targetMessageIndex,\n 'usage',\n deltaUsage,\n )\n }\n\n // Public actions\n function clearAllConversations() {\n setState('conversations', {})\n setState('activeConversationId', null)\n streamToConversation.clear()\n requestToConversation.clear()\n pendingConversationChunks.clear()\n pendingMessageChunks.clear()\n }\n\n function selectConversation(id: string) {\n setState('activeConversationId', id)\n }\n\n // Additional optimized helper functions\n function updateConversation(\n conversationId: string,\n updates: Partial<Conversation>,\n ): void {\n if (!state.conversations[conversationId]) return\n for (const [key, value] of Object.entries(updates)) {\n setState(\n 'conversations',\n conversationId,\n key as keyof Conversation,\n value as Conversation[keyof Conversation],\n )\n }\n }\n\n function updateMessage(\n conversationId: string,\n messageIndex: number,\n updates: Partial<Message>,\n ): void {\n const conv = state.conversations[conversationId]\n if (!conv || !conv.messages[messageIndex]) return\n for (const [key, value] of Object.entries(updates)) {\n setState(\n 'conversations',\n conversationId,\n 'messages',\n messageIndex,\n key as keyof Message,\n value as Message[keyof Message],\n )\n }\n }\n\n function updateToolCall(\n conversationId: string,\n messageIndex: number,\n toolCallIndex: number,\n updates: Partial<ToolCall>,\n ): void {\n const conv = state.conversations[conversationId]\n if (!conv?.messages[messageIndex]?.toolCalls?.[toolCallIndex]) return\n setState(\n 'conversations',\n conversationId,\n 'messages',\n messageIndex,\n 'toolCalls',\n toolCallIndex,\n produce((tc: ToolCall) => Object.assign(tc, updates)),\n )\n }\n\n function setToolCalls(\n conversationId: string,\n messageIndex: number,\n toolCalls: Array<ToolCall>,\n ): void {\n if (!state.conversations[conversationId]?.messages[messageIndex]) return\n setState(\n 'conversations',\n conversationId,\n 'messages',\n messageIndex,\n 'toolCalls',\n toolCalls,\n )\n }\n\n function addChunk(conversationId: string, chunk: Chunk): void {\n if (!state.conversations[conversationId]) return\n queueChunk(conversationId, chunk)\n }\n\n function addActivityEvent(\n conversationId: string,\n activity:\n | 'imageEvents'\n | 'speechEvents'\n | 'transcriptionEvents'\n | 'videoEvents',\n event: ActivityEvent,\n ): void {\n if (!state.conversations[conversationId]) return\n\n setState(\n 'conversations',\n conversationId,\n activity,\n produce((events: Array<ActivityEvent> | undefined) => {\n if (!events) return [event]\n events.push(event)\n return events\n }),\n )\n\n const activityFlagMap: Record<typeof activity, keyof Conversation> = {\n imageEvents: 'hasImage',\n speechEvents: 'hasSpeech',\n transcriptionEvents: 'hasTranscription',\n videoEvents: 'hasVideo',\n }\n\n setState('conversations', conversationId, activityFlagMap[activity], true)\n }\n\n /**\n * For server conversations, ensure a message exists for the given messageId.\n * This creates a placeholder message that will be updated as chunks arrive.\n */\n function ensureMessageForChunk(\n conversationId: string,\n messageId: string | undefined,\n timestamp: number,\n ): void {\n if (!messageId) return\n const conv = state.conversations[conversationId]\n if (!conv || conv.type === 'client') return\n\n // Check if message already exists\n const existingMessage = conv.messages.find((m) => m.id === messageId)\n if (existingMessage) return\n\n // Create a new message for this messageId (server-side message)\n addMessage(conversationId, {\n id: messageId,\n role: 'assistant',\n content: '',\n timestamp,\n source: 'server',\n })\n }\n\n // Register all event listeners on mount\n onMount(() => {\n const cleanupFns: Array<() => void> = []\n\n // ============= Client Events =============\n\n cleanupFns.push(\n aiEventClient.on('client:created', (e) => {\n const clientId = e.payload.clientId\n getOrCreateConversation(\n clientId,\n 'client',\n `Client Chat (${clientId.substring(0, 8)})`,\n )\n updateConversation(clientId, { model: undefined, provider: 'Client' })\n }),\n )\n\n // ============= Message Events =============\n\n cleanupFns.push(\n aiEventClient.on('text:message:created', (e) => {\n const { clientId, streamId, messageId, role, content, timestamp } =\n e.payload\n const conversationId =\n clientId ||\n (streamId ? streamToConversation.get(streamId) : undefined)\n\n if (!conversationId) return\n if (role === 'tool' || role === 'system') return\n\n if (!state.conversations[conversationId]) {\n getOrCreateConversation(\n conversationId,\n clientId ? 'client' : 'server',\n clientId\n ? `Client Chat (${conversationId.substring(0, 8)})`\n : `Server Chat (${conversationId.substring(0, 8)})`,\n )\n }\n\n const conv = state.conversations[conversationId]\n if (!conv) return\n\n const existingIndex = conv.messages.findIndex(\n (message) => message.id === messageId,\n )\n\n const parts = e.payload.parts\n ?.map((part): MessagePart | null => {\n if (part.type === 'text') {\n return { type: 'text', content: part.content }\n }\n if (part.type === 'tool-call') {\n return {\n type: 'tool-call',\n toolCallId: part.id,\n toolName: part.name,\n arguments: part.arguments,\n state: part.state,\n output: part.output,\n content: part.approval\n ? JSON.stringify(part.approval)\n : undefined,\n }\n }\n if (part.type === 'tool-result') {\n return {\n type: 'tool-result',\n toolCallId: part.toolCallId,\n content: part.content,\n state: part.state,\n error: part.error,\n }\n }\n if (part.type === 'thinking') {\n return {\n type: 'thinking',\n content: part.content,\n }\n }\n // Handle multimodal parts (image, audio, video, document)\n // These have a source property instead of content\n if (\n part.type === 'image' ||\n part.type === 'audio' ||\n part.type === 'video' ||\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n part.type === 'document'\n ) {\n return {\n type: part.type,\n source: part.source,\n metadata: part.metadata,\n }\n }\n // Fallback for any unknown part types - skip them\n return null\n })\n .filter((part): part is MessagePart => part !== null)\n\n const toolCalls = e.payload.toolCalls?.map((toolCall) => ({\n id: toolCall.id,\n name: toolCall.function.name,\n arguments: toolCall.function.arguments,\n state: 'input-complete',\n }))\n\n const source = e.payload.source ?? (clientId ? 'client' : 'server')\n\n if (role === 'user' && conv.type === 'client' && source === 'server') {\n return\n }\n\n // Skip empty assistant messages from client - the real content comes from server\n if (\n role === 'assistant' &&\n source === 'client' &&\n !content &&\n (!toolCalls || toolCalls.length === 0)\n ) {\n return\n }\n\n const messagePayload: Message = {\n id: messageId,\n role,\n content,\n timestamp,\n parts,\n toolCalls,\n source,\n }\n\n if (existingIndex >= 0) {\n updateMessage(conversationId, existingIndex, messagePayload)\n } else {\n addMessage(conversationId, messagePayload)\n }\n\n updateConversation(conversationId, { status: 'active', hasChat: true })\n }),\n )\n\n cleanupFns.push(\n aiEventClient.on('text:message:user', (e) => {\n const { clientId, streamId, messageId, content, timestamp } = e.payload\n const conversationId =\n clientId ||\n (streamId ? streamToConversation.get(streamId) : undefined)\n if (!conversationId) return\n\n const conv = state.conversations[conversationId]\n if (!conv) return\n\n const existingIndex = conv.messages.findIndex(\n (message) => message.id === messageId,\n )\n\n if (existingIndex >= 0) return\n\n const source = e.payload.source ?? (clientId ? 'client' : 'server')\n\n if (conv.type === 'client' && source === 'server') {\n return\n }\n\n addMessage(conversationId, {\n id: messageId,\n role: 'user',\n content,\n timestamp,\n source,\n })\n }),\n )\n\n cleanupFns.push(\n aiEventClient.on('client:loading:changed', (e) => {\n const clientId = e.payload.clientId\n if (state.conversations[clientId]) {\n updateConversation(clientId, {\n status: e.payload.isLoading ? 'active' : 'completed',\n })\n }\n }),\n )\n\n cleanupFns.push(\n aiEventClient.on('client:stopped', (e) => {\n const clientId = e.payload.clientId\n if (state.conversations[clientId]) {\n updateConversation(clientId, {\n status: 'completed',\n completedAt: e.payload.timestamp,\n })\n }\n }),\n )\n\n cleanupFns.push(\n aiEventClient.on('client:messages:cleared', (e) => {\n const clientId = e.payload.clientId\n if (state.conversations[clientId]) {\n updateConversation(clientId, {\n messages: [],\n chunks: [],\n usage: undefined,\n })\n }\n }),\n )\n\n cleanupFns.push(\n aiEventClient.on('client:reloaded', (e) => {\n const clientId = e.payload.clientId\n const conv = state.conversations[clientId]\n if (conv) {\n updateConversation(clientId, {\n messages: conv.messages.slice(0, e.payload.fromMessageIndex),\n status: 'active',\n })\n }\n }),\n )\n\n cleanupFns.push(\n aiEventClient.on('client:error:changed', (e) => {\n const clientId = e.payload.clientId\n if (state.conversations[clientId] && e.payload.error) {\n updateConversation(clientId, { status: 'error' })\n }\n }),\n )\n\n // ============= Tool Events =============\n\n cleanupFns.push(\n aiEventClient.on('tools:result:added', (e) => {\n const {\n clientId,\n toolCallId,\n toolName,\n output,\n state: resultState,\n timestamp,\n } = e.payload\n\n if (!clientId) return\n if (!state.conversations[clientId]) return\n\n const conv = state.conversations[clientId]\n\n // Always create a chunk for the tool result\n const chunk: Chunk = {\n id: `chunk-tool-result-${toolCallId}-${Date.now()}`,\n type: 'tool_result',\n toolCallId,\n toolName,\n result: output,\n timestamp,\n chunkCount: 1,\n isClientTool: true,\n }\n\n // Find the message with the tool call and update it\n for (\n let messageIndex = conv.messages.length - 1;\n messageIndex >= 0;\n messageIndex--\n ) {\n const message = conv.messages[messageIndex]\n if (!message?.toolCalls) continue\n\n const toolCallIndex = message.toolCalls.findIndex(\n (t: ToolCall) => t.id === toolCallId,\n )\n if (toolCallIndex >= 0) {\n // Update the tool call state\n updateToolCall(clientId, messageIndex, toolCallIndex, {\n result: output,\n state: resultState === 'output-error' ? 'error' : 'complete',\n })\n\n // Add chunk with message ID\n chunk.messageId = message.id\n addChunkToMessage(clientId, chunk)\n return\n }\n }\n\n // If we couldn't find the message with toolCalls, still add the chunk\n // This handles cases where the message hasn't been processed yet\n // or the tool call is a client-only tool\n addChunkToMessage(clientId, chunk)\n }),\n )\n\n cleanupFns.push(\n aiEventClient.on('tools:approval:responded', (e) => {\n const { clientId, toolCallId, approved } = e.payload\n\n if (!clientId) return\n if (!state.conversations[clientId]) return\n\n const conv = state.conversations[clientId]\n\n for (\n let messageIndex = conv.messages.length - 1;\n messageIndex >= 0;\n messageIndex--\n ) {\n const message = conv.messages[messageIndex]\n if (!message?.toolCalls) continue\n\n const toolCallIndex = message.toolCalls.findIndex(\n (t: ToolCall) => t.id === toolCallId,\n )\n if (toolCallIndex >= 0) {\n updateToolCall(clientId, messageIndex, toolCallIndex, {\n state: approved ? 'approved' : 'denied',\n approvalRequired: false,\n })\n return\n }\n }\n }),\n )\n\n cleanupFns.push(\n aiEventClient.on('tools:call:updated', (e) => {\n const {\n clientId,\n streamId,\n messageId,\n toolCallId,\n toolName,\n state: toolCallState,\n arguments: args,\n } = e.payload\n\n const conversationId =\n clientId ||\n (streamId ? streamToConversation.get(streamId) : undefined)\n if (!conversationId || !state.conversations[conversationId]) return\n\n const conv = state.conversations[conversationId]\n const messageIndex = conv.messages.findIndex(\n (m: Message) => m.id === messageId,\n )\n if (messageIndex === -1) return\n\n const message = conv.messages[messageIndex]\n if (!message) return\n\n const toolCalls = message.toolCalls || []\n const existingToolIndex = toolCalls.findIndex(\n (t: ToolCall) => t.id === toolCallId,\n )\n\n const toolCall: ToolCall = {\n id: toolCallId,\n name: toolName,\n arguments: args,\n state: toolCallState,\n }\n\n if (existingToolIndex >= 0) {\n updateToolCall(\n conversationId,\n messageIndex,\n existingToolIndex,\n toolCall,\n )\n } else {\n setToolCalls(conversationId, messageIndex, [...toolCalls, toolCall])\n }\n }),\n )\n\n cleanupFns.push(\n aiEventClient.on('tools:input:available', (e) => {\n const {\n streamId,\n messageId,\n toolCallId,\n toolName,\n input,\n timestamp,\n clientId,\n } = e.payload\n\n const conversationId =\n clientId ||\n (streamId ? streamToConversation.get(streamId) : undefined)\n if (!conversationId) return\n\n const chunk: Chunk = {\n id: `chunk-${Date.now()}-${Math.random()}`,\n type: 'tool_call',\n messageId: messageId,\n toolCallId,\n toolName,\n arguments: JSON.stringify(input),\n timestamp,\n chunkCount: 1,\n }\n\n const conv = state.conversations[conversationId]\n if (conv?.type === 'client') {\n addChunkToMessage(conversationId, chunk)\n } else {\n addChunk(conversationId, chunk)\n }\n }),\n )\n\n cleanupFns.push(\n aiEventClient.on('tools:call:completed', (e) => {\n const {\n streamId,\n toolCallId,\n toolName,\n result,\n duration,\n messageId,\n timestamp,\n clientId,\n } = e.payload\n\n const conversationId =\n clientId ||\n (streamId ? streamToConversation.get(streamId) : undefined)\n if (!conversationId || !state.conversations[conversationId]) return\n\n const conv = state.conversations[conversationId]\n\n const chunk: Chunk = {\n id: `chunk-tool-result-${toolCallId}-${Date.now()}`,\n type: 'tool_result',\n messageId: messageId,\n toolCallId,\n toolName,\n result,\n duration,\n timestamp,\n chunkCount: 1,\n }\n\n if (conv.type === 'client' && messageId) {\n const messageIndex = conv.messages.findIndex(\n (m) => m.id === messageId,\n )\n if (messageIndex !== -1) {\n queueMessageChunk(conversationId, messageIndex, chunk)\n } else {\n for (let i = conv.messages.length - 1; i >= 0; i--) {\n if (conv.messages[i]?.role === 'assistant') {\n queueMessageChunk(conversationId, i, chunk)\n break\n }\n }\n }\n } else {\n addChunk(conversationId, chunk)\n }\n\n for (let i = conv.messages.length - 1; i >= 0; i--) {\n const message = conv.messages[i]\n if (!message?.toolCalls) continue\n\n const toolCallIndex = message.toolCalls.findIndex(\n (t) => t.id === toolCallId,\n )\n if (toolCallIndex >= 0) {\n updateToolCall(conversationId, i, toolCallIndex, {\n duration,\n result,\n })\n return\n }\n }\n }),\n )\n\n // ============= Stream Events =============\n\n cleanupFns.push(\n aiEventClient.on('text:chunk:content', (e) => {\n const streamId = e.payload.streamId\n const conversationId = streamToConversation.get(streamId)\n if (!conversationId) return\n\n const chunk: Chunk = {\n id: `chunk-${Date.now()}-${Math.random()}`,\n type: 'content',\n messageId: e.payload.messageId,\n content: e.payload.content,\n delta: e.payload.delta,\n timestamp: e.payload.timestamp,\n chunkCount: 1,\n }\n\n const conv = state.conversations[conversationId]\n if (conv?.type === 'client') {\n addChunkToMessage(conversationId, chunk)\n } else {\n ensureMessageForChunk(\n conversationId,\n e.payload.messageId,\n e.payload.timestamp,\n )\n addChunk(conversationId, chunk)\n }\n\n if (e.payload.messageId) {\n const messageIndex = conv?.messages.findIndex(\n (msg) => msg.id === e.payload.messageId,\n )\n if (messageIndex !== undefined && messageIndex >= 0) {\n updateMessage(conversationId, messageIndex, {\n content: e.payload.content,\n })\n }\n }\n }),\n )\n\n cleanupFns.push(\n aiEventClient.on('text:chunk:tool-call', (e) => {\n const streamId = e.payload.streamId\n const conversationId = streamToConversation.get(streamId)\n if (!conversationId) return\n\n const chunk: Chunk = {\n id: `chunk-${Date.now()}-${Math.random()}`,\n type: 'tool_call',\n messageId: e.payload.messageId,\n toolCallId: e.payload.toolCallId,\n toolName: e.payload.toolName,\n arguments: e.payload.arguments,\n timestamp: e.payload.timestamp,\n chunkCount: 1,\n }\n\n const conv = state.conversations[conversationId]\n if (conv?.type === 'client') {\n addChunkToMessage(conversationId, chunk)\n } else {\n ensureMessageForChunk(\n conversationId,\n e.payload.messageId,\n e.payload.timestamp,\n )\n addChunk(conversationId, chunk)\n }\n\n if (e.payload.messageId) {\n const messageIndex = conv?.messages.findIndex(\n (msg) => msg.id === e.payload.messageId,\n )\n if (messageIndex !== undefined && messageIndex >= 0) {\n const message = conv?.messages[messageIndex]\n if (!message) return\n\n const toolCalls = message.toolCalls || []\n const existingToolIndex = toolCalls.findIndex(\n (t: ToolCall) => t.id === e.payload.toolCallId,\n )\n\n const toolCall: ToolCall = {\n id: e.payload.toolCallId,\n name: e.payload.toolName,\n arguments: e.payload.arguments,\n state: 'input-streaming',\n }\n\n if (existingToolIndex >= 0) {\n updateToolCall(\n conversationId,\n messageIndex,\n existingToolIndex,\n toolCall,\n )\n } else {\n setToolCalls(conversationId, messageIndex, [\n ...toolCalls,\n toolCall,\n ])\n }\n }\n }\n }),\n )\n\n cleanupFns.push(\n aiEventClient.on('text:chunk:tool-result', (e) => {\n const streamId = e.payload.streamId\n const conversationId = streamToConversation.get(streamId)\n if (!conversationId) return\n\n const chunk: Chunk = {\n id: `chunk-${Date.now()}-${Math.random()}`,\n type: 'tool_result',\n messageId: e.payload.messageId,\n toolCallId: e.payload.toolCallId,\n result: e.payload.result,\n timestamp: e.payload.timestamp,\n chunkCount: 1,\n }\n\n const conv = state.conversations[conversationId]\n if (conv?.type === 'client') {\n addChunkToMessage(conversationId, chunk)\n } else {\n ensureMessageForChunk(\n conversationId,\n e.payload.messageId,\n e.payload.timestamp,\n )\n addChunk(conversationId, chunk)\n }\n\n // Also update the toolCalls array with the result\n if (conv && e.payload.toolCallId) {\n for (let i = conv.messages.length - 1; i >= 0; i--) {\n const message = conv.messages[i]\n if (!message?.toolCalls) continue\n\n const toolCallIndex = message.toolCalls.findIndex(\n (t) => t.id === e.payload.toolCallId,\n )\n if (toolCallIndex >= 0) {\n updateToolCall(conversationId, i, toolCallIndex, {\n result: e.payload.result,\n state: 'complete',\n })\n break\n }\n }\n }\n }),\n )\n\n cleanupFns.push(\n aiEventClient.on('text:chunk:thinking', (e) => {\n const streamId = e.payload.streamId\n const conversationId = streamToConversation.get(streamId)\n if (!conversationId) return\n\n const chunk: Chunk = {\n id: `chunk-${Date.now()}-${Math.random()}`,\n type: 'thinking',\n messageId: e.payload.messageId,\n content: e.payload.content,\n delta: e.payload.delta,\n timestamp: e.payload.timestamp,\n chunkCount: 1,\n }\n\n const conv = state.conversations[conversationId]\n if (conv?.type === 'client') {\n addChunkToMessage(conversationId, chunk)\n\n if (e.payload.messageId) {\n const messageIndex = conv.messages.findIndex(\n (msg) => msg.id === e.payload.messageId,\n )\n if (messageIndex !== -1) {\n updateMessage(conversationId, messageIndex, {\n thinkingContent: e.payload.content,\n })\n }\n }\n } else {\n ensureMessageForChunk(\n conversationId,\n e.payload.messageId,\n e.payload.timestamp,\n )\n addChunk(conversationId, chunk)\n }\n }),\n )\n\n cleanupFns.push(\n aiEventClient.on('text:chunk:done', (e) => {\n const streamId = e.payload.streamId\n const conversationId = streamToConversation.get(streamId)\n if (!conversationId) return\n\n const chunk: Chunk = {\n id: `chunk-${Date.now()}-${Math.random()}`,\n type: 'done',\n messageId: e.payload.messageId,\n finishReason: e.payload.finishReason || undefined,\n timestamp: e.payload.timestamp,\n chunkCount: 1,\n }\n\n if (e.payload.usage) {\n updateConversation(conversationId, { usage: e.payload.usage })\n updateMessageUsage(\n conversationId,\n e.payload.messageId,\n e.payload.usage,\n )\n }\n\n const conv = state.conversations[conversationId]\n if (conv?.type === 'client') {\n addChunkToMessage(conversationId, chunk)\n } else {\n ensureMessageForChunk(\n conversationId,\n e.payload.messageId,\n e.payload.timestamp,\n )\n addChunk(conversationId, chunk)\n }\n\n updateConversation(conversationId, {\n status: 'completed',\n completedAt: e.payload.timestamp,\n })\n }),\n )\n\n cleanupFns.push(\n aiEventClient.on('text:chunk:error', (e) => {\n const streamId = e.payload.streamId\n const conversationId = streamToConversation.get(streamId)\n if (!conversationId) return\n\n const chunk: Chunk = {\n id: `chunk-${Date.now()}-${Math.random()}`,\n type: 'error',\n messageId: e.payload.messageId,\n error: e.payload.error,\n timestamp: e.payload.timestamp,\n chunkCount: 1,\n }\n\n const conv = state.conversations[conversationId]\n if (conv?.type === 'client') {\n addChunkToMessage(conversationId, chunk)\n } else {\n ensureMessageForChunk(\n conversationId,\n e.payload.messageId,\n e.payload.timestamp,\n )\n addChunk(conversationId, chunk)\n }\n\n updateConversation(conversationId, {\n status: 'error',\n completedAt: e.payload.timestamp,\n })\n }),\n )\n\n cleanupFns.push(\n aiEventClient.on('tools:approval:requested', (e) => {\n const {\n streamId,\n messageId,\n toolCallId,\n toolName,\n input,\n approvalId,\n timestamp,\n clientId,\n } = e.payload\n\n const conversationId =\n clientId || streamToConversation.get(streamId) || ''\n if (!conversationId) return\n\n const conv = state.conversations[conversationId]\n if (!conv) return\n\n const chunk: Chunk = {\n id: `chunk-${Date.now()}-${Math.random()}`,\n type: 'approval',\n messageId: messageId,\n toolCallId,\n toolName,\n approvalId,\n input,\n timestamp,\n chunkCount: 1,\n }\n\n if (conv.type === 'client') {\n addChunkToMessage(conversationId, chunk)\n } else {\n addChunk(conversationId, chunk)\n }\n\n for (let i = conv.messages.length - 1; i >= 0; i--) {\n const message = conv.messages[i]\n if (!message) continue\n\n if (message.role === 'assistant' && message.toolCalls) {\n const toolCallIndex = message.toolCalls.findIndex(\n (t: ToolCall) => t.id === toolCallId,\n )\n if (toolCallIndex >= 0) {\n updateToolCall(conversationId, i, toolCallIndex, {\n approvalRequired: true,\n approvalId,\n state: 'approval-requested',\n })\n return\n }\n }\n }\n }),\n )\n\n // ============= Chat Events (for usage tracking) =============\n\n cleanupFns.push(\n aiEventClient.on('text:request:started', (e) => {\n const streamId = e.payload.streamId\n const model = e.payload.model\n const provider = e.payload.provider\n const clientId = e.payload.clientId\n\n if (clientId && state.conversations[clientId]) {\n streamToConversation.set(streamId, clientId)\n requestToConversation.set(e.payload.requestId, clientId)\n updateConversation(clientId, {\n status: 'active',\n ...e.payload,\n systemPrompts: e.payload.systemPrompts,\n hasChat: true,\n })\n return\n }\n\n const activeClient = Object.values(state.conversations).find(\n (c) => c.type === 'client' && c.status === 'active' && !c.model,\n )\n\n if (activeClient) {\n streamToConversation.set(streamId, activeClient.id)\n requestToConversation.set(e.payload.requestId, activeClient.id)\n updateConversation(activeClient.id, {\n ...e.payload,\n systemPrompts: e.payload.systemPrompts,\n hasChat: true,\n })\n } else {\n const existingServerConv = Object.values(state.conversations).find(\n (c) => c.type === 'server' && c.model === model,\n )\n\n if (existingServerConv) {\n streamToConversation.set(streamId, existingServerConv.id)\n requestToConversation.set(\n e.payload.requestId,\n existingServerConv.id,\n )\n updateConversation(existingServerConv.id, {\n status: 'active',\n ...e.payload,\n systemPrompts: e.payload.systemPrompts,\n hasChat: true,\n })\n } else {\n const serverId = `server-${model}`\n getOrCreateConversation(serverId, 'server', `${model} Server`)\n streamToConversation.set(streamId, serverId)\n requestToConversation.set(e.payload.requestId, serverId)\n updateConversation(serverId, {\n ...e.payload,\n systemPrompts: e.payload.systemPrompts,\n hasChat: true,\n })\n }\n }\n }),\n )\n\n cleanupFns.push(\n aiEventClient.on('text:request:completed', (e) => {\n const { requestId, usage } = e.payload\n\n const conversationId = requestToConversation.get(requestId)\n if (conversationId && state.conversations[conversationId]) {\n const updates: Partial<Conversation> = {\n status: 'completed',\n completedAt: e.payload.timestamp,\n }\n if (usage) {\n updates.usage = usage\n }\n updateConversation(conversationId, updates)\n if (usage) {\n updateMessageUsage(conversationId, e.payload.messageId, usage)\n }\n }\n }),\n )\n\n cleanupFns.push(\n aiEventClient.on('text:usage', (e) => {\n const { requestId, usage, messageId } = e.payload\n\n const conversationId = requestToConversation.get(requestId)\n if (conversationId && state.conversations[conversationId]) {\n updateConversation(conversationId, { usage })\n updateMessageUsage(conversationId, messageId, usage)\n }\n }),\n )\n\n // ============= Summarize Events =============\n\n cleanupFns.push(\n aiEventClient.on('summarize:request:started', (e) => {\n const { requestId, model, inputLength, timestamp, clientId } = e.payload\n\n // Try to find an active conversation to attach to, or create a new one\n let conversationId = clientId\n if (!conversationId || !state.conversations[conversationId]) {\n // Find most recent active client conversation\n const activeClients = Object.values(state.conversations)\n .filter((c) => c.type === 'client' && c.status === 'active')\n .sort((a, b) => b.startedAt - a.startedAt)\n\n if (activeClients.length > 0 && activeClients[0]) {\n conversationId = activeClients[0].id\n } else {\n // Create a new conversation for summaries\n conversationId = `summarize-${requestId}`\n getOrCreateConversation(\n conversationId,\n 'server',\n `Summarize (${model})`,\n )\n updateConversation(conversationId, { model })\n }\n }\n\n requestToConversation.set(requestId, conversationId)\n\n const summarizeOp: SummarizeOperation = {\n id: requestId,\n model,\n inputLength,\n timestamp,\n status: 'started',\n }\n\n const conv = state.conversations[conversationId]\n if (conv) {\n const summaries = conv.summaries || []\n setState('conversations', conversationId, 'summaries', [\n ...summaries,\n summarizeOp,\n ])\n setState('conversations', conversationId, 'hasSummarize', true)\n }\n }),\n )\n\n cleanupFns.push(\n aiEventClient.on('summarize:request:completed', (e) => {\n const { requestId, outputLength, duration } = e.payload\n\n const conversationId = requestToConversation.get(requestId)\n if (!conversationId || !state.conversations[conversationId]) return\n\n const conv = state.conversations[conversationId]\n if (!conv.summaries) return\n\n const summaryIndex = conv.summaries.findIndex(\n (op) => op.id === requestId,\n )\n if (summaryIndex >= 0) {\n setState(\n 'conversations',\n conversationId,\n 'summaries',\n summaryIndex,\n produce((op: SummarizeOperation) => {\n op.duration = duration\n op.outputLength = outputLength\n op.status = 'completed'\n }),\n )\n }\n }),\n )\n\n // ============= Image Events =============\n\n cleanupFns.push(\n aiEventClient.on('image:request:started', (e) => {\n const { requestId, clientId, timestamp } = e.payload\n\n let conversationId = clientId\n if (!conversationId || !state.conversations[conversationId]) {\n conversationId = `image-${requestId}`\n getOrCreateConversation(\n conversationId,\n 'server',\n `Image (${requestId.substring(0, 8)})`,\n )\n }\n\n addActivityEvent(conversationId, 'imageEvents', {\n id: requestId,\n name: 'image:request:started',\n timestamp,\n payload: e.payload,\n })\n }),\n )\n\n cleanupFns.push(\n aiEventClient.on('image:request:completed', (e) => {\n const { requestId, clientId, timestamp } = e.payload\n\n let conversationId = clientId\n if (!conversationId || !state.conversations[conversationId]) {\n conversationId = `image-${requestId}`\n getOrCreateConversation(\n conversationId,\n 'server',\n `Image (${requestId.substring(0, 8)})`,\n )\n }\n\n addActivityEvent(conversationId, 'imageEvents', {\n id: requestId,\n name: 'image:request:completed',\n timestamp,\n payload: e.payload,\n })\n }),\n )\n\n cleanupFns.push(\n aiEventClient.on('image:usage', (e) => {\n const { requestId, clientId, timestamp } = e.payload\n\n let conversationId = clientId\n if (!conversationId || !state.conversations[conversationId]) {\n conversationId = `image-${requestId}`\n getOrCreateConversation(\n conversationId,\n 'server',\n `Image (${requestId.substring(0, 8)})`,\n )\n }\n\n addActivityEvent(conversationId, 'imageEvents', {\n id: requestId,\n name: 'image:usage',\n timestamp,\n payload: e.payload,\n })\n }),\n )\n\n // ============= Speech Events =============\n\n cleanupFns.push(\n aiEventClient.on('speech:request:started', (e) => {\n const { requestId, clientId, timestamp } = e.payload\n\n let conversationId = clientId\n if (!conversationId || !state.conversations[conversationId]) {\n conversationId = `speech-${requestId}`\n getOrCreateConversation(\n conversationId,\n 'server',\n `Speech (${requestId.substring(0, 8)})`,\n )\n }\n\n addActivityEvent(conversationId, 'speechEvents', {\n id: requestId,\n name: 'speech:request:started',\n timestamp,\n payload: e.payload,\n })\n }),\n )\n\n cleanupFns.push(\n aiEventClient.on('speech:request:completed', (e) => {\n const { requestId, clientId, timestamp } = e.payload\n\n let conversationId = clientId\n if (!conversationId || !state.conversations[conversationId]) {\n conversationId = `speech-${requestId}`\n getOrCreateConversation(\n conversationId,\n 'server',\n `Speech (${requestId.substring(0, 8)})`,\n )\n }\n\n addActivityEvent(conversationId, 'speechEvents', {\n id: requestId,\n name: 'speech:request:completed',\n timestamp,\n payload: e.payload,\n })\n }),\n )\n\n cleanupFns.push(\n aiEventClient.on('speech:usage', (e) => {\n const { requestId, clientId, timestamp } = e.payload\n\n let conversationId = clientId\n if (!conversationId || !state.conversations[conversationId]) {\n conversationId = `speech-${requestId}`\n getOrCreateConversation(\n conversationId,\n 'server',\n `Speech (${requestId.substring(0, 8)})`,\n )\n }\n\n addActivityEvent(conversationId, 'speechEvents', {\n id: requestId,\n name: 'speech:usage',\n timestamp,\n payload: e.payload,\n })\n }),\n )\n\n // ============= Transcription Events =============\n\n cleanupFns.push(\n aiEventClient.on('transcription:request:started', (e) => {\n const { requestId, clientId, timestamp } = e.payload\n\n let conversationId = clientId\n if (!conversationId || !state.conversations[conversationId]) {\n conversationId = `transcription-${requestId}`\n getOrCreateConversation(\n conversationId,\n 'server',\n `Transcription (${requestId.substring(0, 8)})`,\n )\n }\n\n addActivityEvent(conversationId, 'transcriptionEvents', {\n id: requestId,\n name: 'transcription:request:started',\n timestamp,\n payload: e.payload,\n })\n }),\n )\n\n cleanupFns.push(\n aiEventClient.on('transcription:request:completed', (e) => {\n const { requestId, clientId, timestamp } = e.payload\n\n let conversationId = clientId\n if (!conversationId || !state.conversations[conversationId]) {\n conversationId = `transcription-${requestId}`\n getOrCreateConversation(\n conversationId,\n 'server',\n `Transcription (${requestId.substring(0, 8)})`,\n )\n }\n\n addActivityEvent(conversationId, 'transcriptionEvents', {\n id: requestId,\n name: 'transcription:request:completed',\n timestamp,\n payload: e.payload,\n })\n }),\n )\n\n cleanupFns.push(\n aiEventClient.on('transcription:usage', (e) => {\n const { requestId, clientId, timestamp } = e.payload\n\n let conversationId = clientId\n if (!conversationId || !state.conversations[conversationId]) {\n conversationId = `transcription-${requestId}`\n getOrCreateConversation(\n conversationId,\n 'server',\n `Transcription (${requestId.substring(0, 8)})`,\n )\n }\n\n addActivityEvent(conversationId, 'transcriptionEvents', {\n id: requestId,\n name: 'transcription:usage',\n timestamp,\n payload: e.payload,\n })\n }),\n )\n\n // ============= Video Events =============\n\n cleanupFns.push(\n aiEventClient.on('video:request:started', (e) => {\n const { requestId, clientId, timestamp } = e.payload\n\n let conversationId = clientId\n if (!conversationId || !state.conversations[conversationId]) {\n conversationId = `video-${requestId}`\n getOrCreateConversation(\n conversationId,\n 'server',\n `Video (${requestId.substring(0, 8)})`,\n )\n }\n\n addActivityEvent(conversationId, 'videoEvents', {\n id: requestId,\n name: 'video:request:started',\n timestamp,\n payload: e.payload,\n })\n }),\n )\n\n cleanupFns.push(\n aiEventClient.on('video:request:completed', (e) => {\n const { requestId, clientId, timestamp } = e.payload\n\n let conversationId = clientId\n if (!conversationId || !state.conversations[conversationId]) {\n conversationId = `video-${requestId}`\n getOrCreateConversation(\n conversationId,\n 'server',\n `Video (${requestId.substring(0, 8)})`,\n )\n }\n\n addActivityEvent(conversationId, 'videoEvents', {\n id: requestId,\n name: 'video:request:completed',\n timestamp,\n payload: e.payload,\n })\n }),\n )\n\n cleanupFns.push(\n aiEventClient.on('video:usage', (e) => {\n const { requestId, clientId, timestamp } = e.payload\n\n let conversationId = clientId\n if (!conversationId || !state.conversations[conversationId]) {\n conversationId = `video-${requestId}`\n getOrCreateConversation(\n conversationId,\n 'server',\n `Video (${requestId.substring(0, 8)})`,\n )\n }\n\n addActivityEvent(conversationId, 'videoEvents', {\n id: requestId,\n name: 'video:usage',\n timestamp,\n payload: e.payload,\n })\n }),\n )\n\n // Cleanup all listeners on unmount\n onCleanup(() => {\n for (const cleanup of cleanupFns) {\n cleanup()\n }\n streamToConversation.clear()\n requestToConversation.clear()\n })\n })\n\n const contextValue: AIContextValue = {\n state,\n clearAllConversations,\n selectConversation,\n }\n\n return (\n <AIContext.Provider value={contextValue}>\n {props.children}\n </AIContext.Provider>\n )\n}\n"],"names":["AIContext","createContext","useAIStore","context","useContext","Error","AIProvider","props","state","setState","createStore","conversations","activeConversationId","streamToConversation","Map","requestToConversation","pendingConversationChunks","pendingMessageChunks","batchScheduled","scheduleBatchFlush","queueMicrotask","flushPendingChunks","isMergeableChunkType","type","mergeChunks","existing","pending","chunk","lastChunk","length","messageId","content","delta","chunkCount","push","batch","conversationId","chunks","newChunkCount","conv","produce","arr","clear","messageMap","messageIndex","message","messages","currentTotal","totalChunkCount","queueChunk","has","set","get","lastPending","queueMessageChunk","getOrCreateConversation","id","label","imageEvents","speechEvents","transcriptionEvents","videoEvents","status","startedAt","Date","now","addMessage","addChunkToMessage","findIndex","msg","newMessage","role","timestamp","model","i","addChunk","updateMessageUsage","cumulativeUsage","previousPromptTokens","previousCompletionTokens","targetMessageIndex","usage","promptTokens","completionTokens","deltaUsage","Math","max","totalTokens","clearAllConversations","selectConversation","updateConversation","updates","key","value","Object","entries","updateMessage","updateToolCall","toolCallIndex","toolCalls","tc","assign","setToolCalls","addActivityEvent","activity","event","events","activityFlagMap","ensureMessageForChunk","existingMessage","find","m","source","onMount","cleanupFns","aiEventClient","on","e","clientId","payload","substring","undefined","provider","streamId","existingIndex","parts","map","part","toolCallId","toolName","name","arguments","output","approval","JSON","stringify","error","metadata","filter","toolCall","function","messagePayload","hasChat","isLoading","completedAt","slice","fromMessageIndex","resultState","result","isClientTool","t","approved","approvalRequired","toolCallState","args","existingToolIndex","input","random","duration","thinkingContent","finishReason","approvalId","requestId","systemPrompts","activeClient","values","c","existingServerConv","serverId","inputLength","activeClients","sort","a","b","summarizeOp","summaries","outputLength","summaryIndex","op","onCleanup","cleanup","contextValue","_$createComponent","Provider","children"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tanstack/ai-devtools-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "Core TanStack AI Devtools",
|
|
5
5
|
"author": "",
|
|
6
6
|
"license": "MIT",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"@tanstack/devtools-utils": "^0.3.0",
|
|
41
41
|
"goober": "^2.1.18",
|
|
42
42
|
"solid-js": "^1.9.10",
|
|
43
|
-
"@tanstack/ai": "0.
|
|
43
|
+
"@tanstack/ai": "0.4.1"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
46
|
"@vitest/coverage-v8": "4.0.14",
|
package/src/store/ai-context.tsx
CHANGED
|
@@ -1,10 +1,19 @@
|
|
|
1
1
|
import { batch, createContext, onCleanup, onMount, useContext } from 'solid-js'
|
|
2
2
|
import { createStore, produce } from 'solid-js/store'
|
|
3
3
|
import { aiEventClient } from '@tanstack/ai/event-client'
|
|
4
|
+
import type { ContentPartSource } from '@tanstack/ai'
|
|
4
5
|
import type { ParentComponent } from 'solid-js'
|
|
5
6
|
|
|
6
7
|
interface MessagePart {
|
|
7
|
-
type:
|
|
8
|
+
type:
|
|
9
|
+
| 'text'
|
|
10
|
+
| 'tool-call'
|
|
11
|
+
| 'tool-result'
|
|
12
|
+
| 'thinking'
|
|
13
|
+
| 'image'
|
|
14
|
+
| 'audio'
|
|
15
|
+
| 'video'
|
|
16
|
+
| 'document'
|
|
8
17
|
content?: string
|
|
9
18
|
toolCallId?: string
|
|
10
19
|
toolName?: string
|
|
@@ -12,6 +21,9 @@ interface MessagePart {
|
|
|
12
21
|
state?: string
|
|
13
22
|
output?: unknown
|
|
14
23
|
error?: string
|
|
24
|
+
// Multimodal content fields
|
|
25
|
+
source?: ContentPartSource
|
|
26
|
+
metadata?: unknown
|
|
15
27
|
}
|
|
16
28
|
|
|
17
29
|
export interface ToolCall {
|
|
@@ -685,37 +697,58 @@ export const AIProvider: ParentComponent = (props) => {
|
|
|
685
697
|
(message) => message.id === messageId,
|
|
686
698
|
)
|
|
687
699
|
|
|
688
|
-
const parts = e.payload.parts
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
type
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
700
|
+
const parts = e.payload.parts
|
|
701
|
+
?.map((part): MessagePart | null => {
|
|
702
|
+
if (part.type === 'text') {
|
|
703
|
+
return { type: 'text', content: part.content }
|
|
704
|
+
}
|
|
705
|
+
if (part.type === 'tool-call') {
|
|
706
|
+
return {
|
|
707
|
+
type: 'tool-call',
|
|
708
|
+
toolCallId: part.id,
|
|
709
|
+
toolName: part.name,
|
|
710
|
+
arguments: part.arguments,
|
|
711
|
+
state: part.state,
|
|
712
|
+
output: part.output,
|
|
713
|
+
content: part.approval
|
|
714
|
+
? JSON.stringify(part.approval)
|
|
715
|
+
: undefined,
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
if (part.type === 'tool-result') {
|
|
719
|
+
return {
|
|
720
|
+
type: 'tool-result',
|
|
721
|
+
toolCallId: part.toolCallId,
|
|
722
|
+
content: part.content,
|
|
723
|
+
state: part.state,
|
|
724
|
+
error: part.error,
|
|
725
|
+
}
|
|
726
|
+
}
|
|
727
|
+
if (part.type === 'thinking') {
|
|
728
|
+
return {
|
|
729
|
+
type: 'thinking',
|
|
730
|
+
content: part.content,
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
// Handle multimodal parts (image, audio, video, document)
|
|
734
|
+
// These have a source property instead of content
|
|
735
|
+
if (
|
|
736
|
+
part.type === 'image' ||
|
|
737
|
+
part.type === 'audio' ||
|
|
738
|
+
part.type === 'video' ||
|
|
739
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
740
|
+
part.type === 'document'
|
|
741
|
+
) {
|
|
742
|
+
return {
|
|
743
|
+
type: part.type,
|
|
744
|
+
source: part.source,
|
|
745
|
+
metadata: part.metadata,
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
// Fallback for any unknown part types - skip them
|
|
749
|
+
return null
|
|
750
|
+
})
|
|
751
|
+
.filter((part): part is MessagePart => part !== null)
|
|
719
752
|
|
|
720
753
|
const toolCalls = e.payload.toolCalls?.map((toolCall) => ({
|
|
721
754
|
id: toolCall.id,
|