@sqlrooms/ai-core 0.26.0-rc.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.
Files changed (99) hide show
  1. package/LICENSE.md +9 -0
  2. package/README.md +488 -0
  3. package/dist/AiSlice.d.ts +52 -0
  4. package/dist/AiSlice.d.ts.map +1 -0
  5. package/dist/AiSlice.js +367 -0
  6. package/dist/AiSlice.js.map +1 -0
  7. package/dist/analysis.d.ts +51 -0
  8. package/dist/analysis.d.ts.map +1 -0
  9. package/dist/analysis.js +43 -0
  10. package/dist/analysis.js.map +1 -0
  11. package/dist/components/AnalysisAnswer.d.ts +15 -0
  12. package/dist/components/AnalysisAnswer.d.ts.map +1 -0
  13. package/dist/components/AnalysisAnswer.js +102 -0
  14. package/dist/components/AnalysisAnswer.js.map +1 -0
  15. package/dist/components/AnalysisResult.d.ts +22 -0
  16. package/dist/components/AnalysisResult.d.ts.map +1 -0
  17. package/dist/components/AnalysisResult.js +39 -0
  18. package/dist/components/AnalysisResult.js.map +1 -0
  19. package/dist/components/AnalysisResultsContainer.d.ts +5 -0
  20. package/dist/components/AnalysisResultsContainer.d.ts.map +1 -0
  21. package/dist/components/AnalysisResultsContainer.js +26 -0
  22. package/dist/components/AnalysisResultsContainer.js.map +1 -0
  23. package/dist/components/ErrorMessage.d.ts +4 -0
  24. package/dist/components/ErrorMessage.d.ts.map +1 -0
  25. package/dist/components/ErrorMessage.js +8 -0
  26. package/dist/components/ErrorMessage.js.map +1 -0
  27. package/dist/components/MessageContainer.d.ts +10 -0
  28. package/dist/components/MessageContainer.d.ts.map +1 -0
  29. package/dist/components/MessageContainer.js +9 -0
  30. package/dist/components/MessageContainer.js.map +1 -0
  31. package/dist/components/ModelSelector.d.ts +13 -0
  32. package/dist/components/ModelSelector.d.ts.map +1 -0
  33. package/dist/components/ModelSelector.js +34 -0
  34. package/dist/components/ModelSelector.js.map +1 -0
  35. package/dist/components/QueryControls.d.ts +10 -0
  36. package/dist/components/QueryControls.d.ts.map +1 -0
  37. package/dist/components/QueryControls.js +52 -0
  38. package/dist/components/QueryControls.js.map +1 -0
  39. package/dist/components/SessionControls.d.ts +17 -0
  40. package/dist/components/SessionControls.d.ts.map +1 -0
  41. package/dist/components/SessionControls.js +20 -0
  42. package/dist/components/SessionControls.js.map +1 -0
  43. package/dist/components/session/DeleteSessionButton.d.ts +19 -0
  44. package/dist/components/session/DeleteSessionButton.d.ts.map +1 -0
  45. package/dist/components/session/DeleteSessionButton.js +54 -0
  46. package/dist/components/session/DeleteSessionButton.js.map +1 -0
  47. package/dist/components/session/DeleteSessionDialog.d.ts +27 -0
  48. package/dist/components/session/DeleteSessionDialog.d.ts.map +1 -0
  49. package/dist/components/session/DeleteSessionDialog.js +19 -0
  50. package/dist/components/session/DeleteSessionDialog.js.map +1 -0
  51. package/dist/components/session/SessionActions.d.ts +18 -0
  52. package/dist/components/session/SessionActions.d.ts.map +1 -0
  53. package/dist/components/session/SessionActions.js +19 -0
  54. package/dist/components/session/SessionActions.js.map +1 -0
  55. package/dist/components/session/SessionDropdown.d.ts +18 -0
  56. package/dist/components/session/SessionDropdown.d.ts.map +1 -0
  57. package/dist/components/session/SessionDropdown.js +21 -0
  58. package/dist/components/session/SessionDropdown.js.map +1 -0
  59. package/dist/components/session/SessionTitle.d.ts +18 -0
  60. package/dist/components/session/SessionTitle.d.ts.map +1 -0
  61. package/dist/components/session/SessionTitle.js +22 -0
  62. package/dist/components/session/SessionTitle.js.map +1 -0
  63. package/dist/components/session/SessionType.d.ts +24 -0
  64. package/dist/components/session/SessionType.d.ts.map +1 -0
  65. package/dist/components/session/SessionType.js +2 -0
  66. package/dist/components/session/SessionType.js.map +1 -0
  67. package/dist/components/session/index.d.ts +7 -0
  68. package/dist/components/session/index.d.ts.map +1 -0
  69. package/dist/components/session/index.js +7 -0
  70. package/dist/components/session/index.js.map +1 -0
  71. package/dist/components/tools/ToolErrorMessage.d.ts +39 -0
  72. package/dist/components/tools/ToolErrorMessage.d.ts.map +1 -0
  73. package/dist/components/tools/ToolErrorMessage.js +20 -0
  74. package/dist/components/tools/ToolErrorMessage.js.map +1 -0
  75. package/dist/components/tools/ToolResult.d.ts +11 -0
  76. package/dist/components/tools/ToolResult.d.ts.map +1 -0
  77. package/dist/components/tools/ToolResult.js +29 -0
  78. package/dist/components/tools/ToolResult.js.map +1 -0
  79. package/dist/components/tools/ToolResultErrorBoundary.d.ts +19 -0
  80. package/dist/components/tools/ToolResultErrorBoundary.d.ts.map +1 -0
  81. package/dist/components/tools/ToolResultErrorBoundary.js +24 -0
  82. package/dist/components/tools/ToolResultErrorBoundary.js.map +1 -0
  83. package/dist/hasAiSettingsConfig.d.ts +13 -0
  84. package/dist/hasAiSettingsConfig.d.ts.map +1 -0
  85. package/dist/hasAiSettingsConfig.js +16 -0
  86. package/dist/hasAiSettingsConfig.js.map +1 -0
  87. package/dist/hooks/useScrollToBottom.d.ts +82 -0
  88. package/dist/hooks/useScrollToBottom.d.ts.map +1 -0
  89. package/dist/hooks/useScrollToBottom.js +142 -0
  90. package/dist/hooks/useScrollToBottom.js.map +1 -0
  91. package/dist/index.d.ts +21 -0
  92. package/dist/index.d.ts.map +1 -0
  93. package/dist/index.js +18 -0
  94. package/dist/index.js.map +1 -0
  95. package/dist/utils.d.ts +15 -0
  96. package/dist/utils.d.ts.map +1 -0
  97. package/dist/utils.js +31 -0
  98. package/dist/utils.js.map +1 -0
  99. package/package.json +51 -0
@@ -0,0 +1,367 @@
1
+ import { createId } from '@paralleldrive/cuid2';
2
+ import { createDefaultAiConfig, } from '@sqlrooms/ai-config';
3
+ import { createBaseSlice, useBaseRoomStore, } from '@sqlrooms/room-store';
4
+ import { produce } from 'immer';
5
+ import { runAnalysis } from './analysis';
6
+ import { hasAiSettingsConfig } from './hasAiSettingsConfig';
7
+ export function createAiSlice(params) {
8
+ const { defaultProvider = 'openai', defaultModel = 'gpt-4.1', initialAnalysisPrompt = '', tools, getApiKey, getBaseUrl, maxSteps, getInstructions, } = params;
9
+ return createBaseSlice((set, get, store) => {
10
+ return {
11
+ ai: {
12
+ config: createDefaultAiConfig(params.config),
13
+ analysisPrompt: initialAnalysisPrompt,
14
+ isRunningAnalysis: false,
15
+ tools,
16
+ setAnalysisPrompt: (prompt) => {
17
+ set((state) => produce(state, (draft) => {
18
+ draft.ai.analysisPrompt = prompt;
19
+ }));
20
+ },
21
+ /**
22
+ * Set the AI model for the current session
23
+ * @param model - The model to set
24
+ */
25
+ setAiModel: (modelProvider, model) => {
26
+ set((state) => produce(state, (draft) => {
27
+ const currentSession = getCurrentSessionFromState(draft);
28
+ if (currentSession) {
29
+ currentSession.modelProvider = modelProvider;
30
+ currentSession.model = model;
31
+ }
32
+ }));
33
+ },
34
+ /**
35
+ * Get the current active session
36
+ */
37
+ getCurrentSession: () => {
38
+ const state = get();
39
+ const { currentSessionId, sessions } = state.ai.config;
40
+ return sessions.find((session) => session.id === currentSessionId);
41
+ },
42
+ /**
43
+ * Create a new session with the given name and model settings
44
+ */
45
+ createSession: (name, modelProvider, model) => {
46
+ const currentSession = get().ai.getCurrentSession();
47
+ const newSessionId = createId();
48
+ // Generate a default name if none is provided
49
+ let sessionName = name;
50
+ if (!sessionName) {
51
+ // Generate a human-readable date and time for the session name
52
+ const now = new Date();
53
+ const formattedDate = now.toLocaleDateString('en-US', {
54
+ month: 'short',
55
+ day: 'numeric',
56
+ year: 'numeric',
57
+ });
58
+ const formattedTime = now.toLocaleTimeString('en-US', {
59
+ hour: 'numeric',
60
+ minute: 'numeric',
61
+ hour12: true,
62
+ });
63
+ sessionName = `Session ${formattedDate} at ${formattedTime}`;
64
+ }
65
+ set((state) => produce(state, (draft) => {
66
+ // Add to AI sessions
67
+ draft.ai.config.sessions.unshift({
68
+ id: newSessionId,
69
+ name: sessionName,
70
+ modelProvider: modelProvider || currentSession?.modelProvider || 'openai',
71
+ model: model || currentSession?.model || 'gpt-4.1',
72
+ analysisResults: [],
73
+ createdAt: new Date(),
74
+ });
75
+ draft.ai.config.currentSessionId = newSessionId;
76
+ }));
77
+ },
78
+ /**
79
+ * Switch to a different session
80
+ */
81
+ switchSession: (sessionId) => {
82
+ set((state) => produce(state, (draft) => {
83
+ draft.ai.config.currentSessionId = sessionId;
84
+ }));
85
+ },
86
+ /**
87
+ * Rename an existing session
88
+ */
89
+ renameSession: (sessionId, name) => {
90
+ set((state) => produce(state, (draft) => {
91
+ const session = draft.ai.config.sessions.find((s) => s.id === sessionId);
92
+ if (session) {
93
+ session.name = name;
94
+ }
95
+ }));
96
+ },
97
+ /**
98
+ * Delete a session
99
+ */
100
+ deleteSession: (sessionId) => {
101
+ set((state) => produce(state, (draft) => {
102
+ const sessionIndex = draft.ai.config.sessions.findIndex((s) => s.id === sessionId);
103
+ if (sessionIndex !== -1) {
104
+ // Don't delete the last session
105
+ if (draft.ai.config.sessions.length > 1) {
106
+ draft.ai.config.sessions.splice(sessionIndex, 1);
107
+ // If we deleted the current session, switch to another one
108
+ if (draft.ai.config.currentSessionId === sessionId) {
109
+ // Make sure there's at least one session before accessing its id
110
+ if (draft.ai.config.sessions.length > 0) {
111
+ const firstSession = draft.ai.config.sessions[0];
112
+ if (firstSession) {
113
+ draft.ai.config.currentSessionId = firstSession.id;
114
+ }
115
+ }
116
+ }
117
+ }
118
+ }
119
+ }));
120
+ },
121
+ /**
122
+ * Start the analysis
123
+ * TODO: how to pass the history analysisResults?
124
+ */
125
+ startAnalysis: async () => {
126
+ const resultId = createId();
127
+ const abortController = new AbortController();
128
+ const currentSession = get().ai.getCurrentSession();
129
+ if (!currentSession) {
130
+ console.error('No current session found');
131
+ return;
132
+ }
133
+ set((state) => produce(state, (draft) => {
134
+ draft.ai.analysisAbortController = abortController;
135
+ draft.ai.isRunningAnalysis = true;
136
+ const session = draft.ai.config.sessions.find((s) => s.id === draft.ai.config.currentSessionId);
137
+ if (session) {
138
+ session.analysisResults.push({
139
+ id: resultId,
140
+ prompt: get().ai.analysisPrompt,
141
+ streamMessage: {
142
+ parts: [
143
+ {
144
+ type: 'text',
145
+ text: '',
146
+ },
147
+ ],
148
+ },
149
+ isCompleted: false,
150
+ });
151
+ }
152
+ }));
153
+ try {
154
+ await runAnalysis({
155
+ modelProvider: currentSession.modelProvider || defaultProvider,
156
+ model: currentSession.model || defaultModel,
157
+ apiKey: get().ai.getApiKeyFromSettings(),
158
+ baseUrl: get().ai.getBaseUrlFromSettings(),
159
+ prompt: get().ai.analysisPrompt,
160
+ abortController,
161
+ tools: get().ai.tools,
162
+ maxSteps: get().ai.getMaxStepsFromSettings(),
163
+ getInstructions: get().ai.getFullInstructions,
164
+ historyAnalysis: currentSession.analysisResults,
165
+ onStreamResult: (isCompleted, streamMessage) => {
166
+ set(makeResultsAppender({
167
+ resultId,
168
+ streamMessage,
169
+ isCompleted,
170
+ }));
171
+ },
172
+ });
173
+ }
174
+ catch (err) {
175
+ set(makeResultsAppender({
176
+ resultId,
177
+ isCompleted: true,
178
+ errorMessage: {
179
+ error: err instanceof Error ? err.message : String(err),
180
+ },
181
+ }));
182
+ }
183
+ finally {
184
+ set((state) => produce(state, (draft) => {
185
+ draft.ai.isRunningAnalysis = false;
186
+ draft.ai.analysisPrompt = '';
187
+ }));
188
+ }
189
+ },
190
+ cancelAnalysis: () => {
191
+ set((state) => produce(state, (draft) => {
192
+ draft.ai.isRunningAnalysis = false;
193
+ }));
194
+ get().ai.analysisAbortController?.abort('Analysis cancelled');
195
+ },
196
+ /**
197
+ * Delete an analysis result from a session
198
+ */
199
+ deleteAnalysisResult: (sessionId, resultId) => {
200
+ set((state) => produce(state, (draft) => {
201
+ const session = draft.ai.config.sessions.find((s) => s.id === sessionId);
202
+ if (session) {
203
+ session.analysisResults = session.analysisResults.filter((r) => r.id !== resultId);
204
+ }
205
+ }));
206
+ },
207
+ findToolComponent: (toolName) => {
208
+ return Object.entries(get().ai.tools).find(([name]) => name === toolName)?.[1]?.component;
209
+ },
210
+ getBaseUrlFromSettings: () => {
211
+ // First try the getBaseUrl function if provided
212
+ const baseUrlFromFunction = getBaseUrl?.();
213
+ if (baseUrlFromFunction) {
214
+ return baseUrlFromFunction;
215
+ }
216
+ // Fall back to settings
217
+ const store = get();
218
+ if (hasAiSettingsConfig(store)) {
219
+ const currentSession = getCurrentSessionFromState(store);
220
+ if (currentSession) {
221
+ if (currentSession.modelProvider === 'custom') {
222
+ const customModel = store.aiSettings.config.customModels.find((m) => m.modelName === currentSession.model);
223
+ return customModel?.baseUrl;
224
+ }
225
+ const provider = store.aiSettings.config.providers[currentSession.modelProvider];
226
+ return provider?.baseUrl;
227
+ }
228
+ }
229
+ return undefined;
230
+ },
231
+ getApiKeyFromSettings: () => {
232
+ const store = get();
233
+ const currentSession = getCurrentSessionFromState(store);
234
+ if (currentSession) {
235
+ // First try the getApiKey function if provided
236
+ const apiKeyFromFunction = getApiKey?.(currentSession.modelProvider || defaultProvider);
237
+ if (apiKeyFromFunction) {
238
+ return apiKeyFromFunction;
239
+ }
240
+ // Fall back to settings
241
+ if (hasAiSettingsConfig(store)) {
242
+ if (currentSession.modelProvider === 'custom') {
243
+ const customModel = store.aiSettings.config.customModels.find((m) => m.modelName === currentSession.model);
244
+ return customModel?.apiKey || '';
245
+ }
246
+ else {
247
+ const provider = store.aiSettings.config.providers?.[currentSession.modelProvider];
248
+ return provider?.apiKey || '';
249
+ }
250
+ }
251
+ }
252
+ return '';
253
+ },
254
+ getMaxStepsFromSettings: () => {
255
+ const store = get();
256
+ // First try the maxSteps parameter if provided
257
+ if (maxSteps && Number.isFinite(maxSteps) && maxSteps > 0) {
258
+ return maxSteps;
259
+ }
260
+ // Fall back to settings
261
+ if (hasAiSettingsConfig(store)) {
262
+ const settingsMaxSteps = store.aiSettings.config.modelParameters.maxSteps;
263
+ if (Number.isFinite(settingsMaxSteps) && settingsMaxSteps > 0) {
264
+ return settingsMaxSteps;
265
+ }
266
+ }
267
+ return 5;
268
+ },
269
+ getFullInstructions: () => {
270
+ const store = get();
271
+ let instructions = getInstructions();
272
+ // Fall back to settings
273
+ if (hasAiSettingsConfig(store)) {
274
+ // get additional instructions from settings
275
+ const { additionalInstruction } = store.aiSettings.config.modelParameters;
276
+ if (additionalInstruction) {
277
+ instructions = `${instructions}\n\nAdditional Instructions:\n\n${additionalInstruction}`;
278
+ }
279
+ }
280
+ return instructions;
281
+ },
282
+ },
283
+ };
284
+ });
285
+ }
286
+ /**
287
+ * Helper function to get the current session from state
288
+ */
289
+ function getCurrentSessionFromState(state) {
290
+ const { currentSessionId, sessions } = state.ai.config;
291
+ return sessions.find((session) => session.id === currentSessionId);
292
+ }
293
+ function findResultById(analysisResults, id) {
294
+ return analysisResults.find((result) => result.id === id);
295
+ }
296
+ /**
297
+ * Appends the tool results, tool calls, and analysis to the state
298
+ *
299
+ * @param resultId - The id of the result to append to
300
+ * @param message - The message to append to the state. The structure of the message is defined as:
301
+ * - reasoning: string The reasoning of the assistant
302
+ * - toolCallMessages: ToolCallMessage[] The tool call messages
303
+ * - text: string The final text message
304
+ * @param isCompleted - Whether the analysis is completed
305
+ * @returns The new state
306
+ */
307
+ function makeResultsAppender({ resultId, streamMessage, errorMessage, isCompleted, }) {
308
+ return (state) => produce(state, (draft) => {
309
+ const currentSession = getCurrentSessionFromState(draft);
310
+ if (!currentSession) {
311
+ console.error('No current session found');
312
+ return;
313
+ }
314
+ const result = findResultById(currentSession.analysisResults, resultId);
315
+ if (result) {
316
+ if (streamMessage && streamMessage.parts) {
317
+ // copy all properties from streamMessage
318
+ const newStreamMessage = {
319
+ parts: streamMessage.parts.map((part) => {
320
+ if (part.type === 'text') {
321
+ return {
322
+ type: 'text',
323
+ text: part.text,
324
+ additionalData: part.additionalData,
325
+ isCompleted: part.isCompleted,
326
+ };
327
+ }
328
+ else if (part.type === 'tool-invocation') {
329
+ return {
330
+ type: 'tool-invocation',
331
+ toolInvocation: {
332
+ toolCallId: part.toolInvocation.toolCallId,
333
+ toolName: part.toolInvocation.toolName,
334
+ args: part.toolInvocation.args,
335
+ state: part.toolInvocation.state,
336
+ result: part.toolInvocation.state === 'result'
337
+ ? part.toolInvocation.result
338
+ : undefined,
339
+ },
340
+ additionalData: part.additionalData,
341
+ isCompleted: part.isCompleted,
342
+ };
343
+ }
344
+ else {
345
+ // TODO: handle other part types later
346
+ return part;
347
+ }
348
+ }),
349
+ };
350
+ result.streamMessage = newStreamMessage;
351
+ }
352
+ if (errorMessage) {
353
+ result.errorMessage = errorMessage;
354
+ }
355
+ if (isCompleted) {
356
+ result.isCompleted = isCompleted;
357
+ }
358
+ }
359
+ else {
360
+ console.error('Result not found', resultId);
361
+ }
362
+ });
363
+ }
364
+ export function useStoreWithAi(selector) {
365
+ return useBaseRoomStore((state) => selector(state));
366
+ }
367
+ //# sourceMappingURL=AiSlice.js.map
@@ -0,0 +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"]}
@@ -0,0 +1,51 @@
1
+ import { StreamMessage } from '@openassistant/core';
2
+ import { AnalysisResultSchema } from '@sqlrooms/ai-config';
3
+ import { AiSliceTool } from './AiSlice';
4
+ /**
5
+ * Configuration options for running an AI analysis session
6
+ */
7
+ type AnalysisParameters = {
8
+ /** Assistant instance identifier (default: 'sqlrooms-ai') */
9
+ name?: string;
10
+ /** AI model provider (e.g., 'openai', 'anthropic') */
11
+ modelProvider: string;
12
+ /** Model identifier (e.g., 'gpt-4', 'claude-3') */
13
+ model: string;
14
+ /** Authentication key for the model provider's API */
15
+ apiKey: string;
16
+ /** Analysis prompt or question to be processed */
17
+ prompt: string;
18
+ /** Optional controller for canceling the analysis operation */
19
+ abortController?: AbortController;
20
+ /** Maximum number of analysis steps allowed (default: 100) */
21
+ maxSteps?: number;
22
+ /** The history of analysis results (e.g. saved in localStorage) */
23
+ historyAnalysis?: AnalysisResultSchema[];
24
+ /** Tools to use in the analysis */
25
+ tools?: Record<string, AiSliceTool>;
26
+ /** Base URL for Ollama provider (required when modelProvider is 'ollama') */
27
+ baseUrl?: string;
28
+ /**
29
+ * Function to get custom instructions for the AI assistant
30
+ * @returns The instructions string to use
31
+ */
32
+ getInstructions: () => string;
33
+ /**
34
+ * Callback for handling streaming results
35
+ * @param isCompleted - Indicates if this is the final message in the stream
36
+ * @param streamMessage - Current message content being streamed
37
+ */
38
+ onStreamResult: (isCompleted: boolean, streamMessage?: StreamMessage) => void;
39
+ };
40
+ /**
41
+ * Executes an AI analysis session on the room data
42
+ *
43
+ * @param config - Analysis configuration options. See {@link AnalysisParameters} for more details.
44
+ * @returns Object containing tool calls executed and the final analysis result
45
+ */
46
+ export declare function runAnalysis({ name, modelProvider, model, apiKey, prompt, abortController, historyAnalysis, onStreamResult, maxSteps, tools, getInstructions, baseUrl, }: AnalysisParameters): Promise<{
47
+ streamMessage: StreamMessage;
48
+ messages: import("ai").CoreMessage[];
49
+ }>;
50
+ export {};
51
+ //# sourceMappingURL=analysis.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analysis.d.ts","sourceRoot":"","sources":["../src/analysis.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,aAAa,EACd,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAC,oBAAoB,EAAC,MAAM,qBAAqB,CAAC;AAEzD,OAAO,EAAC,WAAW,EAAC,MAAM,WAAW,CAAC;AAEtC;;GAEG;AACH,KAAK,kBAAkB,GAAG;IACxB,6DAA6D;IAC7D,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd,sDAAsD;IACtD,aAAa,EAAE,MAAM,CAAC;IAEtB,mDAAmD;IACnD,KAAK,EAAE,MAAM,CAAC;IAEd,sDAAsD;IACtD,MAAM,EAAE,MAAM,CAAC;IAEf,kDAAkD;IAClD,MAAM,EAAE,MAAM,CAAC;IAEf,+DAA+D;IAC/D,eAAe,CAAC,EAAE,eAAe,CAAC;IAElC,8DAA8D;IAC9D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB,mEAAmE;IACnE,eAAe,CAAC,EAAE,oBAAoB,EAAE,CAAC;IAEzC,mCAAmC;IACnC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IAEpC,6EAA6E;IAC7E,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;;OAGG;IACH,eAAe,EAAE,MAAM,MAAM,CAAC;IAE9B;;;;OAIG;IACH,cAAc,EAAE,CAAC,WAAW,EAAE,OAAO,EAAE,aAAa,CAAC,EAAE,aAAa,KAAK,IAAI,CAAC;CAC/E,CAAC;AAEF;;;;;GAKG;AACH,wBAAsB,WAAW,CAAC,EAChC,IAAoB,EACpB,aAAa,EACb,KAAK,EACL,MAAM,EACN,MAAM,EACN,eAAe,EACf,eAAe,EACf,cAAc,EACd,QAAY,EACZ,KAAU,EACV,eAAe,EACf,OAAO,GACR,EAAE,kBAAkB;;;GA0CpB"}
@@ -0,0 +1,43 @@
1
+ import { createAssistant, rebuildMessages, } from '@openassistant/core';
2
+ import { convertToCoreMessages } from 'ai';
3
+ /**
4
+ * Executes an AI analysis session on the room data
5
+ *
6
+ * @param config - Analysis configuration options. See {@link AnalysisParameters} for more details.
7
+ * @returns Object containing tool calls executed and the final analysis result
8
+ */
9
+ export async function runAnalysis({ name = 'sqlrooms-ai', modelProvider, model, apiKey, prompt, abortController, historyAnalysis, onStreamResult, maxSteps = 5, tools = {}, getInstructions, baseUrl, }) {
10
+ // get the singleton assistant instance
11
+ const assistant = await createAssistant({
12
+ name,
13
+ modelProvider,
14
+ model,
15
+ apiKey,
16
+ version: 'v1',
17
+ instructions: getInstructions(),
18
+ tools: tools,
19
+ temperature: 0,
20
+ toolChoice: 'auto', // this will enable streaming
21
+ maxSteps,
22
+ ...(abortController ? { abortController } : {}),
23
+ baseUrl, // ollama base url or LLM proxy server url
24
+ });
25
+ // restore ai messages from historyAnalysis?
26
+ if (historyAnalysis) {
27
+ const historyMessages = historyAnalysis.map((analysis) => ({
28
+ prompt: analysis.prompt,
29
+ response: analysis.streamMessage,
30
+ }));
31
+ const initialMessages = rebuildMessages(historyMessages);
32
+ assistant.setMessages(convertToCoreMessages(initialMessages));
33
+ }
34
+ // process the prompt
35
+ const newMessages = await assistant.processTextMessage({
36
+ textMessage: prompt,
37
+ streamMessageCallback: ({ isCompleted, message, }) => {
38
+ onStreamResult(isCompleted ?? false, message);
39
+ },
40
+ });
41
+ return newMessages;
42
+ }
43
+ //# sourceMappingURL=analysis.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analysis.js","sourceRoot":"","sources":["../src/analysis.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,eAAe,GAEhB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAC,qBAAqB,EAAC,MAAM,IAAI,CAAC;AAmDzC;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,EAChC,IAAI,GAAG,aAAa,EACpB,aAAa,EACb,KAAK,EACL,MAAM,EACN,MAAM,EACN,eAAe,EACf,eAAe,EACf,cAAc,EACd,QAAQ,GAAG,CAAC,EACZ,KAAK,GAAG,EAAE,EACV,eAAe,EACf,OAAO,GACY;IACnB,uCAAuC;IACvC,MAAM,SAAS,GAAG,MAAM,eAAe,CAAC;QACtC,IAAI;QACJ,aAAa;QACb,KAAK;QACL,MAAM;QACN,OAAO,EAAE,IAAI;QACb,YAAY,EAAE,eAAe,EAAE;QAC/B,KAAK,EAAE,KAAK;QACZ,WAAW,EAAE,CAAC;QACd,UAAU,EAAE,MAAM,EAAE,6BAA6B;QACjD,QAAQ;QACR,GAAG,CAAC,eAAe,CAAC,CAAC,CAAC,EAAC,eAAe,EAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAC7C,OAAO,EAAE,0CAA0C;KACpD,CAAC,CAAC;IAEH,4CAA4C;IAC5C,IAAI,eAAe,EAAE,CAAC;QACpB,MAAM,eAAe,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;YACzD,MAAM,EAAE,QAAQ,CAAC,MAAM;YACvB,QAAQ,EAAE,QAAQ,CAAC,aAA8B;SAClD,CAAC,CAAC,CAAC;QACJ,MAAM,eAAe,GAAG,eAAe,CAAC,eAAe,CAAC,CAAC;QACzD,SAAS,CAAC,WAAW,CAAC,qBAAqB,CAAC,eAAe,CAAC,CAAC,CAAC;IAChE,CAAC;IAED,qBAAqB;IACrB,MAAM,WAAW,GAAG,MAAM,SAAS,CAAC,kBAAkB,CAAC;QACrD,WAAW,EAAE,MAAM;QACnB,qBAAqB,EAAE,CAAC,EACtB,WAAW,EACX,OAAO,GAIR,EAAE,EAAE;YACH,cAAc,CAAC,WAAW,IAAI,KAAK,EAAE,OAAO,CAAC,CAAC;QAChD,CAAC;KACF,CAAC,CAAC;IAEH,OAAO,WAAW,CAAC;AACrB,CAAC","sourcesContent":["import {\n createAssistant,\n rebuildMessages,\n StreamMessage,\n} from '@openassistant/core';\nimport {AnalysisResultSchema} from '@sqlrooms/ai-config';\nimport {convertToCoreMessages} from 'ai';\nimport {AiSliceTool} from './AiSlice';\n\n/**\n * Configuration options for running an AI analysis session\n */\ntype AnalysisParameters = {\n /** Assistant instance identifier (default: 'sqlrooms-ai') */\n name?: string;\n\n /** AI model provider (e.g., 'openai', 'anthropic') */\n modelProvider: string;\n\n /** Model identifier (e.g., 'gpt-4', 'claude-3') */\n model: string;\n\n /** Authentication key for the model provider's API */\n apiKey: string;\n\n /** Analysis prompt or question to be processed */\n prompt: string;\n\n /** Optional controller for canceling the analysis operation */\n abortController?: AbortController;\n\n /** Maximum number of analysis steps allowed (default: 100) */\n maxSteps?: number;\n\n /** The history of analysis results (e.g. saved in localStorage) */\n historyAnalysis?: AnalysisResultSchema[];\n\n /** Tools to use in the analysis */\n tools?: Record<string, AiSliceTool>;\n\n /** Base URL for Ollama provider (required when modelProvider is 'ollama') */\n baseUrl?: string;\n\n /**\n * Function to get custom instructions for the AI assistant\n * @returns The instructions string to use\n */\n getInstructions: () => string;\n\n /**\n * Callback for handling streaming results\n * @param isCompleted - Indicates if this is the final message in the stream\n * @param streamMessage - Current message content being streamed\n */\n onStreamResult: (isCompleted: boolean, streamMessage?: StreamMessage) => void;\n};\n\n/**\n * Executes an AI analysis session on the room data\n *\n * @param config - Analysis configuration options. See {@link AnalysisParameters} for more details.\n * @returns Object containing tool calls executed and the final analysis result\n */\nexport async function runAnalysis({\n name = 'sqlrooms-ai',\n modelProvider,\n model,\n apiKey,\n prompt,\n abortController,\n historyAnalysis,\n onStreamResult,\n maxSteps = 5,\n tools = {},\n getInstructions,\n baseUrl,\n}: AnalysisParameters) {\n // get the singleton assistant instance\n const assistant = await createAssistant({\n name,\n modelProvider,\n model,\n apiKey,\n version: 'v1',\n instructions: getInstructions(),\n tools: tools,\n temperature: 0,\n toolChoice: 'auto', // this will enable streaming\n maxSteps,\n ...(abortController ? {abortController} : {}),\n baseUrl, // ollama base url or LLM proxy server url\n });\n\n // restore ai messages from historyAnalysis?\n if (historyAnalysis) {\n const historyMessages = historyAnalysis.map((analysis) => ({\n prompt: analysis.prompt,\n response: analysis.streamMessage as StreamMessage,\n }));\n const initialMessages = rebuildMessages(historyMessages);\n assistant.setMessages(convertToCoreMessages(initialMessages));\n }\n\n // process the prompt\n const newMessages = await assistant.processTextMessage({\n textMessage: prompt,\n streamMessageCallback: ({\n isCompleted,\n message,\n }: {\n isCompleted?: boolean;\n message?: StreamMessage;\n }) => {\n onStreamResult(isCompleted ?? false, message);\n },\n });\n\n return newMessages;\n}\n"]}
@@ -0,0 +1,15 @@
1
+ import React from 'react';
2
+ type AnalysisAnswerProps = {
3
+ content: string;
4
+ isAnswer: boolean;
5
+ };
6
+ /**
7
+ * Renders an analysis answer with markdown content of the final streaming response.
8
+ * Supports streaming think content that may arrive in chunks (e.g., "<think>Hello" before "</think>").
9
+ *
10
+ * @param {AnalysisAnswerProps} props - The component props. See {@link AnalysisAnswerProps} for more details.
11
+ * @returns {JSX.Element} The rendered answer tool call
12
+ */
13
+ export declare const AnalysisAnswer: React.NamedExoticComponent<AnalysisAnswerProps>;
14
+ export {};
15
+ //# sourceMappingURL=AnalysisAnswer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AnalysisAnswer.d.ts","sourceRoot":"","sources":["../../src/components/AnalysisAnswer.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAuC,MAAM,OAAO,CAAC;AAS5D,KAAK,mBAAmB,GAAG;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,OAAO,CAAC;CACnB,CAAC;AA6GF;;;;;;GAMG;AACH,eAAO,MAAM,cAAc,iDA0EzB,CAAC"}