@tanstack/ai-devtools-core 0.0.2 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"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'\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}\n\nexport interface EmbeddingOperation {\n id: string\n model: string\n inputCount: number\n duration: number\n timestamp: number\n status: 'started' | 'completed'\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 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 providerOptions?: Record<string, unknown>\n /** Flags for which operation types this conversation has */\n hasChat?: boolean\n hasEmbedding?: boolean\n hasSummarize?: boolean\n /** Embedding operations in this conversation */\n embeddings?: Array<EmbeddingOperation>\n /** Summarize operations in this conversation */\n summaries?: Array<SummarizeOperation>\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 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\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 /**\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(\n 'client:created',\n (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 { withEventTarget: false },\n ),\n )\n\n cleanupFns.push(\n aiEventClient.on(\n 'client:message-sent',\n (e) => {\n const clientId = e.payload.clientId\n if (!state.conversations[clientId]) {\n getOrCreateConversation(\n clientId,\n 'client',\n `Client Chat (${clientId.substring(0, 8)})`,\n )\n }\n addMessage(clientId, {\n id: e.payload.messageId,\n role: 'user',\n content: e.payload.content,\n timestamp: e.payload.timestamp,\n source: 'client',\n })\n updateConversation(clientId, { status: 'active' })\n },\n { withEventTarget: false },\n ),\n )\n\n cleanupFns.push(\n aiEventClient.on(\n 'client:message-appended',\n (e) => {\n const clientId = e.payload.clientId\n const role = e.payload.role\n\n if (role === 'user') return\n if (!state.conversations[clientId]) return\n\n if (role === 'assistant') {\n addMessage(clientId, {\n id: e.payload.messageId,\n role: 'assistant',\n content: e.payload.contentPreview,\n timestamp: e.payload.timestamp,\n source: 'client',\n })\n } else if (role === 'tool') {\n // Tool result message from the LLM\n addMessage(clientId, {\n id: e.payload.messageId,\n role: 'tool',\n content: e.payload.contentPreview,\n timestamp: e.payload.timestamp,\n source: 'client',\n })\n }\n },\n { withEventTarget: false },\n ),\n )\n\n cleanupFns.push(\n aiEventClient.on(\n 'client:loading-changed',\n (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 { withEventTarget: false },\n ),\n )\n\n cleanupFns.push(\n aiEventClient.on(\n 'client:stopped',\n (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 { withEventTarget: false },\n ),\n )\n\n cleanupFns.push(\n aiEventClient.on(\n 'client:messages-cleared',\n (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 { withEventTarget: false },\n ),\n )\n\n cleanupFns.push(\n aiEventClient.on(\n 'client:reloaded',\n (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 { withEventTarget: false },\n ),\n )\n\n cleanupFns.push(\n aiEventClient.on(\n 'client:error-changed',\n (e) => {\n const clientId = e.payload.clientId\n if (state.conversations[clientId] && e.payload.error) {\n updateConversation(clientId, { status: 'error' })\n }\n },\n { withEventTarget: false },\n ),\n )\n\n cleanupFns.push(\n aiEventClient.on(\n 'client:assistant-message-updated',\n (e) => {\n const clientId = e.payload.clientId\n const messageId = e.payload.messageId\n const content = e.payload.content\n\n if (!state.conversations[clientId]) return\n\n const conv = state.conversations[clientId]\n\n // Find message by ID anywhere in the list, not just the last one\n const messageIndex = conv.messages.findIndex(\n (m: Message) => m.id === messageId,\n )\n\n // Only update existing messages, don't create new ones\n // (client:message-appended is responsible for creating messages)\n if (messageIndex >= 0) {\n updateMessage(clientId, messageIndex, {\n content,\n model: conv.model,\n })\n }\n },\n { withEventTarget: false },\n ),\n )\n\n cleanupFns.push(\n aiEventClient.on(\n 'client:tool-call-updated',\n (e) => {\n const {\n clientId,\n messageId,\n toolCallId,\n toolName,\n state: toolCallState,\n arguments: args,\n } = e.payload as {\n clientId: string\n messageId: string\n toolCallId: string\n toolName: string\n state: string\n arguments: unknown\n timestamp: number\n }\n\n if (!state.conversations[clientId]) return\n\n const conv = state.conversations[clientId]\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: JSON.stringify(args, null, 2),\n state: toolCallState,\n }\n\n if (existingToolIndex >= 0) {\n updateToolCall(clientId, messageIndex, existingToolIndex, toolCall)\n } else {\n setToolCalls(clientId, messageIndex, [...toolCalls, toolCall])\n }\n },\n { withEventTarget: false },\n ),\n )\n\n cleanupFns.push(\n aiEventClient.on(\n 'client:approval-requested',\n (e) => {\n const { clientId, messageId, toolCallId, approvalId } = e.payload\n\n if (!state.conversations[clientId]) return\n\n const conv = state.conversations[clientId]\n const messageIndex = conv.messages.findIndex(\n (m) => m.id === messageId,\n )\n if (messageIndex === -1) return\n\n const message = conv.messages[messageIndex]\n if (!message?.toolCalls) return\n\n const toolCallIndex = message.toolCalls.findIndex(\n (t) => t.id === toolCallId,\n )\n if (toolCallIndex === -1) return\n\n updateToolCall(clientId, messageIndex, toolCallIndex, {\n approvalRequired: true,\n approvalId,\n state: 'approval-requested',\n })\n },\n { withEventTarget: false },\n ),\n )\n\n // ============= Tool Events =============\n\n cleanupFns.push(\n aiEventClient.on(\n 'tool:result-added',\n (e) => {\n const {\n clientId,\n toolCallId,\n toolName,\n output,\n state: resultState,\n timestamp,\n } = e.payload\n\n if (!state.conversations[clientId]) return\n\n const conv = state.conversations[clientId]\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 // Also add a chunk to show the tool result in the chunks view\n const chunk: Chunk = {\n id: `chunk-tool-result-${toolCallId}-${Date.now()}`,\n type: 'tool_result',\n messageId: message.id,\n toolCallId,\n toolName,\n result: output,\n timestamp,\n chunkCount: 1,\n }\n addChunkToMessage(clientId, chunk)\n return\n }\n }\n },\n { withEventTarget: false },\n ),\n )\n\n cleanupFns.push(\n aiEventClient.on(\n 'tool:approval-responded',\n (e) => {\n const { clientId, toolCallId, approved } = e.payload\n\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 { withEventTarget: false },\n ),\n )\n\n // ============= Stream Events =============\n\n cleanupFns.push(\n aiEventClient.on(\n 'stream:chunk:content',\n (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 { withEventTarget: false },\n ),\n )\n\n cleanupFns.push(\n aiEventClient.on(\n 'stream:chunk:tool-call',\n (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 { withEventTarget: false },\n ),\n )\n\n cleanupFns.push(\n aiEventClient.on(\n 'stream:chunk:tool-result',\n (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 content: 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 { withEventTarget: false },\n ),\n )\n\n cleanupFns.push(\n aiEventClient.on(\n 'stream:chunk:thinking',\n (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 { withEventTarget: false },\n ),\n )\n\n cleanupFns.push(\n aiEventClient.on(\n 'stream:chunk:done',\n (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 { withEventTarget: false },\n ),\n )\n\n cleanupFns.push(\n aiEventClient.on(\n 'stream:chunk:error',\n (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 { withEventTarget: false },\n ),\n )\n\n cleanupFns.push(\n aiEventClient.on(\n 'stream:ended',\n (e) => {\n const streamId = e.payload.streamId\n const conversationId = streamToConversation.get(streamId)\n if (!conversationId) return\n\n updateConversation(conversationId, {\n status: 'completed',\n completedAt: e.payload.timestamp,\n })\n },\n { withEventTarget: false },\n ),\n )\n\n cleanupFns.push(\n aiEventClient.on(\n 'stream:approval-requested',\n (e) => {\n const {\n streamId,\n messageId,\n toolCallId,\n toolName,\n input,\n approvalId,\n timestamp,\n } = e.payload\n\n const conversationId = 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 { withEventTarget: false },\n ),\n )\n\n // ============= Processor Events =============\n\n cleanupFns.push(\n aiEventClient.on(\n 'processor:text-updated',\n (e) => {\n const streamId = e.payload.streamId\n\n let conversationId = streamToConversation.get(streamId)\n\n if (!conversationId) {\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 streamToConversation.set(streamId, conversationId)\n }\n }\n\n if (!conversationId) return\n\n const conv = state.conversations[conversationId]\n if (!conv) return\n\n // Only update existing assistant messages, don't create new ones\n // (client:message-appended is responsible for creating messages)\n const lastMessage = conv.messages[conv.messages.length - 1]\n if (lastMessage && lastMessage.role === 'assistant') {\n updateMessage(conversationId, conv.messages.length - 1, {\n content: e.payload.content,\n })\n }\n },\n { withEventTarget: false },\n ),\n )\n\n cleanupFns.push(\n aiEventClient.on(\n 'processor:tool-call-state-changed',\n (e) => {\n const streamId = e.payload.streamId\n const conversationId = streamToConversation.get(streamId)\n\n if (!conversationId || !state.conversations[conversationId]) return\n\n const conv = state.conversations[conversationId]\n const lastMessage = conv.messages[conv.messages.length - 1]\n\n if (lastMessage && lastMessage.role === 'assistant') {\n const toolCalls = lastMessage.toolCalls || []\n const existingToolIndex = toolCalls.findIndex(\n (t) => t.id === e.payload.toolCallId,\n )\n\n const toolCall: ToolCall = {\n id: e.payload.toolCallId,\n name: e.payload.toolName,\n arguments: JSON.stringify(e.payload.arguments, null, 2),\n state: e.payload.state,\n }\n\n if (existingToolIndex >= 0) {\n updateToolCall(\n conversationId,\n conv.messages.length - 1,\n existingToolIndex,\n toolCall,\n )\n } else {\n setToolCalls(conversationId, conv.messages.length - 1, [\n ...toolCalls,\n toolCall,\n ])\n }\n }\n },\n { withEventTarget: false },\n ),\n )\n\n cleanupFns.push(\n aiEventClient.on(\n 'processor:tool-result-state-changed',\n (e) => {\n const streamId = e.payload.streamId\n const conversationId = streamToConversation.get(streamId)\n\n if (!conversationId || !state.conversations[conversationId]) return\n\n const conv = state.conversations[conversationId]\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 === e.payload.toolCallId,\n )\n if (toolCallIndex >= 0) {\n updateToolCall(conversationId, i, toolCallIndex, {\n result: e.payload.content,\n state: e.payload.error ? 'error' : e.payload.state,\n })\n return\n }\n }\n },\n { withEventTarget: false },\n ),\n )\n\n // ============= Chat Events (for usage tracking) =============\n\n cleanupFns.push(\n aiEventClient.on(\n 'chat:started',\n (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 updateConversation(clientId, { status: 'active', ...e.payload })\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 updateConversation(activeClient.id, { ...e.payload })\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 updateConversation(existingServerConv.id, {\n status: 'active',\n ...e.payload,\n })\n } else {\n const serverId = `server-${model}`\n getOrCreateConversation(serverId, 'server', `${model} Server`)\n streamToConversation.set(streamId, serverId)\n updateConversation(serverId, { ...e.payload })\n }\n }\n },\n { withEventTarget: false },\n ),\n )\n\n cleanupFns.push(\n aiEventClient.on(\n 'chat:completed',\n (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 { withEventTarget: false },\n ),\n )\n\n cleanupFns.push(\n aiEventClient.on(\n 'chat:iteration',\n (e) => {\n const { requestId, iterationNumber } = e.payload\n\n const conversationId = requestToConversation.get(requestId)\n if (conversationId && state.conversations[conversationId]) {\n updateConversation(conversationId, {\n iterationCount: iterationNumber,\n })\n }\n },\n { withEventTarget: false },\n ),\n )\n\n cleanupFns.push(\n aiEventClient.on(\n 'usage:tokens',\n (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 { withEventTarget: false },\n ),\n )\n\n // ============= Tool Call Completed (with duration) =============\n\n cleanupFns.push(\n aiEventClient.on(\n 'tool:call-completed',\n (e) => {\n const {\n streamId,\n toolCallId,\n toolName,\n result,\n duration,\n messageId,\n timestamp,\n } = e.payload\n\n const conversationId = streamToConversation.get(streamId)\n if (!conversationId || !state.conversations[conversationId]) return\n\n const conv = state.conversations[conversationId]\n\n // Add a tool_result chunk to show the result in the chunks view\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 // Add chunk to message if it's a client conversation, otherwise to conversation\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 // If message not found, add to last assistant message\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 // Update the tool call with duration\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 { withEventTarget: false },\n ),\n )\n\n // ============= Embedding Events =============\n\n cleanupFns.push(\n aiEventClient.on(\n 'embedding:started',\n (e) => {\n const { requestId, model, inputCount, timestamp, clientId } =\n 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 embeddings\n conversationId = `embedding-${requestId}`\n getOrCreateConversation(\n conversationId,\n 'server',\n `Embedding (${model})`,\n )\n updateConversation(conversationId, { model })\n }\n }\n\n requestToConversation.set(requestId, conversationId)\n\n const embeddingOp: EmbeddingOperation = {\n id: requestId,\n model,\n inputCount,\n duration: 0,\n timestamp,\n status: 'started',\n }\n\n const conv = state.conversations[conversationId]\n if (conv) {\n const embeddings = conv.embeddings || []\n setState('conversations', conversationId, 'embeddings', [\n ...embeddings,\n embeddingOp,\n ])\n setState('conversations', conversationId, 'hasEmbedding', true)\n }\n },\n { withEventTarget: false },\n ),\n )\n\n cleanupFns.push(\n aiEventClient.on(\n 'embedding:completed',\n (e) => {\n const { requestId, 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.embeddings) return\n\n const embeddingIndex = conv.embeddings.findIndex(\n (op) => op.id === requestId,\n )\n if (embeddingIndex >= 0) {\n setState(\n 'conversations',\n conversationId,\n 'embeddings',\n embeddingIndex,\n produce((op: EmbeddingOperation) => {\n op.duration = duration\n op.status = 'completed'\n }),\n )\n }\n },\n { withEventTarget: false },\n ),\n )\n\n // ============= Summarize Events =============\n\n cleanupFns.push(\n aiEventClient.on(\n 'summarize:started',\n (e) => {\n const { requestId, model, inputLength, timestamp, clientId } =\n 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 { withEventTarget: false },\n ),\n )\n\n cleanupFns.push(\n aiEventClient.on(\n 'summarize:completed',\n (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 { withEventTarget: false },\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","status","startedAt","Date","now","addMessage","addChunkToMessage","findIndex","msg","newMessage","role","timestamp","model","i","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","addChunk","ensureMessageForChunk","existingMessage","find","m","source","onMount","cleanupFns","aiEventClient","on","e","clientId","payload","substring","undefined","provider","withEventTarget","contentPreview","isLoading","completedAt","slice","fromMessageIndex","error","toolCallId","toolName","toolCallState","arguments","args","existingToolIndex","t","toolCall","name","JSON","stringify","approvalId","approvalRequired","output","resultState","result","approved","streamId","random","thinkingContent","finishReason","input","activeClients","values","filter","c","sort","a","b","lastMessage","activeClient","existingServerConv","serverId","requestId","iterationNumber","iterationCount","duration","inputCount","embeddingOp","embeddings","embeddingIndex","op","inputLength","summarizeOp","summaries","outputLength","summaryIndex","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 { ParentComponent } from 'solid-js'\n\ninterface MessagePart {\n type: 'text' | 'tool-call' | 'tool-result'\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}\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 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 providerOptions?: Record<string, unknown>\n /** Flags for which operation types this conversation has */\n hasChat?: boolean\n hasSummarize?: boolean\n /** Summarize operations in this conversation */\n summaries?: Array<SummarizeOperation>\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 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\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 /**\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 cleanupFns.push(\n aiEventClient.on('client:message-sent', (e) => {\n const clientId = e.payload.clientId\n if (!state.conversations[clientId]) {\n getOrCreateConversation(\n clientId,\n 'client',\n `Client Chat (${clientId.substring(0, 8)})`,\n )\n }\n addMessage(clientId, {\n id: e.payload.messageId,\n role: 'user',\n content: e.payload.content,\n timestamp: e.payload.timestamp,\n source: 'client',\n })\n updateConversation(clientId, { status: 'active' })\n }),\n )\n\n cleanupFns.push(\n aiEventClient.on('client:message-appended', (e) => {\n const clientId = e.payload.clientId\n const role = e.payload.role\n\n if (role === 'user') return\n if (!state.conversations[clientId]) return\n\n if (role === 'assistant') {\n addMessage(clientId, {\n id: e.payload.messageId,\n role: 'assistant',\n content: e.payload.contentPreview,\n timestamp: e.payload.timestamp,\n source: 'client',\n })\n } else if (role === 'tool') {\n // Tool result message from the LLM\n addMessage(clientId, {\n id: e.payload.messageId,\n role: 'tool',\n content: e.payload.contentPreview,\n timestamp: e.payload.timestamp,\n source: 'client',\n })\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 cleanupFns.push(\n aiEventClient.on('client:assistant-message-updated', (e) => {\n const clientId = e.payload.clientId\n const messageId = e.payload.messageId\n const content = e.payload.content\n\n if (!state.conversations[clientId]) return\n\n const conv = state.conversations[clientId]\n\n // Find message by ID anywhere in the list, not just the last one\n const messageIndex = conv.messages.findIndex(\n (m: Message) => m.id === messageId,\n )\n\n // Only update existing messages, don't create new ones\n // (client:message-appended is responsible for creating messages)\n if (messageIndex >= 0) {\n updateMessage(clientId, messageIndex, {\n content,\n model: conv.model,\n })\n }\n }),\n )\n\n cleanupFns.push(\n aiEventClient.on('client:tool-call-updated', (e) => {\n const {\n clientId,\n messageId,\n toolCallId,\n toolName,\n state: toolCallState,\n arguments: args,\n } = e.payload as {\n clientId: string\n messageId: string\n toolCallId: string\n toolName: string\n state: string\n arguments: unknown\n timestamp: number\n }\n\n if (!state.conversations[clientId]) return\n\n const conv = state.conversations[clientId]\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: JSON.stringify(args, null, 2),\n state: toolCallState,\n }\n\n if (existingToolIndex >= 0) {\n updateToolCall(clientId, messageIndex, existingToolIndex, toolCall)\n } else {\n setToolCalls(clientId, messageIndex, [...toolCalls, toolCall])\n }\n }),\n )\n\n cleanupFns.push(\n aiEventClient.on('client:approval-requested', (e) => {\n const { clientId, messageId, toolCallId, approvalId } = e.payload\n\n if (!state.conversations[clientId]) return\n\n const conv = state.conversations[clientId]\n const messageIndex = conv.messages.findIndex((m) => m.id === messageId)\n if (messageIndex === -1) return\n\n const message = conv.messages[messageIndex]\n if (!message?.toolCalls) return\n\n const toolCallIndex = message.toolCalls.findIndex(\n (t) => t.id === toolCallId,\n )\n if (toolCallIndex === -1) return\n\n updateToolCall(clientId, messageIndex, toolCallIndex, {\n approvalRequired: true,\n approvalId,\n state: 'approval-requested',\n })\n }),\n )\n\n // ============= Tool Events =============\n\n cleanupFns.push(\n aiEventClient.on('tool:result-added', (e) => {\n const {\n clientId,\n toolCallId,\n toolName,\n output,\n state: resultState,\n timestamp,\n } = e.payload\n\n if (!state.conversations[clientId]) return\n\n const conv = state.conversations[clientId]\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 // Also add a chunk to show the tool result in the chunks view\n const chunk: Chunk = {\n id: `chunk-tool-result-${toolCallId}-${Date.now()}`,\n type: 'tool_result',\n messageId: message.id,\n toolCallId,\n toolName,\n result: output,\n timestamp,\n chunkCount: 1,\n }\n addChunkToMessage(clientId, chunk)\n return\n }\n }\n }),\n )\n\n cleanupFns.push(\n aiEventClient.on('tool:approval-responded', (e) => {\n const { clientId, toolCallId, approved } = e.payload\n\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 // ============= Stream Events =============\n\n cleanupFns.push(\n aiEventClient.on('stream: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 )\n\n cleanupFns.push(\n aiEventClient.on('stream: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 )\n\n cleanupFns.push(\n aiEventClient.on('stream: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 content: 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('stream: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('stream: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('stream: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('stream:ended', (e) => {\n const streamId = e.payload.streamId\n const conversationId = streamToConversation.get(streamId)\n if (!conversationId) return\n\n updateConversation(conversationId, {\n status: 'completed',\n completedAt: e.payload.timestamp,\n })\n }),\n )\n\n cleanupFns.push(\n aiEventClient.on('stream:approval-requested', (e) => {\n const {\n streamId,\n messageId,\n toolCallId,\n toolName,\n input,\n approvalId,\n timestamp,\n } = e.payload\n\n const conversationId = 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 // ============= Processor Events =============\n\n cleanupFns.push(\n aiEventClient.on('processor:text-updated', (e) => {\n const streamId = e.payload.streamId\n\n let conversationId = streamToConversation.get(streamId)\n\n if (!conversationId) {\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 streamToConversation.set(streamId, conversationId)\n }\n }\n\n if (!conversationId) return\n\n const conv = state.conversations[conversationId]\n if (!conv) return\n\n // Only update existing assistant messages, don't create new ones\n // (client:message-appended is responsible for creating messages)\n const lastMessage = conv.messages[conv.messages.length - 1]\n if (lastMessage && lastMessage.role === 'assistant') {\n updateMessage(conversationId, conv.messages.length - 1, {\n content: e.payload.content,\n })\n }\n }),\n )\n\n cleanupFns.push(\n aiEventClient.on('processor:tool-call-state-changed', (e) => {\n const streamId = e.payload.streamId\n const conversationId = streamToConversation.get(streamId)\n\n if (!conversationId || !state.conversations[conversationId]) return\n\n const conv = state.conversations[conversationId]\n const lastMessage = conv.messages[conv.messages.length - 1]\n\n if (lastMessage && lastMessage.role === 'assistant') {\n const toolCalls = lastMessage.toolCalls || []\n const existingToolIndex = toolCalls.findIndex(\n (t) => t.id === e.payload.toolCallId,\n )\n\n const toolCall: ToolCall = {\n id: e.payload.toolCallId,\n name: e.payload.toolName,\n arguments: JSON.stringify(e.payload.arguments, null, 2),\n state: e.payload.state,\n }\n\n if (existingToolIndex >= 0) {\n updateToolCall(\n conversationId,\n conv.messages.length - 1,\n existingToolIndex,\n toolCall,\n )\n } else {\n setToolCalls(conversationId, conv.messages.length - 1, [\n ...toolCalls,\n toolCall,\n ])\n }\n }\n }),\n )\n\n cleanupFns.push(\n aiEventClient.on('processor:tool-result-state-changed', (e) => {\n const streamId = e.payload.streamId\n const conversationId = streamToConversation.get(streamId)\n\n if (!conversationId || !state.conversations[conversationId]) return\n\n const conv = state.conversations[conversationId]\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 === e.payload.toolCallId,\n )\n if (toolCallIndex >= 0) {\n updateToolCall(conversationId, i, toolCallIndex, {\n result: e.payload.content,\n state: e.payload.error ? 'error' : e.payload.state,\n })\n return\n }\n }\n }),\n )\n\n // ============= Chat Events (for usage tracking) =============\n\n cleanupFns.push(\n aiEventClient.on('text: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 updateConversation(clientId, { status: 'active', ...e.payload })\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 updateConversation(activeClient.id, { ...e.payload })\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 updateConversation(existingServerConv.id, {\n status: 'active',\n ...e.payload,\n })\n } else {\n const serverId = `server-${model}`\n getOrCreateConversation(serverId, 'server', `${model} Server`)\n streamToConversation.set(streamId, serverId)\n updateConversation(serverId, { ...e.payload })\n }\n }\n }),\n )\n\n cleanupFns.push(\n aiEventClient.on('text: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:iteration', (e) => {\n const { requestId, iterationNumber } = e.payload\n\n const conversationId = requestToConversation.get(requestId)\n if (conversationId && state.conversations[conversationId]) {\n updateConversation(conversationId, {\n iterationCount: iterationNumber,\n })\n }\n }),\n )\n\n cleanupFns.push(\n aiEventClient.on('usage:tokens', (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 // ============= Tool Call Completed (with duration) =============\n\n cleanupFns.push(\n aiEventClient.on('tool:call-completed', (e) => {\n const {\n streamId,\n toolCallId,\n toolName,\n result,\n duration,\n messageId,\n timestamp,\n } = e.payload\n\n const conversationId = streamToConversation.get(streamId)\n if (!conversationId || !state.conversations[conversationId]) return\n\n const conv = state.conversations[conversationId]\n\n // Add a tool_result chunk to show the result in the chunks view\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 // Add chunk to message if it's a client conversation, otherwise to conversation\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 // If message not found, add to last assistant message\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 // Update the tool call with duration\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 // ============= Summarize Events =============\n\n cleanupFns.push(\n aiEventClient.on('summarize: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: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 // 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","status","startedAt","Date","now","addMessage","addChunkToMessage","findIndex","msg","newMessage","role","timestamp","model","i","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","addChunk","ensureMessageForChunk","existingMessage","find","m","source","onMount","cleanupFns","aiEventClient","on","e","clientId","payload","substring","undefined","provider","contentPreview","isLoading","completedAt","slice","fromMessageIndex","error","toolCallId","toolName","toolCallState","arguments","args","existingToolIndex","t","toolCall","name","JSON","stringify","approvalId","approvalRequired","output","resultState","result","approved","streamId","random","thinkingContent","finishReason","input","activeClients","values","filter","c","sort","a","b","lastMessage","activeClient","existingServerConv","serverId","requestId","iterationNumber","iterationCount","duration","inputLength","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.0.2",
3
+ "version": "0.1.0",
4
4
  "description": "Core TanStack AI Devtools",
5
5
  "author": "",
6
6
  "license": "MIT",
@@ -40,12 +40,12 @@
40
40
  "@tanstack/devtools-utils": "^0.0.8",
41
41
  "goober": "^2.1.18",
42
42
  "solid-js": "^1.9.10",
43
- "@tanstack/ai": "0.0.2"
43
+ "@tanstack/ai": "0.1.0"
44
44
  },
45
45
  "devDependencies": {
46
46
  "@vitest/coverage-v8": "4.0.14",
47
47
  "jsdom": "^27.2.0",
48
- "vite": "^7.2.4",
48
+ "vite": "^7.2.7",
49
49
  "vite-plugin-solid": "^2.11.10"
50
50
  },
51
51
  "scripts": {
@@ -5,7 +5,6 @@ import {
5
5
  ChunksTab,
6
6
  ConversationHeader,
7
7
  ConversationTabs,
8
- EmbeddingsTab,
9
8
  MessagesTab,
10
9
  SummariesTab,
11
10
  } from './conversation'
@@ -31,11 +30,6 @@ export const ConversationDetails: Component = () => {
31
30
  if (conv.type === 'server') {
32
31
  if (conv.chunks.length > 0) {
33
32
  setActiveTab('chunks')
34
- } else if (
35
- conv.hasEmbedding ||
36
- (conv.embeddings && conv.embeddings.length > 0)
37
- ) {
38
- setActiveTab('embeddings')
39
33
  } else if (
40
34
  conv.hasSummarize ||
41
35
  (conv.summaries && conv.summaries.length > 0)
@@ -75,9 +69,6 @@ export const ConversationDetails: Component = () => {
75
69
  <Show when={activeTab() === 'chunks'}>
76
70
  <ChunksTab chunks={conv().chunks} messages={conv().messages} />
77
71
  </Show>
78
- <Show when={activeTab() === 'embeddings'}>
79
- <EmbeddingsTab embeddings={conv().embeddings ?? []} />
80
- </Show>
81
72
  <Show when={activeTab() === 'summaries'}>
82
73
  <SummariesTab summaries={conv().summaries ?? []} />
83
74
  </Show>
@@ -26,9 +26,7 @@ export const ChunksCollapsible: Component<ChunksCollapsibleProps> = (props) => {
26
26
  <details class={styles().conversationDetails.chunksDetails}>
27
27
  <summary class={styles().conversationDetails.chunksSummary}>
28
28
  <div class={styles().conversationDetails.chunksSummaryRow}>
29
- <span class={styles().conversationDetails.chunksSummaryArrow}>
30
- ▶
31
- </span>
29
+ <span class={styles().conversationDetails.chunksSummaryArrow}>▶</span>
32
30
  <span class={styles().conversationDetails.chunksSummaryTitle}>
33
31
  📦 {totalRawChunks()} chunks
34
32
  </span>
@@ -3,7 +3,7 @@ import { useStyles } from '../../styles/use-styles'
3
3
  import type { Component } from 'solid-js'
4
4
  import type { Conversation } from '../../store/ai-context'
5
5
 
6
- export type TabType = 'messages' | 'chunks' | 'embeddings' | 'summaries'
6
+ export type TabType = 'messages' | 'chunks' | 'summaries'
7
7
 
8
8
  interface ConversationTabsProps {
9
9
  conversation: Conversation
@@ -19,7 +19,6 @@ export const ConversationTabs: Component<ConversationTabsProps> = (props) => {
19
19
  const totalRawChunks = () =>
20
20
  conv().chunks.reduce((sum, c) => sum + (c.chunkCount || 1), 0)
21
21
 
22
- const embeddingsCount = () => conv().embeddings?.length ?? 0
23
22
  const summariesCount = () => conv().summaries?.length ?? 0
24
23
 
25
24
  // Determine if we should show any chat-related tabs
@@ -27,7 +26,6 @@ export const ConversationTabs: Component<ConversationTabsProps> = (props) => {
27
26
  const hasMessages = () =>
28
27
  conv().type === 'client' && conv().messages.length > 0
29
28
  const hasChunks = () => conv().chunks.length > 0 || conv().type === 'server'
30
- const hasEmbeddings = () => conv().hasEmbedding || embeddingsCount() > 0
31
29
  const hasSummaries = () => conv().hasSummarize || summariesCount() > 0
32
30
 
33
31
  // Count how many tabs would be visible
@@ -35,7 +33,6 @@ export const ConversationTabs: Component<ConversationTabsProps> = (props) => {
35
33
  let count = 0
36
34
  if (hasMessages()) count++
37
35
  if (hasChunks() && conv().type === 'server') count++
38
- if (hasEmbeddings()) count++
39
36
  if (hasSummaries()) count++
40
37
  return count
41
38
  }
@@ -73,19 +70,6 @@ export const ConversationTabs: Component<ConversationTabsProps> = (props) => {
73
70
  📦 Chunks ({totalRawChunks()})
74
71
  </button>
75
72
  </Show>
76
- {/* Show embeddings tab if there are embedding operations */}
77
- <Show when={hasEmbeddings()}>
78
- <button
79
- class={`${styles().actionButton} ${
80
- props.activeTab === 'embeddings'
81
- ? styles().conversationDetails.tabButtonActive
82
- : ''
83
- }`}
84
- onClick={() => props.onTabChange('embeddings')}
85
- >
86
- 🔢 Embeddings ({embeddingsCount()})
87
- </button>
88
- </Show>
89
73
  {/* Show summaries tab if there are summarize operations */}
90
74
  <Show when={hasSummaries()}>
91
75
  <button
@@ -4,5 +4,4 @@ export type { TabType } from './ConversationTabs'
4
4
 
5
5
  export { MessagesTab } from './MessagesTab'
6
6
  export { ChunksTab } from './ChunksTab'
7
- export { EmbeddingsTab } from './EmbeddingsTab'
8
7
  export { SummariesTab } from './SummariesTab'