@sqlrooms/ai-core 0.26.0-rc.2 → 0.26.0-rc.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +238 -348
- package/dist/AiSlice.d.ts +37 -7
- package/dist/AiSlice.d.ts.map +1 -1
- package/dist/AiSlice.js +203 -147
- package/dist/AiSlice.js.map +1 -1
- package/dist/chatTransport.d.ts +48 -0
- package/dist/chatTransport.d.ts.map +1 -0
- package/dist/chatTransport.js +270 -0
- package/dist/chatTransport.js.map +1 -0
- package/dist/components/AiThinkingDots.d.ts +10 -0
- package/dist/components/AiThinkingDots.d.ts.map +1 -0
- package/dist/components/AiThinkingDots.js +18 -0
- package/dist/components/AiThinkingDots.js.map +1 -0
- package/dist/components/AnalysisResult.d.ts +1 -2
- package/dist/components/AnalysisResult.d.ts.map +1 -1
- package/dist/components/AnalysisResult.js +48 -18
- package/dist/components/AnalysisResult.js.map +1 -1
- package/dist/components/AnalysisResultsContainer.d.ts.map +1 -1
- package/dist/components/AnalysisResultsContainer.js +5 -10
- package/dist/components/AnalysisResultsContainer.js.map +1 -1
- package/dist/components/QueryControls.d.ts.map +1 -1
- package/dist/components/QueryControls.js +6 -3
- package/dist/components/QueryControls.js.map +1 -1
- package/dist/components/ToolCallInfo.d.ts +25 -0
- package/dist/components/ToolCallInfo.d.ts.map +1 -0
- package/dist/components/ToolCallInfo.js +32 -0
- package/dist/components/ToolCallInfo.js.map +1 -0
- package/dist/components/tools/ToolResult.d.ts +12 -7
- package/dist/components/tools/ToolResult.d.ts.map +1 -1
- package/dist/components/tools/ToolResult.js +8 -6
- package/dist/components/tools/ToolResult.js.map +1 -1
- package/dist/hooks/useAiChat.d.ts +60 -0
- package/dist/hooks/useAiChat.d.ts.map +1 -0
- package/dist/hooks/useAiChat.js +92 -0
- package/dist/hooks/useAiChat.js.map +1 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/utils.d.ts +23 -1
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +24 -0
- package/dist/utils.js.map +1 -1
- package/package.json +15 -14
- package/dist/analysis.d.ts +0 -51
- package/dist/analysis.d.ts.map +0 -1
- package/dist/analysis.js +0 -43
- package/dist/analysis.js.map +0 -1
package/dist/AiSlice.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AiSlice.js","sourceRoot":"","sources":["../src/AiSlice.ts"],"names":[],"mappings":"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","sourcesContent":["import {StreamMessage} from '@openassistant/core';\nimport {ExtendedTool} from '@openassistant/utils';\nimport {createId} from '@paralleldrive/cuid2';\nimport {\n AiSliceConfig,\n AnalysisResultSchema,\n AnalysisSessionSchema,\n createDefaultAiConfig,\n ErrorMessageSchema,\n} from '@sqlrooms/ai-config';\nimport {\n BaseRoomConfig,\n createBaseSlice,\n RoomState,\n useBaseRoomStore,\n type StateCreator,\n} from '@sqlrooms/room-store';\nimport {produce} from 'immer';\nimport {z} from 'zod';\nimport {runAnalysis} from './analysis';\nimport {hasAiSettingsConfig} from './hasAiSettingsConfig';\n\n// template for the tool: Argument, LLM Result, Additional Data, Context\nexport type AiSliceTool = ExtendedTool<z.ZodTypeAny, unknown, unknown, unknown>;\n\nexport type AiSliceState = {\n ai: {\n config: AiSliceConfig;\n analysisPrompt: string;\n isRunningAnalysis: boolean;\n tools: Record<string, AiSliceTool>;\n analysisAbortController?: AbortController;\n setAnalysisPrompt: (prompt: string) => void;\n startAnalysis: () => Promise<void>;\n cancelAnalysis: () => void;\n setAiModel: (modelProvider: string, model: string) => void;\n createSession: (\n name?: string,\n modelProvider?: string,\n model?: string,\n ) => void;\n switchSession: (sessionId: string) => void;\n renameSession: (sessionId: string, name: string) => void;\n deleteSession: (sessionId: string) => void;\n getCurrentSession: () => AnalysisSessionSchema | undefined;\n deleteAnalysisResult: (sessionId: string, resultId: string) => void;\n findToolComponent: (toolName: string) => React.ComponentType | undefined;\n getApiKeyFromSettings: () => string;\n getBaseUrlFromSettings: () => string | undefined;\n getMaxStepsFromSettings: () => number;\n getFullInstructions: () => string;\n };\n};\n\n/**\n * Configuration options for creating an AI slice\n */\nexport interface AiSliceOptions {\n config?: Partial<AiSliceConfig>;\n /** Initial prompt to display in the analysis input */\n initialAnalysisPrompt?: string;\n /** Tools to add to the AI assistant */\n tools: Record<string, AiSliceTool>;\n\n /**\n * Function to get custom instructions for the AI assistant\n * @returns The instructions string to use\n */\n getInstructions: () => string;\n defaultProvider?: string;\n defaultModel?: string;\n maxSteps?: number;\n getApiKey?: (modelProvider: string) => string;\n getBaseUrl?: () => string;\n}\n\nexport function createAiSlice<PC extends BaseRoomConfig>(\n params: AiSliceOptions,\n): StateCreator<AiSliceState> {\n const {\n defaultProvider = 'openai',\n defaultModel = 'gpt-4.1',\n initialAnalysisPrompt = '',\n tools,\n getApiKey,\n getBaseUrl,\n maxSteps,\n getInstructions,\n } = params;\n\n return createBaseSlice<PC, AiSliceState>((set, get, store) => {\n return {\n ai: {\n config: createDefaultAiConfig(params.config),\n\n analysisPrompt: initialAnalysisPrompt,\n isRunningAnalysis: false,\n\n tools,\n\n setAnalysisPrompt: (prompt: string) => {\n set((state) =>\n produce(state, (draft) => {\n draft.ai.analysisPrompt = prompt;\n }),\n );\n },\n\n /**\n * Set the AI model for the current session\n * @param model - The model to set\n */\n setAiModel: (modelProvider: string, model: string) => {\n set((state) =>\n produce(state, (draft) => {\n const currentSession = getCurrentSessionFromState(draft);\n if (currentSession) {\n currentSession.modelProvider = modelProvider;\n currentSession.model = model;\n }\n }),\n );\n },\n\n /**\n * Get the current active session\n */\n getCurrentSession: () => {\n const state = get();\n const {currentSessionId, sessions} = state.ai.config;\n return sessions.find((session) => session.id === currentSessionId);\n },\n\n /**\n * Create a new session with the given name and model settings\n */\n createSession: (\n name?: string,\n modelProvider?: string,\n model?: string,\n ) => {\n const currentSession = get().ai.getCurrentSession();\n const newSessionId = createId();\n\n // Generate a default name if none is provided\n let sessionName = name;\n if (!sessionName) {\n // Generate a human-readable date and time for the session name\n const now = new Date();\n const formattedDate = now.toLocaleDateString('en-US', {\n month: 'short',\n day: 'numeric',\n year: 'numeric',\n });\n const formattedTime = now.toLocaleTimeString('en-US', {\n hour: 'numeric',\n minute: 'numeric',\n hour12: true,\n });\n sessionName = `Session ${formattedDate} at ${formattedTime}`;\n }\n\n set((state) =>\n produce(state, (draft) => {\n // Add to AI sessions\n draft.ai.config.sessions.unshift({\n id: newSessionId,\n name: sessionName,\n modelProvider:\n modelProvider || currentSession?.modelProvider || 'openai',\n model: model || currentSession?.model || 'gpt-4.1',\n analysisResults: [],\n createdAt: new Date(),\n });\n draft.ai.config.currentSessionId = newSessionId;\n }),\n );\n },\n\n /**\n * Switch to a different session\n */\n switchSession: (sessionId: string) => {\n set((state) =>\n produce(state, (draft) => {\n draft.ai.config.currentSessionId = sessionId;\n }),\n );\n },\n\n /**\n * Rename an existing session\n */\n renameSession: (sessionId: string, name: string) => {\n set((state) =>\n produce(state, (draft) => {\n const session = draft.ai.config.sessions.find(\n (s) => s.id === sessionId,\n );\n if (session) {\n session.name = name;\n }\n }),\n );\n },\n\n /**\n * Delete a session\n */\n deleteSession: (sessionId: string) => {\n set((state) =>\n produce(state, (draft) => {\n const sessionIndex = draft.ai.config.sessions.findIndex(\n (s) => s.id === sessionId,\n );\n if (sessionIndex !== -1) {\n // Don't delete the last session\n if (draft.ai.config.sessions.length > 1) {\n draft.ai.config.sessions.splice(sessionIndex, 1);\n // If we deleted the current session, switch to another one\n if (draft.ai.config.currentSessionId === sessionId) {\n // Make sure there's at least one session before accessing its id\n if (draft.ai.config.sessions.length > 0) {\n const firstSession = draft.ai.config.sessions[0];\n if (firstSession) {\n draft.ai.config.currentSessionId = firstSession.id;\n }\n }\n }\n }\n }\n }),\n );\n },\n\n /**\n * Start the analysis\n * TODO: how to pass the history analysisResults?\n */\n startAnalysis: async () => {\n const resultId = createId();\n const abortController = new AbortController();\n const currentSession = get().ai.getCurrentSession();\n\n if (!currentSession) {\n console.error('No current session found');\n return;\n }\n\n set((state) =>\n produce(state, (draft) => {\n draft.ai.analysisAbortController = abortController;\n draft.ai.isRunningAnalysis = true;\n\n const session = draft.ai.config.sessions.find(\n (s) => s.id === draft.ai.config.currentSessionId,\n );\n\n if (session) {\n session.analysisResults.push({\n id: resultId,\n prompt: get().ai.analysisPrompt,\n streamMessage: {\n parts: [\n {\n type: 'text',\n text: '',\n },\n ],\n },\n isCompleted: false,\n });\n }\n }),\n );\n\n try {\n await runAnalysis({\n modelProvider: currentSession.modelProvider || defaultProvider,\n model: currentSession.model || defaultModel,\n apiKey: get().ai.getApiKeyFromSettings(),\n baseUrl: get().ai.getBaseUrlFromSettings(),\n prompt: get().ai.analysisPrompt,\n abortController,\n tools: get().ai.tools,\n maxSteps: get().ai.getMaxStepsFromSettings(),\n getInstructions: get().ai.getFullInstructions,\n historyAnalysis: currentSession.analysisResults,\n onStreamResult: (isCompleted, streamMessage) => {\n set(\n makeResultsAppender({\n resultId,\n streamMessage,\n isCompleted,\n }),\n );\n },\n });\n } catch (err) {\n set(\n makeResultsAppender({\n resultId,\n isCompleted: true,\n errorMessage: {\n error: err instanceof Error ? err.message : String(err),\n },\n }),\n );\n } finally {\n set((state) =>\n produce(state, (draft) => {\n draft.ai.isRunningAnalysis = false;\n draft.ai.analysisPrompt = '';\n }),\n );\n }\n },\n\n cancelAnalysis: () => {\n set((state) =>\n produce(state, (draft) => {\n draft.ai.isRunningAnalysis = false;\n }),\n );\n get().ai.analysisAbortController?.abort('Analysis cancelled');\n },\n\n /**\n * Delete an analysis result from a session\n */\n deleteAnalysisResult: (sessionId: string, resultId: string) => {\n set((state) =>\n produce(state, (draft) => {\n const session = draft.ai.config.sessions.find(\n (s) => s.id === sessionId,\n );\n if (session) {\n session.analysisResults = session.analysisResults.filter(\n (r) => r.id !== resultId,\n );\n }\n }),\n );\n },\n\n findToolComponent: (toolName: string) => {\n return Object.entries(get().ai.tools).find(\n ([name]) => name === toolName,\n )?.[1]?.component as React.ComponentType;\n },\n\n getBaseUrlFromSettings: () => {\n // First try the getBaseUrl function if provided\n const baseUrlFromFunction = getBaseUrl?.();\n if (baseUrlFromFunction) {\n return baseUrlFromFunction;\n }\n\n // Fall back to settings\n const store = get();\n if (hasAiSettingsConfig(store)) {\n const currentSession = getCurrentSessionFromState(store);\n if (currentSession) {\n if (currentSession.modelProvider === 'custom') {\n const customModel = store.aiSettings.config.customModels.find(\n (m: {modelName: string}) =>\n m.modelName === currentSession.model,\n );\n return customModel?.baseUrl;\n }\n const provider =\n store.aiSettings.config.providers[currentSession.modelProvider];\n return provider?.baseUrl;\n }\n }\n return undefined;\n },\n\n getApiKeyFromSettings: () => {\n const store = get();\n const currentSession = getCurrentSessionFromState(store);\n if (currentSession) {\n // First try the getApiKey function if provided\n const apiKeyFromFunction = getApiKey?.(\n currentSession.modelProvider || defaultProvider,\n );\n if (apiKeyFromFunction) {\n return apiKeyFromFunction;\n }\n\n // Fall back to settings\n if (hasAiSettingsConfig(store)) {\n if (currentSession.modelProvider === 'custom') {\n const customModel = store.aiSettings.config.customModels.find(\n (m: {modelName: string}) =>\n m.modelName === currentSession.model,\n );\n return customModel?.apiKey || '';\n } else {\n const provider =\n store.aiSettings.config.providers?.[\n currentSession.modelProvider\n ];\n return provider?.apiKey || '';\n }\n }\n }\n return '';\n },\n\n getMaxStepsFromSettings: () => {\n const store = get();\n // First try the maxSteps parameter if provided\n if (maxSteps && Number.isFinite(maxSteps) && maxSteps > 0) {\n return maxSteps;\n }\n\n // Fall back to settings\n if (hasAiSettingsConfig(store)) {\n const settingsMaxSteps =\n store.aiSettings.config.modelParameters.maxSteps;\n if (Number.isFinite(settingsMaxSteps) && settingsMaxSteps > 0) {\n return settingsMaxSteps;\n }\n }\n return 5;\n },\n\n getFullInstructions: () => {\n const store = get();\n\n let instructions = getInstructions();\n\n // Fall back to settings\n if (hasAiSettingsConfig(store)) {\n // get additional instructions from settings\n const {additionalInstruction} =\n store.aiSettings.config.modelParameters;\n if (additionalInstruction) {\n instructions = `${instructions}\\n\\nAdditional Instructions:\\n\\n${additionalInstruction}`;\n }\n }\n return instructions;\n },\n },\n };\n });\n}\n\n/**\n * Helper function to get the current session from state\n */\nfunction getCurrentSessionFromState<PC extends BaseRoomConfig>(\n state: AiSliceState,\n): AnalysisSessionSchema | undefined {\n const {currentSessionId, sessions} = state.ai.config;\n return sessions.find((session) => session.id === currentSessionId);\n}\n\nfunction findResultById(\n analysisResults: AnalysisResultSchema[],\n id: string,\n): AnalysisResultSchema | undefined {\n return analysisResults.find((result) => result.id === id);\n}\n\n/**\n * Appends the tool results, tool calls, and analysis to the state\n *\n * @param resultId - The id of the result to append to\n * @param message - The message to append to the state. The structure of the message is defined as:\n * - reasoning: string The reasoning of the assistant\n * - toolCallMessages: ToolCallMessage[] The tool call messages\n * - text: string The final text message\n * @param isCompleted - Whether the analysis is completed\n * @returns The new state\n */\nfunction makeResultsAppender({\n resultId,\n streamMessage,\n errorMessage,\n isCompleted,\n}: {\n resultId: string;\n streamMessage?: StreamMessage;\n errorMessage?: ErrorMessageSchema;\n isCompleted?: boolean;\n}) {\n return (state: AiSliceState) =>\n produce(state, (draft) => {\n const currentSession = getCurrentSessionFromState(draft);\n if (!currentSession) {\n console.error('No current session found');\n return;\n }\n\n const result = findResultById(currentSession.analysisResults, resultId);\n if (result) {\n if (streamMessage && streamMessage.parts) {\n // copy all properties from streamMessage\n const newStreamMessage = {\n parts: streamMessage.parts.map((part) => {\n if (part.type === 'text') {\n return {\n type: 'text' as const,\n text: part.text,\n additionalData: part.additionalData,\n isCompleted: part.isCompleted,\n };\n } else if (part.type === 'tool-invocation') {\n return {\n type: 'tool-invocation' as const,\n toolInvocation: {\n toolCallId: part.toolInvocation.toolCallId,\n toolName: part.toolInvocation.toolName,\n args: part.toolInvocation.args,\n state: part.toolInvocation.state,\n result:\n part.toolInvocation.state === 'result'\n ? part.toolInvocation.result\n : undefined,\n },\n additionalData: part.additionalData,\n isCompleted: part.isCompleted,\n };\n } else {\n // TODO: handle other part types later\n return part;\n }\n }),\n };\n\n result.streamMessage = newStreamMessage as StreamMessage;\n }\n if (errorMessage) {\n result.errorMessage = errorMessage;\n }\n if (isCompleted) {\n result.isCompleted = isCompleted;\n }\n } else {\n console.error('Result not found', resultId);\n }\n });\n}\n\nexport function useStoreWithAi<\n T,\n PC extends BaseRoomConfig,\n S extends RoomState<PC> & AiSliceState,\n>(selector: (state: S) => T): T {\n return useBaseRoomStore<PC, RoomState<PC>, T>((state) =>\n selector(state as unknown as S),\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"AiSlice.js","sourceRoot":"","sources":["../src/AiSlice.ts"],"names":[],"mappings":"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","sourcesContent":["import {createId} from '@paralleldrive/cuid2';\nimport {\n AiSliceConfig,\n AnalysisResultSchema,\n AnalysisSessionSchema,\n createDefaultAiConfig,\n} from '@sqlrooms/ai-config';\nimport {\n BaseRoomConfig,\n createBaseSlice,\n RoomState,\n useBaseRoomStore,\n type StateCreator,\n} from '@sqlrooms/room-store';\nimport {produce} from 'immer';\nimport {UIMessage, DefaultChatTransport, LanguageModel} from 'ai';\n\nimport {\n createLocalChatTransportFactory,\n createRemoteChatTransportFactory,\n createChatHandlers,\n} from './chatTransport';\nimport {hasAiSettingsConfig} from './hasAiSettingsConfig';\nimport {OpenAssistantToolSet} from '@openassistant/utils';\n\n// Custom type for onChatToolCall that includes addToolResult\ntype ExtendedChatOnToolCallCallback = (args: {\n toolCall: any;\n addToolResult?: any;\n}) => Promise<any> | any;\n\nexport type AiSliceState = {\n ai: {\n config: AiSliceConfig;\n analysisPrompt: string;\n isRunningAnalysis: boolean;\n tools: OpenAssistantToolSet;\n analysisAbortController?: AbortController;\n setAnalysisPrompt: (prompt: string) => void;\n addAnalysisResult: (message: UIMessage) => void;\n startAnalysis: (\n sendMessage: (message: {text: string}) => void,\n ) => Promise<void>;\n cancelAnalysis: () => void;\n setAiModel: (modelProvider: string, model: string) => void;\n createSession: (\n name?: string,\n modelProvider?: string,\n model?: string,\n ) => void;\n switchSession: (sessionId: string) => void;\n renameSession: (sessionId: string, name: string) => void;\n deleteSession: (sessionId: string) => void;\n getCurrentSession: () => AnalysisSessionSchema | undefined;\n setSessionUiMessages: (sessionId: string, uiMessages: UIMessage[]) => void;\n setSessionToolAdditionalData: (\n sessionId: string,\n toolCallId: string,\n additionalData: unknown,\n ) => void;\n getAnalysisResults: () => AnalysisResultSchema[];\n deleteAnalysisResult: (sessionId: string, resultId: string) => void;\n getAssistantMessageParts: (analysisResultId: string) => UIMessage['parts'];\n findToolComponent: (toolName: string) => React.ComponentType | undefined;\n getApiKeyFromSettings: () => string;\n getBaseUrlFromSettings: () => string | undefined;\n getMaxStepsFromSettings: () => number;\n getFullInstructions: () => string;\n // Chat transport for useChat hook\n getLocalChatTransport: () => DefaultChatTransport<UIMessage>;\n /** Optional remote endpoint to use for chat; if empty, local transport is used */\n chatEndPoint: string;\n chatHeaders: Record<string, string>;\n getRemoteChatTransport: (\n endpoint: string,\n headers?: Record<string, string>,\n ) => DefaultChatTransport<UIMessage>;\n onChatToolCall: ExtendedChatOnToolCallCallback;\n onChatData: (dataPart: any) => void;\n onChatFinish: (args: {\n message: UIMessage;\n messages: UIMessage[];\n isError?: boolean;\n }) => void;\n onChatError: (error: unknown) => void;\n };\n};\n\n/**\n * Configuration options for creating an AI slice\n */\nexport interface AiSliceOptions {\n config?: Partial<AiSliceConfig>;\n /** Initial prompt to display in the analysis input */\n initialAnalysisPrompt?: string;\n /** Tools to add to the AI assistant */\n tools: OpenAssistantToolSet;\n\n /**\n * Function to get custom instructions for the AI assistant\n * @returns The instructions string to use\n */\n getInstructions: () => string;\n defaultProvider?: string;\n defaultModel?: string;\n /** Provide a pre-configured model client for a provider (e.g., Azure). */\n getCustomModel?: () => LanguageModel | undefined;\n maxSteps?: number;\n getApiKey?: (modelProvider: string) => string;\n getBaseUrl?: () => string;\n /** Optional remote endpoint to use for chat; if empty, local transport is used */\n chatEndPoint?: string;\n /** Optional headers to send with remote endpoint */\n chatHeaders?: Record<string, string>;\n}\n\nexport function createAiSlice<PC extends BaseRoomConfig>(\n params: AiSliceOptions,\n): StateCreator<AiSliceState> {\n const {\n initialAnalysisPrompt = '',\n tools,\n getApiKey,\n getBaseUrl,\n maxSteps = 50,\n getInstructions,\n defaultProvider = 'openai',\n defaultModel = 'gpt-4.1',\n getCustomModel,\n chatEndPoint = '',\n chatHeaders = {},\n } = params;\n\n return createBaseSlice<PC, AiSliceState>((set, get, store) => {\n return {\n ai: {\n config: createDefaultAiConfig(params.config),\n analysisPrompt: initialAnalysisPrompt,\n isRunningAnalysis: false,\n tools,\n\n setAnalysisPrompt: (prompt: string) => {\n set((state) =>\n produce(state, (draft) => {\n draft.ai.analysisPrompt = prompt;\n }),\n );\n },\n\n /**\n * Set the AI model for the current session\n * @param model - The model to set\n */\n setAiModel: (modelProvider: string, model: string) => {\n set((state) =>\n produce(state, (draft) => {\n const currentSession = getCurrentSessionFromState(draft);\n if (currentSession) {\n currentSession.modelProvider = modelProvider;\n currentSession.model = model;\n }\n }),\n );\n },\n\n /**\n * Get the current active session\n */\n getCurrentSession: () => {\n const state = get();\n const {currentSessionId, sessions} = state.ai.config;\n return sessions.find((session) => session.id === currentSessionId);\n },\n\n /**\n * Create a new session with the given name and model settings\n */\n createSession: (\n name?: string,\n modelProvider?: string,\n model?: string,\n ) => {\n const currentSession = get().ai.getCurrentSession();\n const newSessionId = createId();\n\n // Generate a default name if none is provided\n let sessionName = name;\n if (!sessionName) {\n // Generate a human-readable date and time for the session name\n const now = new Date();\n const formattedDate = now.toLocaleDateString('en-US', {\n month: 'short',\n day: 'numeric',\n year: 'numeric',\n });\n const formattedTime = now.toLocaleTimeString('en-US', {\n hour: 'numeric',\n minute: 'numeric',\n hour12: true,\n });\n sessionName = `Session ${formattedDate} at ${formattedTime}`;\n }\n\n set((state) =>\n produce(state, (draft) => {\n // Add to AI sessions\n draft.ai.config.sessions.unshift({\n id: newSessionId,\n name: sessionName,\n modelProvider:\n modelProvider || currentSession?.modelProvider || 'openai',\n model: model || currentSession?.model || 'gpt-4.1',\n analysisResults: [],\n createdAt: new Date(),\n uiMessages: [],\n toolAdditionalData: {},\n messagesRevision: 0,\n });\n draft.ai.config.currentSessionId = newSessionId;\n }),\n );\n },\n\n /**\n * Switch to a different session\n */\n switchSession: (sessionId: string) => {\n set((state) =>\n produce(state, (draft) => {\n draft.ai.config.currentSessionId = sessionId;\n }),\n );\n },\n\n /**\n * Rename an existing session\n */\n renameSession: (sessionId: string, name: string) => {\n set((state) =>\n produce(state, (draft) => {\n const session = draft.ai.config.sessions.find(\n (s: AnalysisSessionSchema) => s.id === sessionId,\n );\n if (session) {\n session.name = name;\n }\n }),\n );\n },\n\n /**\n * Delete a session\n */\n deleteSession: (sessionId: string) => {\n set((state) =>\n produce(state, (draft) => {\n const sessionIndex = draft.ai.config.sessions.findIndex(\n (s: AnalysisSessionSchema) => s.id === sessionId,\n );\n if (sessionIndex !== -1) {\n // Don't delete the last session\n if (draft.ai.config.sessions.length > 1) {\n draft.ai.config.sessions.splice(sessionIndex, 1);\n // If we deleted the current session, switch to another one\n if (draft.ai.config.currentSessionId === sessionId) {\n // Make sure there's at least one session before accessing its id\n if (draft.ai.config.sessions.length > 0) {\n const firstSession = draft.ai.config.sessions[0];\n if (firstSession) {\n draft.ai.config.currentSessionId = firstSession.id;\n }\n }\n }\n }\n }\n }),\n );\n },\n\n /**\n * Save the Ai SDK UI messages for a session\n */\n setSessionUiMessages: (sessionId: string, uiMessages: UIMessage[]) => {\n set((state) =>\n produce(state, (draft) => {\n const session = draft.ai.config.sessions.find(\n (s: AnalysisSessionSchema) => s.id === sessionId,\n );\n if (session) {\n // store the latest UI messages from the chat hook\n // Create a deep copy to avoid read-only property issues\n session.uiMessages = JSON.parse(JSON.stringify(uiMessages));\n }\n }),\n );\n },\n\n /**\n * Save additional data for a session\n */\n setSessionToolAdditionalData: (\n sessionId: string,\n toolCallId: string,\n additionalData: unknown,\n ) => {\n set((state) =>\n produce(state, (draft) => {\n const session = draft.ai.config.sessions.find(\n (s) => s.id === sessionId,\n );\n if (session) {\n if (!session.toolAdditionalData) {\n session.toolAdditionalData = {};\n }\n session.toolAdditionalData[toolCallId] = additionalData;\n }\n }),\n );\n },\n\n findToolComponent: (toolName: string) => {\n return get().ai.tools[toolName]?.component as React.ComponentType;\n },\n\n getBaseUrlFromSettings: () => {\n // First try the getBaseUrl function if provided\n const baseUrlFromFunction = getBaseUrl?.();\n if (baseUrlFromFunction) {\n return baseUrlFromFunction;\n }\n\n // Fall back to settings\n const store = get();\n if (hasAiSettingsConfig(store)) {\n const currentSession = getCurrentSessionFromState(store);\n if (currentSession) {\n if (currentSession.modelProvider === 'custom') {\n const customModel = store.aiSettings.config.customModels.find(\n (m: {modelName: string}) =>\n m.modelName === currentSession.model,\n );\n return customModel?.baseUrl;\n }\n const provider =\n store.aiSettings.config.providers[currentSession.modelProvider];\n return provider?.baseUrl;\n }\n }\n return undefined;\n },\n\n getApiKeyFromSettings: () => {\n const store = get();\n const currentSession = getCurrentSessionFromState(store);\n if (currentSession) {\n // First try the getApiKey function if provided\n const apiKeyFromFunction = getApiKey?.(\n currentSession.modelProvider || 'openai',\n );\n if (apiKeyFromFunction) {\n return apiKeyFromFunction;\n }\n\n // Fall back to settings\n if (hasAiSettingsConfig(store)) {\n if (currentSession.modelProvider === 'custom') {\n const customModel = store.aiSettings.config.customModels.find(\n (m: {modelName: string}) =>\n m.modelName === currentSession.model,\n );\n return customModel?.apiKey || '';\n } else {\n const provider =\n store.aiSettings.config.providers?.[\n currentSession.modelProvider\n ];\n return provider?.apiKey || '';\n }\n }\n }\n return '';\n },\n\n getMaxStepsFromSettings: () => {\n const store = get();\n // First try the maxSteps parameter if provided\n if (maxSteps && Number.isFinite(maxSteps) && maxSteps > 0) {\n return maxSteps;\n }\n\n // Fall back to settings\n if (hasAiSettingsConfig(store)) {\n const settingsMaxSteps =\n store.aiSettings.config.modelParameters.maxSteps;\n if (Number.isFinite(settingsMaxSteps) && settingsMaxSteps > 0) {\n return settingsMaxSteps;\n }\n }\n return 50;\n },\n\n getFullInstructions: () => {\n const store = get();\n\n let instructions = getInstructions();\n\n // Fall back to settings\n if (hasAiSettingsConfig(store)) {\n // get additional instructions from settings\n const {additionalInstruction} =\n store.aiSettings.config.modelParameters;\n if (additionalInstruction) {\n instructions = `${instructions}\\n\\nAdditional Instructions:\\n\\n${additionalInstruction}`;\n }\n }\n return instructions;\n },\n\n /**\n * Start the analysis\n * TODO: how to pass the history analysisResults?\n */\n startAnalysis: async (\n sendMessage: (message: {text: string}) => void,\n ) => {\n const abortController = new AbortController();\n const currentSession = get().ai.getCurrentSession();\n\n if (!currentSession) {\n console.error('No current session found');\n return;\n }\n\n const promptText = get().ai.analysisPrompt;\n\n set((state) =>\n produce(state, (draft) => {\n draft.ai.analysisAbortController = abortController;\n draft.ai.isRunningAnalysis = true;\n\n // Add incomplete analysis result to session immediately for instant UI rendering\n const session = draft.ai.config.sessions.find(\n (s: AnalysisSessionSchema) => s.id === currentSession.id,\n );\n if (session) {\n // Add incomplete analysis result with a temporary ID\n // This will be updated in onChatFinish with the actual user message ID\n session.analysisResults.push({\n id: '__pending__',\n prompt: promptText,\n isCompleted: false,\n });\n }\n }),\n );\n\n // The pending analysis result will be updated in onChatFinish with the correct message ID\n sendMessage({text: promptText});\n },\n\n cancelAnalysis: () => {\n const currentSession = get().ai.getCurrentSession();\n set((state) =>\n produce(state, (draft) => {\n draft.ai.isRunningAnalysis = false;\n\n // Remove pending analysis result if it exists\n if (currentSession) {\n const session = draft.ai.config.sessions.find(\n (s: AnalysisSessionSchema) => s.id === currentSession.id,\n );\n if (session) {\n const pendingIndex = session.analysisResults.findIndex(\n (result: AnalysisResultSchema) =>\n result.id === '__pending__',\n );\n if (pendingIndex !== -1) {\n session.analysisResults.splice(pendingIndex, 1);\n }\n }\n }\n }),\n );\n get().ai.analysisAbortController?.abort('Analysis cancelled');\n },\n\n /**\n * Get the assistant message parts for a given analysis result ID\n * @param analysisResultId - The ID of the analysis result (user message ID)\n * @returns Array of message parts from the assistant's response\n */\n getAssistantMessageParts: (analysisResultId: string) => {\n const currentSession = get().ai.getCurrentSession();\n if (!currentSession) return [];\n\n const uiMessages = currentSession.uiMessages as UIMessage[];\n // Find the user message with analysisResultId\n const userMessageIndex = uiMessages.findIndex(\n (msg) => msg.id === analysisResultId && msg.role === 'user',\n );\n if (userMessageIndex === -1) return [];\n\n // Find the next assistant message after this user message\n for (let i = userMessageIndex + 1; i < uiMessages.length; i++) {\n const msg = uiMessages[i];\n if (msg?.role === 'assistant') {\n return msg.parts;\n }\n if (msg?.role === 'user') {\n // Hit next user message without finding assistant response\n break;\n }\n }\n return [];\n },\n\n /**\n * Delete an analysis result from a session\n * - remove the corresponding prompt-response pair from uiMessages\n * - remove the associated toolAdditionalData\n */\n deleteAnalysisResult: (sessionId: string, resultId: string) => {\n set((state) =>\n produce(state, (draft) => {\n const session = draft.ai.config.sessions.find(\n (s: AnalysisSessionSchema) => s.id === sessionId,\n );\n if (session) {\n session.analysisResults = session.analysisResults.filter(\n (r: AnalysisResultSchema) => r.id !== resultId,\n );\n // Remove corresponding prompt-response pair from uiMessages\n const uiMessages = session.uiMessages as UIMessage[];\n const userMessageIndex = uiMessages.findIndex(\n (msg) => msg.id === resultId && msg.role === 'user',\n );\n\n if (userMessageIndex !== -1) {\n // Find the next user message (or end of array) to determine response boundary\n let nextUserIndex = userMessageIndex + 1;\n const toolCallIdsToDelete: Set<string> = new Set();\n\n while (\n nextUserIndex < uiMessages.length &&\n uiMessages[nextUserIndex]?.role !== 'user'\n ) {\n const msg = uiMessages[nextUserIndex];\n // Extract toolCallId from message parts\n if (msg?.parts) {\n for (const part of msg.parts) {\n // Check for tool-* or dynamic-tool parts that have toolCallId\n if (\n 'toolCallId' in part &&\n typeof part.toolCallId === 'string'\n ) {\n toolCallIdsToDelete.add(part.toolCallId);\n }\n }\n }\n nextUserIndex++;\n }\n\n // Remove the user message and all assistant messages until the next user message\n session.uiMessages.splice(\n userMessageIndex,\n nextUserIndex - userMessageIndex,\n );\n\n // Increment messagesRevision to force useChat reset\n session.messagesRevision =\n (session.messagesRevision || 0) + 1;\n\n // Clean up toolAdditionalData for deleted messages\n if (session.toolAdditionalData) {\n // Remove data keyed by the toolCallId from the deleted messages\n toolCallIdsToDelete.forEach((toolCallId) => {\n if (session.toolAdditionalData![toolCallId]) {\n delete session.toolAdditionalData![toolCallId];\n }\n });\n }\n }\n }\n }),\n );\n },\n\n /**\n * Get analysis results for the current session by transforming UI messages\n * into structured analysis results (user prompt → AI response pairs).\n *\n * @returns Array of analysis results for the current session\n */\n getAnalysisResults: (): AnalysisResultSchema[] => {\n const currentSession = get().ai.getCurrentSession();\n if (!currentSession) return [];\n\n return currentSession.analysisResults;\n },\n\n /**\n * Add an analysis result to the current session\n * - add the message to the uiMessages\n * - add the analysis result to the analysisResults\n */\n addAnalysisResult: (message: UIMessage) => {\n const currentSession = get().ai.getCurrentSession();\n if (!currentSession) {\n console.error('No current session found');\n return;\n }\n set((state) =>\n produce(state, (draft) => {\n // Extract text content from message parts\n const textContent =\n message.parts\n ?.filter((part) => part.type === 'text')\n ?.map((part) => (part as {text: string}).text)\n ?.join('') || '';\n\n draft.ai.config.sessions\n .find((s: AnalysisSessionSchema) => s.id === currentSession?.id)\n ?.analysisResults.push({\n id: message.id,\n prompt: textContent,\n isCompleted: true,\n });\n }),\n );\n },\n\n // Chat transport configuration\n chatEndPoint,\n chatHeaders,\n\n getLocalChatTransport: () => {\n const state = get();\n return createLocalChatTransportFactory({\n store,\n defaultProvider: defaultProvider,\n defaultModel: defaultModel,\n apiKey: state.ai.getApiKeyFromSettings(),\n baseUrl: state.ai.getBaseUrlFromSettings(),\n getInstructions: () => store.getState().ai.getFullInstructions(),\n getCustomModel,\n })();\n },\n\n getRemoteChatTransport: (\n endpoint: string,\n headers?: Record<string, string>,\n ) =>\n createRemoteChatTransportFactory({\n store,\n defaultProvider,\n defaultModel,\n })(endpoint, headers),\n\n ...createChatHandlers({store}),\n },\n };\n });\n}\n\n/**\n * Helper function to get the current session from state\n */\nfunction getCurrentSessionFromState(\n state: AiSliceState,\n): AnalysisSessionSchema | undefined {\n const {currentSessionId, sessions} = state.ai.config;\n return sessions.find((session) => session.id === currentSessionId);\n}\n\nexport function useStoreWithAi<\n T,\n PC extends BaseRoomConfig,\n S extends RoomState<PC> & AiSliceState,\n>(selector: (state: S) => T): T {\n return useBaseRoomStore<PC, RoomState<PC>, T>((state) =>\n selector(state as unknown as S),\n );\n}\n"]}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { DefaultChatTransport, UIMessage } from 'ai';
|
|
2
|
+
import type { LanguageModel } from 'ai';
|
|
3
|
+
import type { AiSliceState } from './AiSlice';
|
|
4
|
+
import { AddToolResult } from './hooks/useAiChat';
|
|
5
|
+
import type { StoreApi } from '@sqlrooms/room-store';
|
|
6
|
+
type ToolCall = {
|
|
7
|
+
input: string;
|
|
8
|
+
toolCallId: string;
|
|
9
|
+
toolName: string;
|
|
10
|
+
type: 'tool-input-available';
|
|
11
|
+
};
|
|
12
|
+
export type ChatTransportConfig = {
|
|
13
|
+
store: StoreApi<AiSliceState>;
|
|
14
|
+
defaultProvider: string;
|
|
15
|
+
defaultModel: string;
|
|
16
|
+
apiKey: string;
|
|
17
|
+
baseUrl?: string;
|
|
18
|
+
headers?: Record<string, string>;
|
|
19
|
+
getInstructions: () => string;
|
|
20
|
+
/**
|
|
21
|
+
* Optional: supply a pre-configured custom model.
|
|
22
|
+
* e.g. import {xai} from "@ai-sdk/xai";
|
|
23
|
+
* getCustomModel: () => xai('grok-4')
|
|
24
|
+
* If provided, this model will be used instead of the default OpenAI-compatible client.
|
|
25
|
+
*/
|
|
26
|
+
getCustomModel?: () => LanguageModel | undefined;
|
|
27
|
+
};
|
|
28
|
+
export declare function createLocalChatTransportFactory({ store, defaultProvider, defaultModel, apiKey, baseUrl, headers, getInstructions, getCustomModel, }: ChatTransportConfig): () => DefaultChatTransport<UIMessage<unknown, import("ai").UIDataTypes, import("ai").UITools>>;
|
|
29
|
+
export declare function createRemoteChatTransportFactory(params: {
|
|
30
|
+
store: StoreApi<AiSliceState>;
|
|
31
|
+
defaultProvider: string;
|
|
32
|
+
defaultModel: string;
|
|
33
|
+
}): (endpoint: string, headers?: Record<string, string>) => DefaultChatTransport<UIMessage<unknown, import("ai").UIDataTypes, import("ai").UITools>>;
|
|
34
|
+
export declare function createChatHandlers({ store }: {
|
|
35
|
+
store: StoreApi<AiSliceState>;
|
|
36
|
+
}): {
|
|
37
|
+
onChatToolCall: ({ toolCall, addToolResult, }: {
|
|
38
|
+
toolCall: ToolCall;
|
|
39
|
+
addToolResult?: AddToolResult;
|
|
40
|
+
}) => Promise<void>;
|
|
41
|
+
onChatData: (dataPart: any) => void;
|
|
42
|
+
onChatFinish: ({ messages }: {
|
|
43
|
+
messages: UIMessage[];
|
|
44
|
+
}) => void;
|
|
45
|
+
onChatError: (error: unknown) => void;
|
|
46
|
+
};
|
|
47
|
+
export {};
|
|
48
|
+
//# sourceMappingURL=chatTransport.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chatTransport.d.ts","sourceRoot":"","sources":["../src/chatTransport.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,oBAAoB,EACpB,SAAS,EAGV,MAAM,IAAI,CAAC;AACZ,OAAO,KAAK,EAAC,aAAa,EAAU,MAAM,IAAI,CAAC;AAK/C,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,WAAW,CAAC;AAE5C,OAAO,EAAC,aAAa,EAAC,MAAM,mBAAmB,CAAC;AAChD,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,sBAAsB,CAAC;AAEnD,KAAK,QAAQ,GAAG;IACd,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,sBAAsB,CAAC;CAC9B,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,KAAK,EAAE,QAAQ,CAAC,YAAY,CAAC,CAAC;IAC9B,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,eAAe,EAAE,MAAM,MAAM,CAAC;IAC9B;;;;;OAKG;IACH,cAAc,CAAC,EAAE,MAAM,aAAa,GAAG,SAAS,CAAC;CAClD,CAAC;AAmCF,wBAAgB,+BAA+B,CAAC,EAC9C,KAAK,EACL,eAAe,EACf,YAAY,EACZ,MAAM,EACN,OAAO,EACP,OAAO,EACP,eAAe,EACf,cAAc,GACf,EAAE,mBAAmB,kGA8CrB;AAED,wBAAgB,gCAAgC,CAAC,MAAM,EAAE;IACvD,KAAK,EAAE,QAAQ,CAAC,YAAY,CAAC,CAAC;IAC9B,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;CACtB,IACS,UAAU,MAAM,EAAE,UAAU,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,8FAiC3D;AAED,wBAAgB,kBAAkB,CAAC,EAAC,KAAK,EAAC,EAAE;IAAC,KAAK,EAAE,QAAQ,CAAC,YAAY,CAAC,CAAA;CAAC;mDAKpE;QACD,QAAQ,EAAE,QAAQ,CAAC;QACnB,aAAa,CAAC,EAAE,aAAa,CAAC;KAC/B;2BAwCsB,GAAG;iCAkBC;QAAC,QAAQ,EAAE,SAAS,EAAE,CAAA;KAAC;yBAqE7B,OAAO;EAuE/B"}
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
import { DefaultChatTransport, convertToModelMessages, streamText, } from 'ai';
|
|
2
|
+
import { createOpenAICompatible } from '@ai-sdk/openai-compatible';
|
|
3
|
+
import { convertToVercelAiToolV5 } from '@openassistant/utils';
|
|
4
|
+
import { produce } from 'immer';
|
|
5
|
+
import { getErrorMessageForDisplay } from '@sqlrooms/utils';
|
|
6
|
+
/**
|
|
7
|
+
* Creates a handler for tool completion that updates the tool additional data in the store
|
|
8
|
+
*/
|
|
9
|
+
function createOnToolCompletedHandler(store) {
|
|
10
|
+
return (toolCallId, additionalData) => {
|
|
11
|
+
const sessionId = store.getState().ai.config.currentSessionId;
|
|
12
|
+
if (!sessionId)
|
|
13
|
+
return;
|
|
14
|
+
store
|
|
15
|
+
.getState()
|
|
16
|
+
.ai.setSessionToolAdditionalData(sessionId, toolCallId, additionalData);
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Converts OpenAssistant tools to Vercel AI SDK tools with onToolCompleted handler
|
|
21
|
+
*/
|
|
22
|
+
function convertToAiSDKTools(tools, onToolCompleted) {
|
|
23
|
+
return Object.entries(tools || {}).reduce((acc, [name, tool]) => {
|
|
24
|
+
acc[name] = convertToVercelAiToolV5({
|
|
25
|
+
...tool,
|
|
26
|
+
onToolCompleted,
|
|
27
|
+
});
|
|
28
|
+
return acc;
|
|
29
|
+
}, {});
|
|
30
|
+
}
|
|
31
|
+
export function createLocalChatTransportFactory({ store, defaultProvider, defaultModel, apiKey, baseUrl, headers, getInstructions, getCustomModel, }) {
|
|
32
|
+
return () => {
|
|
33
|
+
const fetchImpl = async (_input, init) => {
|
|
34
|
+
// Resolve provider/model and client at call time to pick up latest settings
|
|
35
|
+
const state = store.getState();
|
|
36
|
+
const currentSession = state.ai.getCurrentSession();
|
|
37
|
+
const provider = currentSession?.modelProvider || defaultProvider;
|
|
38
|
+
const modelId = currentSession?.model || defaultModel;
|
|
39
|
+
// Prefer a user-supplied model if available
|
|
40
|
+
let model = getCustomModel?.();
|
|
41
|
+
// Fallback to OpenAI-compatible if no custom model provided
|
|
42
|
+
if (!model) {
|
|
43
|
+
const openai = createOpenAICompatible({
|
|
44
|
+
apiKey,
|
|
45
|
+
name: provider,
|
|
46
|
+
baseURL: baseUrl || 'https://api.openai.com/v1',
|
|
47
|
+
headers,
|
|
48
|
+
});
|
|
49
|
+
model = openai.chatModel(modelId);
|
|
50
|
+
}
|
|
51
|
+
const body = init?.body;
|
|
52
|
+
const parsed = body ? JSON.parse(body) : {};
|
|
53
|
+
const messagesCopy = JSON.parse(JSON.stringify(parsed.messages || []));
|
|
54
|
+
const onToolCompleted = createOnToolCompletedHandler(store);
|
|
55
|
+
const tools = convertToAiSDKTools(state.ai.tools || {}, onToolCompleted);
|
|
56
|
+
// get system instructions dynamically at request time to ensure fresh table schema
|
|
57
|
+
const systemInstructions = getInstructions();
|
|
58
|
+
const result = streamText({
|
|
59
|
+
model,
|
|
60
|
+
messages: convertToModelMessages(messagesCopy),
|
|
61
|
+
tools,
|
|
62
|
+
system: systemInstructions,
|
|
63
|
+
abortSignal: state.ai.analysisAbortController?.signal,
|
|
64
|
+
});
|
|
65
|
+
return result.toUIMessageStreamResponse();
|
|
66
|
+
};
|
|
67
|
+
return new DefaultChatTransport({ fetch: fetchImpl });
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
export function createRemoteChatTransportFactory(params) {
|
|
71
|
+
return (endpoint, headers) => {
|
|
72
|
+
const fetchImpl = async (input, init) => {
|
|
73
|
+
// Get current session's model and provider at request time
|
|
74
|
+
const state = params.store.getState();
|
|
75
|
+
const currentSession = state.ai.getCurrentSession();
|
|
76
|
+
const modelProvider = currentSession?.modelProvider || params.defaultProvider;
|
|
77
|
+
const model = currentSession?.model || params.defaultModel;
|
|
78
|
+
// Parse the existing body and add model information
|
|
79
|
+
const body = init?.body;
|
|
80
|
+
const parsed = body ? JSON.parse(body) : {};
|
|
81
|
+
const enhancedBody = {
|
|
82
|
+
...parsed,
|
|
83
|
+
modelProvider,
|
|
84
|
+
model,
|
|
85
|
+
};
|
|
86
|
+
// Make the request with enhanced body
|
|
87
|
+
return fetch(input, {
|
|
88
|
+
...init,
|
|
89
|
+
body: JSON.stringify(enhancedBody),
|
|
90
|
+
});
|
|
91
|
+
};
|
|
92
|
+
return new DefaultChatTransport({
|
|
93
|
+
api: endpoint,
|
|
94
|
+
credentials: 'include',
|
|
95
|
+
headers,
|
|
96
|
+
fetch: fetchImpl,
|
|
97
|
+
});
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
export function createChatHandlers({ store }) {
|
|
101
|
+
return {
|
|
102
|
+
onChatToolCall: async ({ toolCall, addToolResult, }) => {
|
|
103
|
+
const { input, toolCallId, toolName } = toolCall;
|
|
104
|
+
try {
|
|
105
|
+
// handle client tools
|
|
106
|
+
const state = store.getState();
|
|
107
|
+
const onToolCompleted = createOnToolCompletedHandler(store);
|
|
108
|
+
const tools = convertToAiSDKTools(state.ai.tools || {}, onToolCompleted);
|
|
109
|
+
// find tool from tools using toolName
|
|
110
|
+
const tool = tools[toolName];
|
|
111
|
+
if (tool && tool.execute) {
|
|
112
|
+
const llmResult = await tool.execute(input, {
|
|
113
|
+
toolCallId,
|
|
114
|
+
messages: [],
|
|
115
|
+
});
|
|
116
|
+
if (addToolResult) {
|
|
117
|
+
// Note: When using sendAutomaticallyWhen, avoid awaiting addToolResult to prevent deadlocks
|
|
118
|
+
addToolResult({
|
|
119
|
+
tool: toolName,
|
|
120
|
+
toolCallId,
|
|
121
|
+
output: llmResult,
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
catch (error) {
|
|
127
|
+
if (addToolResult) {
|
|
128
|
+
addToolResult({
|
|
129
|
+
tool: toolName,
|
|
130
|
+
toolCallId,
|
|
131
|
+
state: 'output-error',
|
|
132
|
+
errorText: getErrorMessageForDisplay(error),
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
},
|
|
137
|
+
onChatData: (dataPart) => {
|
|
138
|
+
// Handle additional tool output data from the backend
|
|
139
|
+
if (dataPart.type === 'data-tool-additional-output') {
|
|
140
|
+
const { toolCallId, output } = dataPart.data;
|
|
141
|
+
// Store the additional data in the session
|
|
142
|
+
const currentSessionId = store.getState().ai.config.currentSessionId;
|
|
143
|
+
if (currentSessionId) {
|
|
144
|
+
store
|
|
145
|
+
.getState()
|
|
146
|
+
.ai.setSessionToolAdditionalData(currentSessionId, toolCallId, output);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
},
|
|
150
|
+
onChatFinish: ({ messages }) => {
|
|
151
|
+
try {
|
|
152
|
+
const currentSessionId = store.getState().ai.config.currentSessionId;
|
|
153
|
+
if (!currentSessionId)
|
|
154
|
+
return;
|
|
155
|
+
store.getState().ai.setSessionUiMessages(currentSessionId, messages);
|
|
156
|
+
// Create or update analysis result with the user message ID for proper correlation
|
|
157
|
+
store.setState((state) => produce(state, (draft) => {
|
|
158
|
+
const targetSession = draft.ai.config.sessions.find((s) => s.id === currentSessionId);
|
|
159
|
+
if (!targetSession)
|
|
160
|
+
return;
|
|
161
|
+
// Find the last user message to get its ID and prompt
|
|
162
|
+
const lastUserMessage = messages
|
|
163
|
+
.filter((msg) => msg.role === 'user')
|
|
164
|
+
.slice(-1)[0];
|
|
165
|
+
if (lastUserMessage) {
|
|
166
|
+
// Extract text content from user message
|
|
167
|
+
const promptText = lastUserMessage.parts
|
|
168
|
+
.filter((part) => part.type === 'text')
|
|
169
|
+
.map((part) => part.text)
|
|
170
|
+
.join('');
|
|
171
|
+
// Check if there's a pending analysis result
|
|
172
|
+
const pendingIndex = targetSession.analysisResults.findIndex((result) => result.id === '__pending__');
|
|
173
|
+
if (pendingIndex !== -1) {
|
|
174
|
+
// Update the pending result with actual data
|
|
175
|
+
targetSession.analysisResults[pendingIndex] = {
|
|
176
|
+
id: lastUserMessage.id,
|
|
177
|
+
prompt: promptText,
|
|
178
|
+
isCompleted: true,
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
else {
|
|
182
|
+
// Check if analysis result already exists for this user message
|
|
183
|
+
const existingResult = targetSession.analysisResults.find((result) => result.id === lastUserMessage.id);
|
|
184
|
+
if (!existingResult) {
|
|
185
|
+
// Create analysis result with the same ID as the user message
|
|
186
|
+
targetSession.analysisResults.push({
|
|
187
|
+
id: lastUserMessage.id,
|
|
188
|
+
prompt: promptText,
|
|
189
|
+
isCompleted: true,
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}));
|
|
195
|
+
store.setState((state) => produce(state, (draft) => {
|
|
196
|
+
draft.ai.isRunningAnalysis = false;
|
|
197
|
+
draft.ai.analysisPrompt = '';
|
|
198
|
+
draft.ai.analysisAbortController = undefined;
|
|
199
|
+
}));
|
|
200
|
+
}
|
|
201
|
+
catch (err) {
|
|
202
|
+
console.error('onChatFinish error:', err);
|
|
203
|
+
throw err;
|
|
204
|
+
}
|
|
205
|
+
},
|
|
206
|
+
onChatError: (error) => {
|
|
207
|
+
try {
|
|
208
|
+
let errMsg = getErrorMessageForDisplay(error);
|
|
209
|
+
if (!errMsg || errMsg.trim().length === 0) {
|
|
210
|
+
errMsg = 'Unknown error';
|
|
211
|
+
}
|
|
212
|
+
const currentSessionId = store.getState().ai.config.currentSessionId;
|
|
213
|
+
store.setState((state) => produce(state, (draft) => {
|
|
214
|
+
if (!currentSessionId)
|
|
215
|
+
return;
|
|
216
|
+
const targetSession = draft.ai.config.sessions.find((s) => s.id === currentSessionId);
|
|
217
|
+
if (targetSession) {
|
|
218
|
+
// Find the last user message to create analysis result with correct ID
|
|
219
|
+
const uiMessages = targetSession.uiMessages;
|
|
220
|
+
const lastUserMessage = uiMessages
|
|
221
|
+
.filter((msg) => msg.role === 'user')
|
|
222
|
+
.slice(-1)[0];
|
|
223
|
+
if (lastUserMessage) {
|
|
224
|
+
// Extract text content from user message
|
|
225
|
+
const promptText = lastUserMessage.parts
|
|
226
|
+
.filter((part) => part.type === 'text')
|
|
227
|
+
.map((part) => part.text)
|
|
228
|
+
.join('');
|
|
229
|
+
// Check if there's a pending analysis result
|
|
230
|
+
const pendingIndex = targetSession.analysisResults.findIndex((result) => result.id === '__pending__');
|
|
231
|
+
if (pendingIndex !== -1) {
|
|
232
|
+
// Update the pending result with error
|
|
233
|
+
targetSession.analysisResults[pendingIndex] = {
|
|
234
|
+
id: lastUserMessage.id,
|
|
235
|
+
prompt: promptText,
|
|
236
|
+
errorMessage: { error: errMsg },
|
|
237
|
+
isCompleted: true,
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
else {
|
|
241
|
+
// Check if analysis result already exists for this user message
|
|
242
|
+
const existingResult = targetSession.analysisResults.find((result) => result.id === lastUserMessage.id);
|
|
243
|
+
if (!existingResult) {
|
|
244
|
+
// Create analysis result with the same ID as the user message
|
|
245
|
+
targetSession.analysisResults.push({
|
|
246
|
+
id: lastUserMessage.id,
|
|
247
|
+
prompt: promptText,
|
|
248
|
+
errorMessage: { error: errMsg },
|
|
249
|
+
isCompleted: true,
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
else {
|
|
253
|
+
// Update existing result with error message
|
|
254
|
+
existingResult.errorMessage = { error: errMsg };
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
draft.ai.isRunningAnalysis = false;
|
|
260
|
+
draft.ai.analysisAbortController = undefined;
|
|
261
|
+
}));
|
|
262
|
+
}
|
|
263
|
+
catch (err) {
|
|
264
|
+
console.error('Failed to store chat error:', err);
|
|
265
|
+
throw err;
|
|
266
|
+
}
|
|
267
|
+
},
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
//# sourceMappingURL=chatTransport.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chatTransport.js","sourceRoot":"","sources":["../src/chatTransport.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n DefaultChatTransport,\n UIMessage,\n convertToModelMessages,\n streamText,\n} from 'ai';\nimport type {LanguageModel, ToolSet} from 'ai';\nimport {createOpenAICompatible} from '@ai-sdk/openai-compatible';\nimport {convertToVercelAiToolV5, OpenAssistantTool} from '@openassistant/utils';\nimport {produce} from 'immer';\nimport {getErrorMessageForDisplay} from '@sqlrooms/utils';\nimport type {AiSliceState} from './AiSlice';\nimport type {AnalysisSessionSchema} from '@sqlrooms/ai-config';\nimport {AddToolResult} from './hooks/useAiChat';\nimport type {StoreApi} from '@sqlrooms/room-store';\n\ntype ToolCall = {\n input: string;\n toolCallId: string;\n toolName: string;\n type: 'tool-input-available';\n};\n\nexport type ChatTransportConfig = {\n store: StoreApi<AiSliceState>;\n defaultProvider: string;\n defaultModel: string;\n apiKey: string;\n baseUrl?: string;\n headers?: Record<string, string>;\n getInstructions: () => string;\n /**\n * Optional: supply a pre-configured custom model.\n * e.g. import {xai} from \"@ai-sdk/xai\";\n * getCustomModel: () => xai('grok-4')\n * If provided, this model will be used instead of the default OpenAI-compatible client.\n */\n getCustomModel?: () => LanguageModel | undefined;\n};\n\n/**\n * Creates a handler for tool completion that updates the tool additional data in the store\n */\nfunction createOnToolCompletedHandler(store: StoreApi<AiSliceState>) {\n return (toolCallId: string, additionalData: unknown) => {\n const sessionId = store.getState().ai.config.currentSessionId;\n if (!sessionId) return;\n\n store\n .getState()\n .ai.setSessionToolAdditionalData(sessionId, toolCallId, additionalData);\n };\n}\n\n/**\n * Converts OpenAssistant tools to Vercel AI SDK tools with onToolCompleted handler\n */\nfunction convertToAiSDKTools(\n tools: Record<string, OpenAssistantTool>,\n onToolCompleted: (toolCallId: string, additionalData: unknown) => void,\n): ToolSet {\n return Object.entries(tools || {}).reduce(\n (acc: ToolSet, [name, tool]: [string, OpenAssistantTool]) => {\n acc[name] = convertToVercelAiToolV5({\n ...tool,\n onToolCompleted,\n });\n return acc;\n },\n {},\n );\n}\n\nexport function createLocalChatTransportFactory({\n store,\n defaultProvider,\n defaultModel,\n apiKey,\n baseUrl,\n headers,\n getInstructions,\n getCustomModel,\n}: ChatTransportConfig) {\n return () => {\n const fetchImpl = async (_input: RequestInfo | URL, init?: RequestInit) => {\n // Resolve provider/model and client at call time to pick up latest settings\n const state = store.getState();\n const currentSession = state.ai.getCurrentSession();\n const provider = currentSession?.modelProvider || defaultProvider;\n const modelId = currentSession?.model || defaultModel;\n\n // Prefer a user-supplied model if available\n let model: LanguageModel | undefined = getCustomModel?.();\n\n // Fallback to OpenAI-compatible if no custom model provided\n if (!model) {\n const openai = createOpenAICompatible({\n apiKey,\n name: provider,\n baseURL: baseUrl || 'https://api.openai.com/v1',\n headers,\n });\n model = openai.chatModel(modelId);\n }\n\n const body = init?.body as string;\n const parsed = body ? JSON.parse(body) : {};\n const messagesCopy = JSON.parse(JSON.stringify(parsed.messages || []));\n\n const onToolCompleted = createOnToolCompletedHandler(store);\n const tools = convertToAiSDKTools(state.ai.tools || {}, onToolCompleted);\n\n // get system instructions dynamically at request time to ensure fresh table schema\n const systemInstructions = getInstructions();\n\n const result = streamText({\n model,\n messages: convertToModelMessages(messagesCopy),\n tools,\n system: systemInstructions,\n abortSignal: state.ai.analysisAbortController?.signal,\n });\n\n return result.toUIMessageStreamResponse();\n };\n\n return new DefaultChatTransport({fetch: fetchImpl});\n };\n}\n\nexport function createRemoteChatTransportFactory(params: {\n store: StoreApi<AiSliceState>;\n defaultProvider: string;\n defaultModel: string;\n}) {\n return (endpoint: string, headers?: Record<string, string>) => {\n const fetchImpl = async (input: RequestInfo | URL, init?: RequestInit) => {\n // Get current session's model and provider at request time\n const state = params.store.getState();\n const currentSession = state.ai.getCurrentSession();\n const modelProvider =\n currentSession?.modelProvider || params.defaultProvider;\n const model = currentSession?.model || params.defaultModel;\n\n // Parse the existing body and add model information\n const body = init?.body as string;\n const parsed = body ? JSON.parse(body) : {};\n\n const enhancedBody = {\n ...parsed,\n modelProvider,\n model,\n };\n\n // Make the request with enhanced body\n return fetch(input, {\n ...init,\n body: JSON.stringify(enhancedBody),\n });\n };\n\n return new DefaultChatTransport({\n api: endpoint,\n credentials: 'include',\n headers,\n fetch: fetchImpl,\n });\n };\n}\n\nexport function createChatHandlers({store}: {store: StoreApi<AiSliceState>}) {\n return {\n onChatToolCall: async ({\n toolCall,\n addToolResult,\n }: {\n toolCall: ToolCall;\n addToolResult?: AddToolResult;\n }) => {\n const {input, toolCallId, toolName} = toolCall;\n try {\n // handle client tools\n const state = store.getState();\n\n const onToolCompleted = createOnToolCompletedHandler(store);\n const tools = convertToAiSDKTools(\n state.ai.tools || {},\n onToolCompleted,\n );\n\n // find tool from tools using toolName\n const tool = tools[toolName];\n if (tool && tool.execute) {\n const llmResult = await tool.execute(input, {\n toolCallId,\n messages: [],\n });\n\n if (addToolResult) {\n // Note: When using sendAutomaticallyWhen, avoid awaiting addToolResult to prevent deadlocks\n addToolResult({\n tool: toolName,\n toolCallId,\n output: llmResult,\n });\n }\n }\n } catch (error) {\n if (addToolResult) {\n addToolResult({\n tool: toolName,\n toolCallId,\n state: 'output-error',\n errorText: getErrorMessageForDisplay(error),\n });\n }\n }\n },\n onChatData: (dataPart: any) => {\n // Handle additional tool output data from the backend\n if (dataPart.type === 'data-tool-additional-output') {\n const {toolCallId, output} = dataPart.data;\n\n // Store the additional data in the session\n const currentSessionId = store.getState().ai.config.currentSessionId;\n if (currentSessionId) {\n store\n .getState()\n .ai.setSessionToolAdditionalData(\n currentSessionId,\n toolCallId,\n output,\n );\n }\n }\n },\n onChatFinish: ({messages}: {messages: UIMessage[]}) => {\n try {\n const currentSessionId = store.getState().ai.config.currentSessionId;\n if (!currentSessionId) return;\n\n store.getState().ai.setSessionUiMessages(currentSessionId, messages);\n\n // Create or update analysis result with the user message ID for proper correlation\n store.setState((state: AiSliceState) =>\n produce(state, (draft: AiSliceState) => {\n const targetSession = draft.ai.config.sessions.find(\n (s: AnalysisSessionSchema) => s.id === currentSessionId,\n );\n if (!targetSession) return;\n\n // Find the last user message to get its ID and prompt\n const lastUserMessage = messages\n .filter((msg) => msg.role === 'user')\n .slice(-1)[0];\n\n if (lastUserMessage) {\n // Extract text content from user message\n const promptText = lastUserMessage.parts\n .filter((part) => part.type === 'text')\n .map((part) => (part as {text: string}).text)\n .join('');\n\n // Check if there's a pending analysis result\n const pendingIndex = targetSession.analysisResults.findIndex(\n (result: any) => result.id === '__pending__',\n );\n\n if (pendingIndex !== -1) {\n // Update the pending result with actual data\n targetSession.analysisResults[pendingIndex] = {\n id: lastUserMessage.id,\n prompt: promptText,\n isCompleted: true,\n };\n } else {\n // Check if analysis result already exists for this user message\n const existingResult = targetSession.analysisResults.find(\n (result: any) => result.id === lastUserMessage.id,\n );\n\n if (!existingResult) {\n // Create analysis result with the same ID as the user message\n targetSession.analysisResults.push({\n id: lastUserMessage.id,\n prompt: promptText,\n isCompleted: true,\n });\n }\n }\n }\n }),\n );\n store.setState((state: AiSliceState) =>\n produce(state, (draft: AiSliceState) => {\n draft.ai.isRunningAnalysis = false;\n draft.ai.analysisPrompt = '';\n draft.ai.analysisAbortController = undefined;\n }),\n );\n } catch (err) {\n console.error('onChatFinish error:', err);\n throw err;\n }\n },\n onChatError: (error: unknown) => {\n try {\n let errMsg = getErrorMessageForDisplay(error);\n if (!errMsg || errMsg.trim().length === 0) {\n errMsg = 'Unknown error';\n }\n const currentSessionId = store.getState().ai.config.currentSessionId;\n store.setState((state: AiSliceState) =>\n produce(state, (draft: AiSliceState) => {\n if (!currentSessionId) return;\n const targetSession = draft.ai.config.sessions.find(\n (s: AnalysisSessionSchema) => s.id === currentSessionId,\n );\n if (targetSession) {\n // Find the last user message to create analysis result with correct ID\n const uiMessages = targetSession.uiMessages as UIMessage[];\n const lastUserMessage = uiMessages\n .filter((msg) => msg.role === 'user')\n .slice(-1)[0];\n\n if (lastUserMessage) {\n // Extract text content from user message\n const promptText = lastUserMessage.parts\n .filter((part: any) => part.type === 'text')\n .map((part: any) => (part as {text: string}).text)\n .join('');\n\n // Check if there's a pending analysis result\n const pendingIndex = targetSession.analysisResults.findIndex(\n (result: any) => result.id === '__pending__',\n );\n\n if (pendingIndex !== -1) {\n // Update the pending result with error\n targetSession.analysisResults[pendingIndex] = {\n id: lastUserMessage.id,\n prompt: promptText,\n errorMessage: {error: errMsg},\n isCompleted: true,\n };\n } else {\n // Check if analysis result already exists for this user message\n const existingResult = targetSession.analysisResults.find(\n (result: any) => result.id === lastUserMessage.id,\n );\n\n if (!existingResult) {\n // Create analysis result with the same ID as the user message\n targetSession.analysisResults.push({\n id: lastUserMessage.id,\n prompt: promptText,\n errorMessage: {error: errMsg},\n isCompleted: true,\n });\n } else {\n // Update existing result with error message\n existingResult.errorMessage = {error: errMsg};\n }\n }\n }\n }\n draft.ai.isRunningAnalysis = false;\n draft.ai.analysisAbortController = undefined;\n }),\n );\n } catch (err) {\n console.error('Failed to store chat error:', err);\n throw err;\n }\n },\n };\n}\n"]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Animated thinking indicator with ellipsis dots
|
|
3
|
+
*
|
|
4
|
+
* @param {className} className - The className for the component
|
|
5
|
+
* @returns {React.FC} The AiThinkingDots component
|
|
6
|
+
**/
|
|
7
|
+
export declare const AiThinkingDots: React.FC<{
|
|
8
|
+
className?: string;
|
|
9
|
+
}>;
|
|
10
|
+
//# sourceMappingURL=AiThinkingDots.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AiThinkingDots.d.ts","sourceRoot":"","sources":["../../src/components/AiThinkingDots.tsx"],"names":[],"mappings":"AAEA;;;;;IAKI;AACJ,eAAO,MAAM,cAAc,EAAE,KAAK,CAAC,EAAE,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAC,CAezD,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { cn } from '@sqlrooms/ui';
|
|
3
|
+
/**
|
|
4
|
+
* Animated thinking indicator with ellipsis dots
|
|
5
|
+
*
|
|
6
|
+
* @param {className} className - The className for the component
|
|
7
|
+
* @returns {React.FC} The AiThinkingDots component
|
|
8
|
+
**/
|
|
9
|
+
export const AiThinkingDots = ({ className }) => (_jsxs("div", { className: cn('flex items-center gap-1', className), children: [_jsx("span", { className: "dot inline-block h-1 w-1 rounded-full bg-current" }), _jsx("span", { className: "dot inline-block h-1 w-1 rounded-full bg-current" }), _jsx("span", { className: "dot inline-block h-1 w-1 rounded-full bg-current" }), _jsx("style", { children: `
|
|
10
|
+
@keyframes dot-bounce {
|
|
11
|
+
0%, 60%, 100% { opacity: 0.3; transform: translateY(0); }
|
|
12
|
+
30% { opacity: 0.8; transform: translateY(-8px); }
|
|
13
|
+
}
|
|
14
|
+
.dot { opacity: 0.3; animation: dot-bounce 2s ease-in-out infinite; }
|
|
15
|
+
.dot:nth-child(2) { animation-delay: 0.20s; }
|
|
16
|
+
.dot:nth-child(3) { animation-delay: 0.30s; }
|
|
17
|
+
` })] }));
|
|
18
|
+
//# sourceMappingURL=AiThinkingDots.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AiThinkingDots.js","sourceRoot":"","sources":["../../src/components/AiThinkingDots.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAC,EAAE,EAAC,MAAM,cAAc,CAAC;AAEhC;;;;;IAKI;AACJ,MAAM,CAAC,MAAM,cAAc,GAAmC,CAAC,EAAC,SAAS,EAAC,EAAE,EAAE,CAAC,CAC7E,eAAK,SAAS,EAAE,EAAE,CAAC,yBAAyB,EAAE,SAAS,CAAC,aACtD,eAAM,SAAS,EAAC,kDAAkD,GAAG,EACrE,eAAM,SAAS,EAAC,kDAAkD,GAAG,EACrE,eAAM,SAAS,EAAC,kDAAkD,GAAG,EACrE,0BAAQ;;;;;;;;KAQP,GAAS,IACN,CACP,CAAC","sourcesContent":["import {cn} from '@sqlrooms/ui';\n\n/**\n * Animated thinking indicator with ellipsis dots\n *\n * @param {className} className - The className for the component\n * @returns {React.FC} The AiThinkingDots component\n **/\nexport const AiThinkingDots: React.FC<{className?: string}> = ({className}) => (\n <div className={cn('flex items-center gap-1', className)}>\n <span className=\"dot inline-block h-1 w-1 rounded-full bg-current\" />\n <span className=\"dot inline-block h-1 w-1 rounded-full bg-current\" />\n <span className=\"dot inline-block h-1 w-1 rounded-full bg-current\" />\n <style>{`\n @keyframes dot-bounce {\n 0%, 60%, 100% { opacity: 0.3; transform: translateY(0); }\n 30% { opacity: 0.8; transform: translateY(-8px); }\n }\n .dot { opacity: 0.3; animation: dot-bounce 2s ease-in-out infinite; }\n .dot:nth-child(2) { animation-delay: 0.20s; }\n .dot:nth-child(3) { animation-delay: 0.30s; }\n `}</style>\n </div>\n);\n"]}
|
|
@@ -4,8 +4,7 @@ import { AnalysisResultSchema } from '@sqlrooms/ai-config';
|
|
|
4
4
|
* @property {AnalysisResultSchema} result - The result of the analysis containing prompt, tool calls, and analysis data
|
|
5
5
|
*/
|
|
6
6
|
type AnalysisResultProps = {
|
|
7
|
-
|
|
8
|
-
onDeleteAnalysisResult: (id: string) => void;
|
|
7
|
+
analysisResult: AnalysisResultSchema;
|
|
9
8
|
};
|
|
10
9
|
/**
|
|
11
10
|
* Component that displays the results of an AI analysis.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AnalysisResult.d.ts","sourceRoot":"","sources":["../../src/components/AnalysisResult.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"AnalysisResult.d.ts","sourceRoot":"","sources":["../../src/components/AnalysisResult.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAC,oBAAoB,EAAC,MAAM,qBAAqB,CAAC;AAoBzD;;;GAGG;AACH,KAAK,mBAAmB,GAAG;IACzB,cAAc,EAAE,oBAAoB,CAAC;CACtC,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,cAAc,EAAE,KAAK,CAAC,EAAE,CAAC,mBAAmB,CA+JxD,CAAC"}
|