@sqlrooms/ai 0.7.0 → 0.8.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 (129) hide show
  1. package/README.md +377 -25
  2. package/dist/AiSlice.d.ts +489 -307
  3. package/dist/AiSlice.d.ts.map +1 -1
  4. package/dist/AiSlice.js +267 -177
  5. package/dist/AiSlice.js.map +1 -1
  6. package/dist/analysis.d.ts +25 -19
  7. package/dist/analysis.d.ts.map +1 -1
  8. package/dist/analysis.js +86 -145
  9. package/dist/analysis.js.map +1 -1
  10. package/dist/components/AnalysisAnswer.d.ts +14 -0
  11. package/dist/components/AnalysisAnswer.d.ts.map +1 -0
  12. package/dist/components/AnalysisAnswer.js +14 -0
  13. package/dist/components/AnalysisAnswer.js.map +1 -0
  14. package/dist/{AnalysisResult.d.ts → components/AnalysisResult.d.ts} +2 -1
  15. package/dist/components/AnalysisResult.d.ts.map +1 -0
  16. package/dist/components/AnalysisResult.js +46 -0
  17. package/dist/components/AnalysisResult.js.map +1 -0
  18. package/dist/components/AnalysisResultsContainer.d.ts +5 -0
  19. package/dist/components/AnalysisResultsContainer.d.ts.map +1 -0
  20. package/dist/components/AnalysisResultsContainer.js +27 -0
  21. package/dist/components/AnalysisResultsContainer.js.map +1 -0
  22. package/dist/components/ErrorMessage.d.ts +4 -0
  23. package/dist/components/ErrorMessage.d.ts.map +1 -0
  24. package/dist/components/ErrorMessage.js +7 -0
  25. package/dist/components/ErrorMessage.js.map +1 -0
  26. package/dist/components/MessageContainer.d.ts +10 -0
  27. package/dist/components/MessageContainer.d.ts.map +1 -0
  28. package/dist/components/MessageContainer.js +17 -0
  29. package/dist/components/MessageContainer.js.map +1 -0
  30. package/dist/components/ModelSelector.d.ts +13 -0
  31. package/dist/components/ModelSelector.d.ts.map +1 -0
  32. package/dist/components/ModelSelector.js +29 -0
  33. package/dist/components/ModelSelector.js.map +1 -0
  34. package/dist/components/QueryControls.d.ts +8 -0
  35. package/dist/components/QueryControls.d.ts.map +1 -0
  36. package/dist/components/QueryControls.js +45 -0
  37. package/dist/components/QueryControls.js.map +1 -0
  38. package/dist/components/SessionControls.d.ts +17 -0
  39. package/dist/components/SessionControls.d.ts.map +1 -0
  40. package/dist/components/SessionControls.js +20 -0
  41. package/dist/components/SessionControls.js.map +1 -0
  42. package/dist/components/session/DeleteSessionButton.d.ts +19 -0
  43. package/dist/components/session/DeleteSessionButton.d.ts.map +1 -0
  44. package/dist/components/session/DeleteSessionButton.js +54 -0
  45. package/dist/components/session/DeleteSessionButton.js.map +1 -0
  46. package/dist/components/session/DeleteSessionDialog.d.ts +27 -0
  47. package/dist/components/session/DeleteSessionDialog.d.ts.map +1 -0
  48. package/dist/components/session/DeleteSessionDialog.js +19 -0
  49. package/dist/components/session/DeleteSessionDialog.js.map +1 -0
  50. package/dist/components/session/SessionActions.d.ts +18 -0
  51. package/dist/components/session/SessionActions.d.ts.map +1 -0
  52. package/dist/components/session/SessionActions.js +19 -0
  53. package/dist/components/session/SessionActions.js.map +1 -0
  54. package/dist/components/session/SessionDropdown.d.ts +18 -0
  55. package/dist/components/session/SessionDropdown.d.ts.map +1 -0
  56. package/dist/components/session/SessionDropdown.js +21 -0
  57. package/dist/components/session/SessionDropdown.js.map +1 -0
  58. package/dist/components/session/SessionTitle.d.ts +18 -0
  59. package/dist/components/session/SessionTitle.d.ts.map +1 -0
  60. package/dist/components/session/SessionTitle.js +22 -0
  61. package/dist/components/session/SessionTitle.js.map +1 -0
  62. package/dist/components/session/SessionType.d.ts +24 -0
  63. package/dist/components/session/SessionType.d.ts.map +1 -0
  64. package/dist/components/session/SessionType.js +2 -0
  65. package/dist/components/session/SessionType.js.map +1 -0
  66. package/dist/components/session/index.d.ts +7 -0
  67. package/dist/components/session/index.d.ts.map +1 -0
  68. package/dist/components/session/index.js +7 -0
  69. package/dist/components/session/index.js.map +1 -0
  70. package/dist/components/tools/QueryToolResult.d.ts +7 -0
  71. package/dist/components/tools/QueryToolResult.d.ts.map +1 -0
  72. package/dist/components/tools/QueryToolResult.js +9 -0
  73. package/dist/components/tools/QueryToolResult.js.map +1 -0
  74. package/dist/components/tools/ToolChart.d.ts +13 -0
  75. package/dist/components/tools/ToolChart.d.ts.map +1 -0
  76. package/dist/components/tools/ToolChart.js +14 -0
  77. package/dist/components/tools/ToolChart.js.map +1 -0
  78. package/dist/components/tools/ToolQuery.d.ts +7 -0
  79. package/dist/components/tools/ToolQuery.d.ts.map +1 -0
  80. package/dist/components/tools/ToolQuery.js +9 -0
  81. package/dist/components/tools/ToolQuery.js.map +1 -0
  82. package/dist/components/tools/ToolResult.d.ts +9 -0
  83. package/dist/components/tools/ToolResult.d.ts.map +1 -0
  84. package/dist/components/tools/ToolResult.js +32 -0
  85. package/dist/components/tools/ToolResult.js.map +1 -0
  86. package/dist/components/tools/ToolResultErrorBoundary.d.ts +19 -0
  87. package/dist/components/tools/ToolResultErrorBoundary.d.ts.map +1 -0
  88. package/dist/components/tools/ToolResultErrorBoundary.js +23 -0
  89. package/dist/components/tools/ToolResultErrorBoundary.js.map +1 -0
  90. package/dist/hooks/useScrollToBottom.d.ts +82 -0
  91. package/dist/hooks/useScrollToBottom.d.ts.map +1 -0
  92. package/dist/hooks/useScrollToBottom.js +140 -0
  93. package/dist/hooks/useScrollToBottom.js.map +1 -0
  94. package/dist/index.d.ts +16 -5
  95. package/dist/index.d.ts.map +1 -1
  96. package/dist/index.js +15 -5
  97. package/dist/index.js.map +1 -1
  98. package/dist/schemas.d.ts +592 -201
  99. package/dist/schemas.d.ts.map +1 -1
  100. package/dist/schemas.js +36 -11
  101. package/dist/schemas.js.map +1 -1
  102. package/package.json +11 -10
  103. package/dist/AnalysisResult.d.ts.map +0 -1
  104. package/dist/AnalysisResult.js +0 -56
  105. package/dist/AnalysisResult.js.map +0 -1
  106. package/dist/AnalysisResultsContainer.d.ts +0 -2
  107. package/dist/AnalysisResultsContainer.d.ts.map +0 -1
  108. package/dist/AnalysisResultsContainer.js +0 -15
  109. package/dist/AnalysisResultsContainer.js.map +0 -1
  110. package/dist/QueryControls.d.ts +0 -6
  111. package/dist/QueryControls.d.ts.map +0 -1
  112. package/dist/QueryControls.js +0 -28
  113. package/dist/QueryControls.js.map +0 -1
  114. package/dist/QueryResult.d.ts +0 -9
  115. package/dist/QueryResult.d.ts.map +0 -1
  116. package/dist/QueryResult.js +0 -46
  117. package/dist/QueryResult.js.map +0 -1
  118. package/dist/ToolCall.d.ts +0 -66
  119. package/dist/ToolCall.d.ts.map +0 -1
  120. package/dist/ToolCall.js +0 -59
  121. package/dist/ToolCall.js.map +0 -1
  122. package/dist/ToolResult.d.ts +0 -10
  123. package/dist/ToolResult.d.ts.map +0 -1
  124. package/dist/ToolResult.js +0 -39
  125. package/dist/ToolResult.js.map +0 -1
  126. package/dist/hooks/use-scroll-to-bottom.d.ts +0 -7
  127. package/dist/hooks/use-scroll-to-bottom.d.ts.map +0 -1
  128. package/dist/hooks/use-scroll-to-bottom.js +0 -51
  129. package/dist/hooks/use-scroll-to-bottom.js.map +0 -1
package/README.md CHANGED
@@ -22,23 +22,108 @@ yarn add @sqlrooms/ai
22
22
  ### Setting Up AI Integration
23
23
 
24
24
  ```tsx
25
- import {createAiSlice, createDefaultAiConfig, useAiStore} from '@sqlrooms/ai';
25
+ import {createAiSlice, createDefaultAiConfig} from '@sqlrooms/ai';
26
26
  import {createProjectStore} from '@sqlrooms/project-builder';
27
27
 
28
28
  // Create a project store with AI capabilities
29
- const useStore = createProjectStore({
30
- ai: createAiSlice(createDefaultAiConfig()),
29
+ const {projectStore, useProjectStore} = createProjectStore({
30
+ // Base project configuration
31
+ ...createProjectSlice({
32
+ config: {
33
+ // Your project configuration
34
+ ...createDefaultAiConfig(), // Default AI configuration
35
+ },
36
+ }),
37
+ // Add AI slice
38
+ ...createAiSlice({
39
+ getApiKey: (modelProvider) => {
40
+ // Return API key for the specified model provider
41
+ return process.env.OPENAI_API_KEY || '';
42
+ },
43
+ initialAnalysisPrompt: 'What insights can you provide from my data?',
44
+ // Optional: Add custom tools
45
+ customTools: {
46
+ // Your custom tools
47
+ },
48
+ // Optional: Custom instructions for the AI
49
+ getInstructions: (tablesSchema) => {
50
+ return `Analyze the following tables: ${tablesSchema.map((t) => t.name).join(', ')}`;
51
+ },
52
+ }),
31
53
  });
32
54
 
33
55
  function MyApp() {
34
56
  return (
35
- <ProjectStateProvider projectStore={useStore}>
57
+ <ProjectStateProvider projectStore={projectStore}>
36
58
  <MyDataApp />
37
59
  </ProjectStateProvider>
38
60
  );
39
61
  }
40
62
  ```
41
63
 
64
+ ### Advanced Store Configuration
65
+
66
+ For more complex applications, you can combine multiple slices:
67
+
68
+ ```tsx
69
+ import {
70
+ createAiSlice,
71
+ createDefaultAiConfig,
72
+ AiSliceConfig,
73
+ } from '@sqlrooms/ai';
74
+ import {
75
+ createSqlEditorSlice,
76
+ createDefaultSqlEditorConfig,
77
+ } from '@sqlrooms/sql-editor';
78
+ import {
79
+ createProjectStore,
80
+ createProjectSlice,
81
+ } from '@sqlrooms/project-builder';
82
+
83
+ // Define your application state type
84
+ export type AppState = ProjectState<AppConfig> &
85
+ AiSliceState &
86
+ SqlEditorSliceState;
87
+
88
+ // Create the store with multiple slices
89
+ export const {projectStore, useProjectStore} = createProjectStore<
90
+ AppConfig,
91
+ AppState
92
+ >((set, get, store) => ({
93
+ // Base project slice
94
+ ...createProjectSlice({
95
+ config: {
96
+ // Your base configuration
97
+ ...createDefaultAiConfig({
98
+ // Optional: Pre-configured AI sessions
99
+ sessions: [
100
+ {
101
+ id: 'default-session',
102
+ name: 'Default Analysis',
103
+ modelProvider: 'openai',
104
+ model: 'gpt-4o',
105
+ analysisResults: [],
106
+ createdAt: new Date(),
107
+ },
108
+ ],
109
+ currentSessionId: 'default-session',
110
+ }),
111
+ ...createDefaultSqlEditorConfig(),
112
+ },
113
+ }),
114
+ // AI slice
115
+ ...createAiSlice({
116
+ getApiKey: (modelProvider) => {
117
+ // Return API key based on provider
118
+ return apiKeys[modelProvider] || '';
119
+ },
120
+ // Custom tools and instructions
121
+ }),
122
+ // SQL Editor slice
123
+ ...createSqlEditorSlice(),
124
+ }));
125
+ ```
126
+
42
127
  ### Using AI Query Controls
43
128
 
44
129
  ```tsx
@@ -46,8 +131,8 @@ import {QueryControls} from '@sqlrooms/ai';
46
131
 
47
132
  function AiQueryPanel() {
48
133
  return (
49
- <div className="p-4 border rounded-lg">
50
- <h2 className="text-xl font-bold mb-4">Ask AI</h2>
134
+ <div className="rounded-lg border p-4">
135
+ <h2 className="mb-4 text-xl font-bold">Ask AI</h2>
51
136
  <QueryControls
52
137
  placeholder="Ask a question about your data..."
53
138
  onSubmit={(query) => console.log('Processing query:', query)}
@@ -61,17 +146,20 @@ function AiQueryPanel() {
61
146
 
62
147
  ```tsx
63
148
  import {AnalysisResultsContainer, AnalysisResult} from '@sqlrooms/ai';
64
- import {useAiStore} from '@sqlrooms/ai';
65
149
 
66
150
  function AnalysisPanel() {
67
- const {analysisResults} = useAiStore();
151
+ // Get the current session and its analysis results
152
+ const currentSession = useProjectStore((state) =>
153
+ state.ai.getCurrentSession(),
154
+ );
155
+ const analysisResults = currentSession?.analysisResults || [];
68
156
 
69
157
  return (
70
- <div className="p-4 border rounded-lg">
71
- <h2 className="text-xl font-bold mb-4">AI Analysis</h2>
158
+ <div className="rounded-lg border p-4">
159
+ <h2 className="mb-4 text-xl font-bold">AI Analysis</h2>
72
160
  <AnalysisResultsContainer>
73
- {analysisResults.map((result, index) => (
74
- <AnalysisResult key={index} result={result} />
161
+ {analysisResults.map((result) => (
162
+ <AnalysisResult key={result.id} result={result} />
75
163
  ))}
76
164
  </AnalysisResultsContainer>
77
165
  </div>
@@ -82,33 +170,297 @@ function AnalysisPanel() {
82
170
  ### Working with AI State
83
171
 
84
172
  ```tsx
85
- import {useAiStore} from '@sqlrooms/ai';
86
-
87
173
  function AiStatusIndicator() {
88
- const {isProcessing, lastQuery, error} = useAiStore();
174
+ const isRunningAnalysis = useProjectStore(
175
+ (state) => state.ai.isRunningAnalysis,
176
+ );
177
+ const analysisPrompt = useProjectStore((state) => state.ai.analysisPrompt);
178
+ const currentSession = useProjectStore((state) =>
179
+ state.ai.getCurrentSession(),
180
+ );
181
+ const lastResult =
182
+ currentSession?.analysisResults[currentSession.analysisResults.length - 1];
89
183
 
90
- if (isProcessing) {
91
- return <div>AI is thinking...</div>;
184
+ if (isRunningAnalysis) {
185
+ return <div>AI is analyzing your data...</div>;
92
186
  }
93
187
 
94
- if (error) {
95
- return <div>Error: {error.message}</div>;
188
+ if (lastResult?.errorMessage) {
189
+ return <div>Error: {lastResult.errorMessage.message}</div>;
96
190
  }
97
191
 
98
- if (lastQuery) {
99
- return <div>Last query: "{lastQuery}"</div>;
192
+ if (analysisPrompt) {
193
+ return <div>Last query: "{analysisPrompt}"</div>;
100
194
  }
101
195
 
102
196
  return <div>Ask AI a question about your data</div>;
103
197
  }
104
198
  ```
105
199
 
200
+ ## AiSlice API Reference
201
+
202
+ The AiSlice provides a comprehensive set of state fields and methods for managing AI interactions in your application.
203
+
204
+ ### State Fields
205
+
206
+ #### `analysisPrompt`
207
+
208
+ The current prompt text entered by the user for analysis.
209
+
210
+ ```tsx
211
+ const prompt = useProjectStore((state) => state.ai.analysisPrompt);
212
+ ```
213
+
214
+ #### `isRunningAnalysis`
215
+
216
+ Boolean flag indicating whether an analysis is currently in progress.
217
+
218
+ ```tsx
219
+ const isRunning = useProjectStore((state) => state.ai.isRunningAnalysis);
220
+ ```
221
+
222
+ #### `tools`
223
+
224
+ Record of available AI tools that can be used during analysis.
225
+
226
+ ```tsx
227
+ const availableTools = useProjectStore((state) => state.ai.tools);
228
+ ```
229
+
230
+ #### `analysisAbortController`
231
+
232
+ Optional AbortController instance that can be used to cancel an ongoing analysis.
233
+
234
+ ```tsx
235
+ const abortController = useProjectStore(
236
+ (state) => state.ai.analysisAbortController,
237
+ );
238
+ ```
239
+
240
+ ### Methods
241
+
242
+ #### `setAnalysisPrompt(prompt: string)`
243
+
244
+ Sets the current analysis prompt text.
245
+
246
+ ```tsx
247
+ const setPrompt = useProjectStore((state) => state.ai.setAnalysisPrompt);
248
+ setPrompt('Analyze sales trends for the last quarter');
249
+ ```
250
+
251
+ #### `startAnalysis()`
252
+
253
+ Starts the analysis process using the current prompt.
254
+
255
+ ```tsx
256
+ const startAnalysis = useProjectStore((state) => state.ai.startAnalysis);
257
+ await startAnalysis();
258
+ ```
259
+
260
+ #### `cancelAnalysis()`
261
+
262
+ Cancels any ongoing analysis.
263
+
264
+ ```tsx
265
+ const cancelAnalysis = useProjectStore((state) => state.ai.cancelAnalysis);
266
+ cancelAnalysis();
267
+ ```
268
+
269
+ #### `setAiModel(modelProvider: string, model: string)`
270
+
271
+ Sets the AI model and provider for the current session.
272
+
273
+ ```tsx
274
+ const setModel = useProjectStore((state) => state.ai.setAiModel);
275
+ setModel('openai', 'gpt-4o');
276
+ ```
277
+
278
+ #### `createSession(name?: string, modelProvider?: string, model?: string)`
279
+
280
+ Creates a new analysis session with optional name and model settings.
281
+
282
+ ```tsx
283
+ const createSession = useProjectStore((state) => state.ai.createSession);
284
+ createSession('Financial Analysis', 'openai', 'gpt-4o');
285
+ ```
286
+
287
+ #### `switchSession(sessionId: string)`
288
+
289
+ Switches to a different analysis session by ID.
290
+
291
+ ```tsx
292
+ const switchSession = useProjectStore((state) => state.ai.switchSession);
293
+ switchSession('session-123');
294
+ ```
295
+
296
+ #### `renameSession(sessionId: string, name: string)`
297
+
298
+ Renames an existing analysis session.
299
+
300
+ ```tsx
301
+ const renameSession = useProjectStore((state) => state.ai.renameSession);
302
+ renameSession('session-123', 'Q4 Sales Analysis');
303
+ ```
304
+
305
+ #### `deleteSession(sessionId: string)`
306
+
307
+ Deletes an analysis session by ID.
308
+
309
+ ```tsx
310
+ const deleteSession = useProjectStore((state) => state.ai.deleteSession);
311
+ deleteSession('session-123');
312
+ ```
313
+
314
+ #### `getCurrentSession()`
315
+
316
+ Returns the current active analysis session.
317
+
318
+ ```tsx
319
+ const currentSession = useProjectStore((state) => state.ai.getCurrentSession());
320
+ ```
321
+
322
+ #### `deleteAnalysisResult(sessionId: string, resultId: string)`
323
+
324
+ Deletes a specific analysis result from a session.
325
+
326
+ ```tsx
327
+ const deleteResult = useProjectStore((state) => state.ai.deleteAnalysisResult);
328
+ deleteResult('session-123', 'result-456');
329
+ ```
330
+
331
+ #### `findToolComponent(toolName: string)`
332
+
333
+ Finds the React component associated with a specific tool.
334
+
335
+ ```tsx
336
+ const ChartComponent = useProjectStore((state) =>
337
+ state.ai.findToolComponent('chart'),
338
+ );
339
+ ```
340
+
341
+ ## Data Structure
342
+
343
+ The basic data structure of the AI package is:
344
+
345
+ ```ts
346
+ ai: {
347
+ sessions: [
348
+ {
349
+ id: defaultSessionId,
350
+ name: 'Default Session',
351
+ modelProvider: 'openai',
352
+ model: 'gpt-4o-mini',
353
+ analysisResults: [],
354
+ createdAt: new Date(),
355
+ },
356
+ ],
357
+ currentSessionId: defaultSessionId,
358
+ }
359
+ ```
360
+
361
+ Each session has a `analysisResults` which is an array of `AnalysisResult`. Each `AnalysisResult` has the following properties:
362
+
363
+ - `id`: The unique identifier for the analysis result
364
+ - `prompt`: The user prompt that was used to generate the analysis result
365
+ - `streamMessage`: The stream message from the LLM
366
+ - `errorMessage`: The error message from the LLM
367
+ - `isCompleted`: Whether the analysis result has been completed
368
+
369
+ For each user prompt, the LLM will run multiple tools (e.g. `query`, `chart`) and return the result as the `streamMessage`. The structure of the `streamMessage` is as follows:
370
+
371
+ - `text`: the final response from the LLM (streamable)
372
+ - `reasoning`: the reasoning of the LLM (only for reason models)
373
+ - `toolCallMessages`: the message array of the tool calls executed by the LLM
374
+
375
+ Each `toolCallMessages` has the following properties:
376
+
377
+ - `toolName`: the name of the tool
378
+ - `toolCallId`: the id of the tool call
379
+ - `args`: the arguments of the tool call
380
+ - `llmResult`: the result from the execution of the tool, which will be sent back to the LLM as response.
381
+ - `additionalData`: the additional data of the tool, which can be used to pass the output of the tool to next tool call or the component for rendering.
382
+
383
+ ## Rendering
384
+
385
+ ```
386
+ |--------------------------------|
387
+ | AnalysisResultsContainer |
388
+ |--------------------------------|
389
+ | |--------------------------| |
390
+ | | AnalysisResult | |
391
+ | | | |
392
+ | | streamMessage | |
393
+ | | | |
394
+ | | |---------------------| | |
395
+ | | | Tools | | |
396
+ | | |---------------------| | |
397
+ | | | |---------------| | | |
398
+ | | | |ToolCallMessage| | | |
399
+ | | | |---------------| | | |
400
+ | | | |---------------| | | |
401
+ | | | |ToolCallMessage| | | |
402
+ | | | |---------------| | | |
403
+ | | | ... | | |
404
+ | | |---------------------| | |
405
+ | | | |
406
+ | | text | |
407
+ | |--------------------------| |
408
+ |--------------------------------|
409
+ ```
410
+
411
+ ## Tools
412
+
413
+ In AI package, we provide a tool() to allow creating function tool for LLM to use. It is an extension of the `tool` from `vercel ai sdk`, and it supports not only `execute` function, but also `context` object and `component` object:
414
+
415
+ - `execute` needs to return
416
+ - llmResult: the result send back to LLM (no raw data)
417
+ - additionalData: the data will be used by `component` and next `tool`
418
+ - `context`
419
+ - provide e.g. runtime or async data for `execute`
420
+ - `execute` can access `context` via `options.context`
421
+ - `component`
422
+ - use `additionalData` to render a React component for this `tool`
423
+
424
+ For example, the `query` tool is defined as follows:
425
+
426
+ ```ts
427
+ const functions = {
428
+ weather: tool({
429
+ description: 'Get the weather in a city from a weather station',
430
+ parameters: z.object({cityName: z.string()}),
431
+ execute: async ({cityName}, options) => {
432
+ const getStation = options.context?.getStation;
433
+ const station = getStation ? await getStation(cityName) : null;
434
+ return {
435
+ llmResult: `The weather in ${cityName} is sunny from weather station ${station}.`,
436
+ additionalData: {
437
+ weather: 'sunny',
438
+ station,
439
+ },
440
+ };
441
+ },
442
+ context: {
443
+ getStation: async (cityName: string) => {
444
+ const stations = {
445
+ 'New York': '123',
446
+ 'Los Angeles': '456',
447
+ Chicago: '789',
448
+ };
449
+ return stations[cityName];
450
+ },
451
+ },
452
+ component: WeatherStation,
453
+ }),
454
+ };
455
+ ```
456
+
106
457
  ## Advanced Features
107
458
 
108
- - **Custom AI Tools**: Define custom tools for AI to use
109
- - **Query Templates**: Create and manage reusable query templates
110
- - **Result Visualization**: Automatically visualize AI analysis results
111
- - **Conversation Context**: Maintain context across multiple queries
459
+ - **Custom AI Tools**: Define custom tools for AI to use with the tool() function
460
+ - **Multiple Sessions**: Create and manage multiple analysis sessions for different purposes
461
+ - **Model Selection**: Switch between different AI models and providers
462
+ - **Result Management**: Save, delete, and organize analysis results
463
+ - **Conversation Context**: Maintain context across multiple queries in a session
112
464
  - **Feedback Loop**: Collect user feedback to improve AI responses
113
465
 
114
466
  For more information, visit the SQLRooms documentation.