@sqlrooms/ai 0.5.1 → 0.6.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.
package/dist/AiSlice.d.ts CHANGED
@@ -1,12 +1,13 @@
1
1
  import { ProjectState, type StateCreator } from '@sqlrooms/project-builder';
2
2
  import { BaseProjectConfig } from '@sqlrooms/project-config';
3
- import { CoreAssistantMessage, CoreToolMessage, CoreUserMessage, LanguageModelV1 } from 'ai';
3
+ import { CoreAssistantMessage, CoreToolMessage, CoreUserMessage } from 'ai';
4
4
  import { z } from 'zod';
5
5
  type AiMessage = (CoreToolMessage | CoreAssistantMessage | CoreUserMessage) & {
6
6
  id: string;
7
7
  };
8
8
  export declare const AiSliceConfig: z.ZodObject<{
9
9
  ai: z.ZodObject<{
10
+ modelProvider: z.ZodString;
10
11
  model: z.ZodString;
11
12
  analysisResults: z.ZodArray<z.ZodObject<{
12
13
  id: z.ZodString;
@@ -73,32 +74,17 @@ export declare const AiSliceConfig: z.ZodObject<{
73
74
  sqlQuery: string;
74
75
  reasoning: string;
75
76
  }>, z.ZodObject<{
76
- type: z.ZodLiteral<"answer">;
77
- answer: z.ZodString;
78
- chart: z.ZodUnion<[z.ZodObject<{
79
- sqlQuery: z.ZodString;
80
- vegaLiteSpec: z.ZodString;
81
- }, "strip", z.ZodTypeAny, {
82
- sqlQuery: string;
83
- vegaLiteSpec: string;
84
- }, {
85
- sqlQuery: string;
86
- vegaLiteSpec: string;
87
- }>, z.ZodNull]>;
77
+ sqlQuery: z.ZodString;
78
+ vegaLiteSpec: z.ZodString;
79
+ reasoning: z.ZodString;
88
80
  }, "strip", z.ZodTypeAny, {
89
- type: "answer";
90
- answer: string;
91
- chart: {
92
- sqlQuery: string;
93
- vegaLiteSpec: string;
94
- } | null;
81
+ sqlQuery: string;
82
+ reasoning: string;
83
+ vegaLiteSpec: string;
95
84
  }, {
96
- type: "answer";
97
- answer: string;
98
- chart: {
99
- sqlQuery: string;
100
- vegaLiteSpec: string;
101
- } | null;
85
+ sqlQuery: string;
86
+ reasoning: string;
87
+ vegaLiteSpec: string;
102
88
  }>]>;
103
89
  }, "strip", z.ZodTypeAny, {
104
90
  toolName: string;
@@ -108,12 +94,9 @@ export declare const AiSliceConfig: z.ZodObject<{
108
94
  sqlQuery: string;
109
95
  reasoning: string;
110
96
  } | {
111
- type: "answer";
112
- answer: string;
113
- chart: {
114
- sqlQuery: string;
115
- vegaLiteSpec: string;
116
- } | null;
97
+ sqlQuery: string;
98
+ reasoning: string;
99
+ vegaLiteSpec: string;
117
100
  };
118
101
  }, {
119
102
  toolName: string;
@@ -123,14 +106,23 @@ export declare const AiSliceConfig: z.ZodObject<{
123
106
  sqlQuery: string;
124
107
  reasoning: string;
125
108
  } | {
126
- type: "answer";
127
- answer: string;
128
- chart: {
129
- sqlQuery: string;
130
- vegaLiteSpec: string;
131
- } | null;
109
+ sqlQuery: string;
110
+ reasoning: string;
111
+ vegaLiteSpec: string;
132
112
  };
133
113
  }>, "many">;
114
+ toolCallMessages: z.ZodArray<z.ZodObject<{
115
+ toolCallId: z.ZodString;
116
+ element: z.ZodAny;
117
+ }, "strip", z.ZodTypeAny, {
118
+ toolCallId: string;
119
+ element?: any;
120
+ }, {
121
+ toolCallId: string;
122
+ element?: any;
123
+ }>, "many">;
124
+ analysis: z.ZodString;
125
+ isCompleted: z.ZodBoolean;
134
126
  }, "strip", z.ZodTypeAny, {
135
127
  id: string;
136
128
  prompt: string;
@@ -154,14 +146,17 @@ export declare const AiSliceConfig: z.ZodObject<{
154
146
  sqlQuery: string;
155
147
  reasoning: string;
156
148
  } | {
157
- type: "answer";
158
- answer: string;
159
- chart: {
160
- sqlQuery: string;
161
- vegaLiteSpec: string;
162
- } | null;
149
+ sqlQuery: string;
150
+ reasoning: string;
151
+ vegaLiteSpec: string;
163
152
  };
164
153
  }[];
154
+ toolCallMessages: {
155
+ toolCallId: string;
156
+ element?: any;
157
+ }[];
158
+ analysis: string;
159
+ isCompleted: boolean;
165
160
  }, {
166
161
  id: string;
167
162
  prompt: string;
@@ -185,16 +180,20 @@ export declare const AiSliceConfig: z.ZodObject<{
185
180
  sqlQuery: string;
186
181
  reasoning: string;
187
182
  } | {
188
- type: "answer";
189
- answer: string;
190
- chart: {
191
- sqlQuery: string;
192
- vegaLiteSpec: string;
193
- } | null;
183
+ sqlQuery: string;
184
+ reasoning: string;
185
+ vegaLiteSpec: string;
194
186
  };
195
187
  }[];
188
+ toolCallMessages: {
189
+ toolCallId: string;
190
+ element?: any;
191
+ }[];
192
+ analysis: string;
193
+ isCompleted: boolean;
196
194
  }>, "many">;
197
195
  }, "strip", z.ZodTypeAny, {
196
+ modelProvider: string;
198
197
  model: string;
199
198
  analysisResults: {
200
199
  id: string;
@@ -219,16 +218,20 @@ export declare const AiSliceConfig: z.ZodObject<{
219
218
  sqlQuery: string;
220
219
  reasoning: string;
221
220
  } | {
222
- type: "answer";
223
- answer: string;
224
- chart: {
225
- sqlQuery: string;
226
- vegaLiteSpec: string;
227
- } | null;
221
+ sqlQuery: string;
222
+ reasoning: string;
223
+ vegaLiteSpec: string;
228
224
  };
229
225
  }[];
226
+ toolCallMessages: {
227
+ toolCallId: string;
228
+ element?: any;
229
+ }[];
230
+ analysis: string;
231
+ isCompleted: boolean;
230
232
  }[];
231
233
  }, {
234
+ modelProvider: string;
232
235
  model: string;
233
236
  analysisResults: {
234
237
  id: string;
@@ -253,18 +256,22 @@ export declare const AiSliceConfig: z.ZodObject<{
253
256
  sqlQuery: string;
254
257
  reasoning: string;
255
258
  } | {
256
- type: "answer";
257
- answer: string;
258
- chart: {
259
- sqlQuery: string;
260
- vegaLiteSpec: string;
261
- } | null;
259
+ sqlQuery: string;
260
+ reasoning: string;
261
+ vegaLiteSpec: string;
262
262
  };
263
263
  }[];
264
+ toolCallMessages: {
265
+ toolCallId: string;
266
+ element?: any;
267
+ }[];
268
+ analysis: string;
269
+ isCompleted: boolean;
264
270
  }[];
265
271
  }>;
266
272
  }, "strip", z.ZodTypeAny, {
267
273
  ai: {
274
+ modelProvider: string;
268
275
  model: string;
269
276
  analysisResults: {
270
277
  id: string;
@@ -289,18 +296,22 @@ export declare const AiSliceConfig: z.ZodObject<{
289
296
  sqlQuery: string;
290
297
  reasoning: string;
291
298
  } | {
292
- type: "answer";
293
- answer: string;
294
- chart: {
295
- sqlQuery: string;
296
- vegaLiteSpec: string;
297
- } | null;
299
+ sqlQuery: string;
300
+ reasoning: string;
301
+ vegaLiteSpec: string;
298
302
  };
299
303
  }[];
304
+ toolCallMessages: {
305
+ toolCallId: string;
306
+ element?: any;
307
+ }[];
308
+ analysis: string;
309
+ isCompleted: boolean;
300
310
  }[];
301
311
  };
302
312
  }, {
303
313
  ai: {
314
+ modelProvider: string;
304
315
  model: string;
305
316
  analysisResults: {
306
317
  id: string;
@@ -325,14 +336,17 @@ export declare const AiSliceConfig: z.ZodObject<{
325
336
  sqlQuery: string;
326
337
  reasoning: string;
327
338
  } | {
328
- type: "answer";
329
- answer: string;
330
- chart: {
331
- sqlQuery: string;
332
- vegaLiteSpec: string;
333
- } | null;
339
+ sqlQuery: string;
340
+ reasoning: string;
341
+ vegaLiteSpec: string;
334
342
  };
335
343
  }[];
344
+ toolCallMessages: {
345
+ toolCallId: string;
346
+ element?: any;
347
+ }[];
348
+ analysis: string;
349
+ isCompleted: boolean;
336
350
  }[];
337
351
  };
338
352
  }>;
@@ -349,10 +363,11 @@ export type AiSliceState = {
349
363
  messagesById: Map<string, AiMessage>;
350
364
  addMessages: (messages: AiMessage[]) => void;
351
365
  getMessages: () => AiMessage[];
366
+ setAiModel: (model: string) => void;
352
367
  };
353
368
  };
354
- export declare function createAiSlice<PC extends BaseProjectConfig & AiSliceConfig>({ createModel, initialAnalysisPrompt, }: {
355
- createModel: (model: string) => LanguageModelV1;
369
+ export declare function createAiSlice<PC extends BaseProjectConfig & AiSliceConfig>({ getApiKey, initialAnalysisPrompt, }: {
370
+ getApiKey: () => string;
356
371
  initialAnalysisPrompt?: string;
357
372
  }): StateCreator<AiSliceState>;
358
373
  type ProjectConfigWithAi = BaseProjectConfig & AiSliceConfig;
@@ -1 +1 @@
1
- {"version":3,"file":"AiSlice.d.ts","sourceRoot":"","sources":["../src/AiSlice.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,YAAY,EAEZ,KAAK,YAAY,EAClB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAC,iBAAiB,EAAC,MAAM,0BAA0B,CAAC;AAC3D,OAAO,EACL,oBAAoB,EACpB,eAAe,EACf,eAAe,EACf,eAAe,EAChB,MAAM,IAAI,CAAC;AAEZ,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AAQtB,KAAK,SAAS,GAAG,CAAC,eAAe,GAAG,oBAAoB,GAAG,eAAe,CAAC,GAAG;IAC5E,EAAE,EAAE,MAAM,CAAC;CACZ,CAAC;AAEF,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAKxB,CAAC;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAC;AAE1D,wBAAgB,qBAAqB,IAAI,aAAa,CAOrD;AAED,MAAM,MAAM,YAAY,GAAG;IACzB,EAAE,EAAE;QACF,cAAc,EAAE,MAAM,CAAC;QACvB,iBAAiB,EAAE,OAAO,CAAC;QAC3B,uBAAuB,CAAC,EAAE,eAAe,CAAC;QAC1C,iBAAiB,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;QAC5C,aAAa,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;QACnC,cAAc,EAAE,MAAM,IAAI,CAAC;QAC3B,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;QACrC,WAAW,EAAE,CAAC,QAAQ,EAAE,SAAS,EAAE,KAAK,IAAI,CAAC;QAC7C,WAAW,EAAE,MAAM,SAAS,EAAE,CAAC;KAChC,CAAC;CACH,CAAC;AAEF,wBAAgB,aAAa,CAAC,EAAE,SAAS,iBAAiB,GAAG,aAAa,EAAE,EAC1E,WAAW,EACX,qBAAgI,GACjI,EAAE;IACD,WAAW,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,eAAe,CAAC;IAChD,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAChC,GAAG,YAAY,CAAC,YAAY,CAAC,CAuJ7B;AAsCD,KAAK,mBAAmB,GAAG,iBAAiB,GAAG,aAAa,CAAC;AAC7D,KAAK,kBAAkB,GAAG,YAAY,CAAC,mBAAmB,CAAC,GAAG,YAAY,CAAC;AAE3E,wBAAgB,cAAc,CAAC,CAAC,EAC9B,QAAQ,EAAE,CAAC,KAAK,EAAE,kBAAkB,KAAK,CAAC,GACzC,CAAC,CAMH"}
1
+ {"version":3,"file":"AiSlice.d.ts","sourceRoot":"","sources":["../src/AiSlice.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,YAAY,EAEZ,KAAK,YAAY,EAClB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAC,iBAAiB,EAAC,MAAM,0BAA0B,CAAC;AAC3D,OAAO,EACL,oBAAoB,EACpB,eAAe,EACf,eAAe,EAGhB,MAAM,IAAI,CAAC;AAEZ,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AAQtB,KAAK,SAAS,GAAG,CAAC,eAAe,GAAG,oBAAoB,GAAG,eAAe,CAAC,GAAG;IAC5E,EAAE,EAAE,MAAM,CAAC;CACZ,CAAC;AAEF,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAMxB,CAAC;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAC;AAE1D,wBAAgB,qBAAqB,IAAI,aAAa,CAQrD;AAED,MAAM,MAAM,YAAY,GAAG;IACzB,EAAE,EAAE;QACF,cAAc,EAAE,MAAM,CAAC;QACvB,iBAAiB,EAAE,OAAO,CAAC;QAC3B,uBAAuB,CAAC,EAAE,eAAe,CAAC;QAC1C,iBAAiB,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;QAC5C,aAAa,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;QACnC,cAAc,EAAE,MAAM,IAAI,CAAC;QAC3B,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;QACrC,WAAW,EAAE,CAAC,QAAQ,EAAE,SAAS,EAAE,KAAK,IAAI,CAAC;QAC7C,WAAW,EAAE,MAAM,SAAS,EAAE,CAAC;QAC/B,UAAU,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;KACrC,CAAC;CACH,CAAC;AAwFF,wBAAgB,aAAa,CAAC,EAAE,SAAS,iBAAiB,GAAG,aAAa,EAAE,EAC1E,SAAS,EACT,qBAAgI,GACjI,EAAE;IACD,SAAS,EAAE,MAAM,MAAM,CAAC;IACxB,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAChC,GAAG,YAAY,CAAC,YAAY,CAAC,CAiH7B;AA+DD,KAAK,mBAAmB,GAAG,iBAAiB,GAAG,aAAa,CAAC;AAC7D,KAAK,kBAAkB,GAAG,YAAY,CAAC,mBAAmB,CAAC,GAAG,YAAY,CAAC;AAE3E,wBAAgB,cAAc,CAAC,CAAC,EAC9B,QAAQ,EAAE,CAAC,KAAK,EAAE,kBAAkB,KAAK,CAAC,GACzC,CAAC,CAMH"}
package/dist/AiSlice.js CHANGED
@@ -6,6 +6,7 @@ import { runAnalysis } from './analysis';
6
6
  import { AnalysisResultSchema, } from './schemas';
7
7
  export const AiSliceConfig = z.object({
8
8
  ai: z.object({
9
+ modelProvider: z.string(),
9
10
  model: z.string(),
10
11
  analysisResults: z.array(AnalysisResultSchema),
11
12
  }),
@@ -13,23 +14,86 @@ export const AiSliceConfig = z.object({
13
14
  export function createDefaultAiConfig() {
14
15
  return {
15
16
  ai: {
17
+ modelProvider: 'openai',
16
18
  model: 'gpt-4o-mini',
17
19
  analysisResults: [],
18
20
  },
19
21
  };
20
22
  }
21
- export function createAiSlice({ createModel, initialAnalysisPrompt = 'Describe the data in the tables and make a chart providing an overview of the most important features.', }) {
23
+ /**
24
+ * Execute the analysis. It will be used by the action `startAnalysis`.
25
+ *
26
+ * Each analysis contains an array of toolCalls and the results of the tool calls (toolResults).
27
+ * After all the tool calls have been executed, the LLM will stream the results as text stored in `analysis`.
28
+ *
29
+ * @param resultId - The result id
30
+ * @param prompt - The prompt
31
+ * @param model - The model
32
+ * @param apiKey - The api key
33
+ * @param abortController - The abort controller
34
+ * @param addMessages - The add messages function
35
+ * @param set - The set function
36
+ */
37
+ async function executeAnalysis({ resultId, prompt, modelProvider, model, apiKey, abortController, addMessages, set, }) {
38
+ try {
39
+ await runAnalysis({
40
+ modelProvider,
41
+ model,
42
+ apiKey,
43
+ prompt,
44
+ abortController,
45
+ onStepFinish: (event, toolCallMessages) => {
46
+ addMessages(event.response.messages);
47
+ set(makeResultsAppender({
48
+ resultId,
49
+ toolResults: event.toolResults,
50
+ toolCalls: event.toolCalls,
51
+ toolCallMessages,
52
+ }));
53
+ },
54
+ onStreamResult: (message, isCompleted) => {
55
+ set(makeResultsAppender({
56
+ resultId,
57
+ analysis: message,
58
+ isCompleted,
59
+ }));
60
+ },
61
+ });
62
+ }
63
+ catch (err) {
64
+ set(makeResultsAppender({
65
+ resultId,
66
+ isCompleted: true,
67
+ toolResults: [
68
+ {
69
+ toolName: 'error',
70
+ toolCallId: createId(),
71
+ args: {},
72
+ result: {
73
+ success: false,
74
+ error: err instanceof Error ? err.message : String(err),
75
+ },
76
+ },
77
+ ],
78
+ toolCalls: [],
79
+ }));
80
+ }
81
+ }
82
+ export function createAiSlice({ getApiKey, initialAnalysisPrompt = 'Describe the data in the tables and make a chart providing an overview of the most important features.', }) {
22
83
  return createSlice((set, get) => ({
23
84
  ai: {
24
85
  analysisPrompt: initialAnalysisPrompt,
25
86
  isRunningAnalysis: false,
26
87
  messagesById: new Map(),
27
- apiKey: null,
28
88
  setAnalysisPrompt: (prompt) => {
29
89
  set((state) => produce(state, (draft) => {
30
90
  draft.ai.analysisPrompt = prompt;
31
91
  }));
32
92
  },
93
+ /**
94
+ * Set the AI model
95
+ * @param model - The model to set
96
+ */
33
97
  setAiModel: (model) => {
34
98
  set((state) => produce(state, (draft) => {
35
99
  draft.project.config.ai.model = model;
@@ -49,7 +113,6 @@ export function createAiSlice({ createModel, initialAnalysisPrompt = 'Describe t
49
113
  }
50
114
  newMessagesById.set(m.id, m);
51
115
  }
52
- console.log('newMessagesById', Array.from(newMessagesById.values()));
53
116
  return {
54
117
  ai: {
55
118
  ...state.ai,
@@ -72,6 +135,9 @@ export function createAiSlice({ createModel, initialAnalysisPrompt = 'Describe t
72
135
  prompt: get().ai.analysisPrompt,
73
136
  toolResults: [],
74
137
  toolCalls: [],
138
+ toolCallMessages: [],
139
+ analysis: '',
140
+ isCompleted: false,
75
141
  });
76
142
  }));
77
143
  get().ai.addMessages([
@@ -81,63 +147,22 @@ export function createAiSlice({ createModel, initialAnalysisPrompt = 'Describe t
81
147
  content: get().ai.analysisPrompt,
82
148
  },
83
149
  ]);
84
- set((state) => produce(state, (draft) => {
85
- draft.ai.analysisPrompt = '';
86
- }));
87
150
  try {
88
- const { toolResults, toolCalls, ...rest } = await runAnalysis({
89
- model: createModel(get().project.config.ai.model),
90
- // prompt: get().analysisPrompt,
91
- messages: get().ai.getMessages(),
92
- onStepFinish: (event) => {
93
- console.log('onStepFinish', event);
94
- get().ai.addMessages(event.response.messages);
95
- set(makeResultsAppender({
96
- resultId,
97
- toolResults: event.toolResults,
98
- toolCalls: event.toolCalls,
99
- }));
100
- },
101
- abortSignal: abortController.signal,
102
- });
103
- console.log('final result', { toolResults, toolCalls, ...rest });
104
- // get().ai.addMessages([
105
- // {
106
- // id: createId(),
107
- // role: 'tool',
108
- // content: [],
109
- // // @ts-ignore
110
- // tool_call_id: toolCalls[toolCalls.length - 1].toolCallId,
111
- // } satisfies AiMessage,
112
- // ]);
113
- // set(
114
- // makeResultsAppender({
115
- // resultId,
116
- // toolResults,
117
- // toolCalls: rest.toolCalls,
118
- // }),
119
- // );
120
- }
121
- catch (err) {
122
- set(makeResultsAppender({
151
+ await executeAnalysis({
123
152
  resultId,
124
- toolResults: [
125
- {
126
- toolName: 'answer',
127
- toolCallId: createId(),
128
- args: {},
129
- result: {
130
- success: false,
131
- error: err instanceof Error ? err.message : String(err),
132
- },
133
- },
134
- ],
135
- toolCalls: [],
136
- }));
153
+ prompt: get().ai.analysisPrompt,
154
+ modelProvider: get().project.config.ai.modelProvider,
155
+ model: get().project.config.ai.model,
156
+ apiKey: getApiKey(),
157
+ abortController,
158
+ addMessages: get().ai.addMessages,
159
+ set,
160
+ });
137
161
  }
138
162
  finally {
139
163
  set((state) => produce(state, (draft) => {
140
164
  draft.ai.isRunningAnalysis = false;
165
+ draft.ai.analysisPrompt = '';
141
166
  }));
142
167
  }
143
168
  },
@@ -154,19 +179,38 @@ function findResultById(analysisResults, id) {
154
179
  return analysisResults.find((r) => r.id === id);
155
180
  }
156
181
  /**
157
- * Returns a function that will update the state by appending new results
158
- * to the analysis results.
182
+ * Returns a function that will update the state by appending new results to the analysis results.
183
+ *
159
184
  * @param resultId - The result id
160
- * @param toolResults - The new tool results
161
- * @param toolCalls - The new tool calls
185
+ * @param toolCalls - The tool calls that were executed by the LLM, e.g. "query" or "chart" ("map" will be added soon). See {@link ToolCallSchema} for more details.
186
+ * @param toolResults - The results of the tool calls that were executed by the LLM. See {@link ToolResultSchema} for more details.
187
+ * @param toolCallMessages - The tool call messages that were created by some of our defined TOOLS, e.g. the table with query result. It's an array of React/JSX elements. It is linked to the tool call by the toolCallId.
188
+ * @param analysis - The analysis is the content generated after all the tool calls have been executed
189
+ * @param isCompleted - Whether the analysis is completed
162
190
  * @returns The new state
163
191
  */
164
- function makeResultsAppender({ resultId, toolResults, toolCalls, }) {
192
+ function makeResultsAppender({ resultId, toolResults, toolCalls, analysis, isCompleted, toolCallMessages, }) {
165
193
  return (state) => produce(state, (draft) => {
166
194
  const result = findResultById(draft.project.config.ai.analysisResults, resultId);
167
195
  if (result) {
168
- result.toolResults = [...result.toolResults, ...toolResults];
169
- result.toolCalls = [...result.toolCalls, ...toolCalls];
196
+ if (toolResults) {
197
+ result.toolResults = [...result.toolResults, ...toolResults];
198
+ }
199
+ if (toolCalls) {
200
+ result.toolCalls = [...result.toolCalls, ...toolCalls];
201
+ }
202
+ if (toolCallMessages) {
203
+ result.toolCallMessages = [
204
+ ...result.toolCallMessages,
205
+ ...toolCallMessages,
206
+ ];
207
+ }
208
+ if (analysis) {
209
+ result.analysis = analysis;
210
+ }
211
+ if (isCompleted) {
212
+ result.isCompleted = isCompleted;
213
+ }
170
214
  }
171
215
  else {
172
216
  console.error('Result not found', resultId);
@@ -1 +1 @@
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 createSlice,\n ProjectState,\n useBaseProjectStore,\n type StateCreator,\n} from '@sqlrooms/project-builder';\nimport {BaseProjectConfig} from '@sqlrooms/project-config';\nimport {\n CoreAssistantMessage,\n CoreToolMessage,\n CoreUserMessage,\n LanguageModelV1,\n} from 'ai';\nimport {produce} from 'immer';\nimport {z} from 'zod';\nimport {runAnalysis} from './analysis';\nimport {\n AnalysisResultSchema,\n ToolCallSchema,\n ToolResultSchema,\n} from './schemas';\n\ntype AiMessage = (CoreToolMessage | CoreAssistantMessage | CoreUserMessage) & {\n id: string;\n};\n\nexport const AiSliceConfig = z.object({\n ai: z.object({\n model: z.string(),\n analysisResults: z.array(AnalysisResultSchema),\n }),\n});\nexport type AiSliceConfig = z.infer<typeof AiSliceConfig>;\n\nexport function createDefaultAiConfig(): AiSliceConfig {\n return {\n ai: {\n model: 'gpt-4o-mini',\n analysisResults: [],\n },\n };\n}\n\nexport type AiSliceState = {\n ai: {\n analysisPrompt: string;\n isRunningAnalysis: boolean;\n analysisAbortController?: AbortController;\n setAnalysisPrompt: (prompt: string) => void;\n startAnalysis: () => Promise<void>;\n cancelAnalysis: () => void;\n messagesById: Map<string, AiMessage>;\n addMessages: (messages: AiMessage[]) => void;\n getMessages: () => AiMessage[];\n };\n};\n\nexport function createAiSlice<PC extends BaseProjectConfig & AiSliceConfig>({\n createModel,\n initialAnalysisPrompt = 'Describe the data in the tables and make a chart providing an overview of the most important features.',\n}: {\n createModel: (model: string) => LanguageModelV1;\n initialAnalysisPrompt?: string;\n}): StateCreator<AiSliceState> {\n return createSlice<PC, AiSliceState>((set, get) => ({\n ai: {\n analysisPrompt: initialAnalysisPrompt,\n isRunningAnalysis: false,\n messagesById: new Map(),\n apiKey: null,\n\n setAnalysisPrompt: (prompt: string) => {\n set((state) =>\n produce(state, (draft) => {\n draft.ai.analysisPrompt = prompt;\n }),\n );\n },\n\n setAiModel: (model: string) => {\n set((state) =>\n produce(state, (draft) => {\n draft.project.config.ai.model = model;\n }),\n );\n },\n\n /**\n * Add messages to the project store uniquely by id\n * @param messages - The messages to add.\n */\n addMessages: (messages: AiMessage[]) => {\n set((state) => {\n const newMessages = messages.filter(\n (m) => !state.ai.messagesById.has(m.id),\n );\n const newMessagesById = new Map(state.ai.messagesById);\n for (const m of newMessages) {\n if (!m.id) {\n console.warn('Message has no id', m);\n }\n newMessagesById.set(m.id, m);\n }\n console.log('newMessagesById', Array.from(newMessagesById.values()));\n return {\n ai: {\n ...state.ai,\n messagesById: newMessagesById,\n },\n };\n });\n },\n\n getMessages: () => {\n return Array.from(get().ai.messagesById.values());\n },\n startAnalysis: async () => {\n const resultId = createId();\n const abortController = new AbortController();\n set((state) =>\n produce(state, (draft) => {\n draft.ai.analysisAbortController = abortController;\n draft.ai.isRunningAnalysis = true;\n draft.project.config.ai.analysisResults.push({\n id: resultId,\n prompt: get().ai.analysisPrompt,\n toolResults: [],\n toolCalls: [],\n });\n }),\n );\n get().ai.addMessages([\n {\n id: createId(),\n role: 'user',\n content: get().ai.analysisPrompt,\n },\n ]);\n set((state) =>\n produce(state, (draft) => {\n draft.ai.analysisPrompt = '';\n }),\n );\n try {\n const {toolResults, toolCalls, ...rest} = await runAnalysis({\n model: createModel(get().project.config.ai.model),\n // prompt: get().analysisPrompt,\n messages: get().ai.getMessages(),\n onStepFinish: (event) => {\n console.log('onStepFinish', event);\n get().ai.addMessages(event.response.messages);\n set(\n makeResultsAppender({\n resultId,\n toolResults: event.toolResults,\n toolCalls: event.toolCalls,\n }),\n );\n },\n abortSignal: abortController.signal,\n });\n console.log('final result', {toolResults, toolCalls, ...rest});\n // get().ai.addMessages([\n // {\n // id: createId(),\n // role: 'tool',\n // content: [],\n // // @ts-ignore\n // tool_call_id: toolCalls[toolCalls.length - 1].toolCallId,\n // } satisfies AiMessage,\n // ]);\n // set(\n // makeResultsAppender({\n // resultId,\n // toolResults,\n // toolCalls: rest.toolCalls,\n // }),\n // );\n } catch (err) {\n set(\n makeResultsAppender({\n resultId,\n toolResults: [\n {\n toolName: 'answer',\n toolCallId: createId(),\n args: {},\n result: {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n },\n },\n ],\n toolCalls: [],\n }),\n );\n } finally {\n set((state) =>\n produce(state, (draft) => {\n draft.ai.isRunningAnalysis = false;\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}\n\nfunction findResultById(analysisResults: AnalysisResultSchema[], id: string) {\n return analysisResults.find((r: AnalysisResultSchema) => r.id === id);\n}\n\n/**\n * Returns a function that will update the state by appending new results\n * to the analysis results.\n * @param resultId - The result id\n * @param toolResults - The new tool results\n * @param toolCalls - The new tool calls\n * @returns The new state\n */\nfunction makeResultsAppender<PC extends BaseProjectConfig & AiSliceConfig>({\n resultId,\n toolResults,\n toolCalls,\n}: {\n resultId: string;\n toolResults: ToolResultSchema[];\n toolCalls: ToolCallSchema[];\n}) {\n return (state: ProjectState<PC>) =>\n produce(state, (draft) => {\n const result = findResultById(\n draft.project.config.ai.analysisResults,\n resultId,\n );\n if (result) {\n result.toolResults = [...result.toolResults, ...toolResults];\n result.toolCalls = [...result.toolCalls, ...toolCalls];\n } else {\n console.error('Result not found', resultId);\n }\n });\n}\n\ntype ProjectConfigWithAi = BaseProjectConfig & AiSliceConfig;\ntype ProjectStateWithAi = ProjectState<ProjectConfigWithAi> & AiSliceState;\n\nexport function useStoreWithAi<T>(\n selector: (state: ProjectStateWithAi) => T,\n): T {\n return useBaseProjectStore<\n BaseProjectConfig & AiSliceConfig,\n ProjectState<ProjectConfigWithAi>,\n T\n >((state) => selector(state as unknown as ProjectStateWithAi));\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 createSlice,\n ProjectState,\n useBaseProjectStore,\n type StateCreator,\n} from '@sqlrooms/project-builder';\nimport {BaseProjectConfig} from '@sqlrooms/project-config';\nimport {\n CoreAssistantMessage,\n CoreToolMessage,\n CoreUserMessage,\n StepResult,\n ToolSet,\n} from 'ai';\nimport {produce} from 'immer';\nimport {z} from 'zod';\nimport {runAnalysis} from './analysis';\nimport {\n AnalysisResultSchema,\n ToolCallSchema,\n ToolResultSchema,\n} from './schemas';\nimport {ToolCallMessage} from '@openassistant/core';\ntype AiMessage = (CoreToolMessage | CoreAssistantMessage | CoreUserMessage) & {\n id: string;\n};\n\nexport const AiSliceConfig = z.object({\n ai: z.object({\n modelProvider: z.string(),\n model: z.string(),\n analysisResults: z.array(AnalysisResultSchema),\n }),\n});\nexport type AiSliceConfig = z.infer<typeof AiSliceConfig>;\n\nexport function createDefaultAiConfig(): AiSliceConfig {\n return {\n ai: {\n modelProvider: 'openai',\n model: 'gpt-4o-mini',\n analysisResults: [],\n },\n };\n}\n\nexport type AiSliceState = {\n ai: {\n analysisPrompt: string;\n isRunningAnalysis: boolean;\n analysisAbortController?: AbortController;\n setAnalysisPrompt: (prompt: string) => void;\n startAnalysis: () => Promise<void>;\n cancelAnalysis: () => void;\n messagesById: Map<string, AiMessage>;\n addMessages: (messages: AiMessage[]) => void;\n getMessages: () => AiMessage[];\n setAiModel: (model: string) => void;\n };\n};\n\n/**\n * Execute the analysis. It will be used by the action `startAnalysis`.\n *\n * Each analysis contains an array of toolCalls and the results of the tool calls (toolResults).\n * After all the tool calls have been executed, the LLM will stream the results as text stored in `analysis`.\n *\n * @param resultId - The result id\n * @param prompt - The prompt\n * @param model - The model\n * @param apiKey - The api key\n * @param abortController - The abort controller\n * @param addMessages - The add messages function\n * @param set - The set function\n */\nasync function executeAnalysis({\n resultId,\n prompt,\n modelProvider,\n model,\n apiKey,\n abortController,\n addMessages,\n set,\n}: {\n resultId: string;\n prompt: string;\n modelProvider: string;\n model: string;\n apiKey: string;\n abortController: AbortController;\n addMessages: (messages: AiMessage[]) => void;\n set: <T>(fn: (state: T) => T) => void;\n}) {\n try {\n await runAnalysis({\n modelProvider,\n model,\n apiKey,\n prompt,\n abortController,\n onStepFinish: (\n event: StepResult<ToolSet>,\n toolCallMessages: ToolCallMessage[],\n ) => {\n addMessages(event.response.messages);\n set(\n makeResultsAppender({\n resultId,\n toolResults: event.toolResults,\n toolCalls: event.toolCalls,\n toolCallMessages,\n }),\n );\n },\n onStreamResult: (message, isCompleted) => {\n set(\n makeResultsAppender({\n resultId,\n analysis: message,\n isCompleted,\n }),\n );\n },\n });\n } catch (err) {\n set(\n makeResultsAppender({\n resultId,\n isCompleted: true,\n toolResults: [\n {\n toolName: 'error',\n toolCallId: createId(),\n args: {},\n result: {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n },\n },\n ],\n toolCalls: [],\n }),\n );\n }\n}\n\nexport function createAiSlice<PC extends BaseProjectConfig & AiSliceConfig>({\n getApiKey,\n initialAnalysisPrompt = 'Describe the data in the tables and make a chart providing an overview of the most important features.',\n}: {\n getApiKey: () => string;\n initialAnalysisPrompt?: string;\n}): StateCreator<AiSliceState> {\n return createSlice<PC, AiSliceState>((set, get) => ({\n ai: {\n analysisPrompt: initialAnalysisPrompt,\n isRunningAnalysis: false,\n messagesById: new Map(),\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\n * @param model - The model to set\n */\n setAiModel: (model: string) => {\n set((state) =>\n produce(state, (draft) => {\n draft.project.config.ai.model = model;\n }),\n );\n },\n\n /**\n * Add messages to the project store uniquely by id\n * @param messages - The messages to add.\n */\n addMessages: (messages: AiMessage[]) => {\n set((state) => {\n const newMessages = messages.filter(\n (m) => !state.ai.messagesById.has(m.id),\n );\n const newMessagesById = new Map(state.ai.messagesById);\n for (const m of newMessages) {\n if (!m.id) {\n console.warn('Message has no id', m);\n }\n newMessagesById.set(m.id, m);\n }\n return {\n ai: {\n ...state.ai,\n messagesById: newMessagesById,\n },\n };\n });\n },\n\n getMessages: () => {\n return Array.from(get().ai.messagesById.values());\n },\n\n startAnalysis: async () => {\n const resultId = createId();\n const abortController = new AbortController();\n set((state) =>\n produce(state, (draft) => {\n draft.ai.analysisAbortController = abortController;\n draft.ai.isRunningAnalysis = true;\n draft.project.config.ai.analysisResults.push({\n id: resultId,\n prompt: get().ai.analysisPrompt,\n toolResults: [],\n toolCalls: [],\n toolCallMessages: [],\n analysis: '',\n isCompleted: false,\n });\n }),\n );\n\n get().ai.addMessages([\n {\n id: createId(),\n role: 'user',\n content: get().ai.analysisPrompt,\n },\n ]);\n\n try {\n await executeAnalysis({\n resultId,\n prompt: get().ai.analysisPrompt,\n modelProvider: get().project.config.ai.modelProvider,\n model: get().project.config.ai.model,\n apiKey: getApiKey(),\n abortController,\n addMessages: get().ai.addMessages,\n set,\n });\n } finally {\n set((state) =>\n produce(state, (draft) => {\n draft.ai.isRunningAnalysis = false;\n draft.ai.analysisPrompt = '';\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}\n\nfunction findResultById(analysisResults: AnalysisResultSchema[], id: string) {\n return analysisResults.find((r: AnalysisResultSchema) => r.id === id);\n}\n\n/**\n * Returns a function that will update the state by appending new results to the analysis results.\n *\n * @param resultId - The result id\n * @param toolCalls - The tool calls that were executed by the LLM, e.g. \"query\" or \"chart\" (\"map\" will be added soon). See {@link ToolCallSchema} for more details.\n * @param toolResults - The results of the tool calls that were executed by the LLM. See {@link ToolResultSchema} for more details.\n * @param toolCallMessages - The tool call messages that were created by some of our defined TOOLS, e.g. the table with query result. It's an array of React/JSX elements. It is linked to the tool call by the toolCallId.\n * @param analysis - The analysis is the content generated after all the tool calls have been executed\n * @param isCompleted - Whether the analysis is completed\n * @returns The new state\n */\nfunction makeResultsAppender<PC extends BaseProjectConfig & AiSliceConfig>({\n resultId,\n toolResults,\n toolCalls,\n analysis,\n isCompleted,\n toolCallMessages,\n}: {\n resultId: string;\n toolResults?: ToolResultSchema[];\n toolCalls?: ToolCallSchema[];\n analysis?: string;\n isCompleted?: boolean;\n toolCallMessages?: ToolCallMessage[];\n}) {\n return (state: ProjectState<PC>) =>\n produce(state, (draft) => {\n const result = findResultById(\n draft.project.config.ai.analysisResults,\n resultId,\n );\n if (result) {\n if (toolResults) {\n result.toolResults = [...result.toolResults, ...toolResults];\n }\n if (toolCalls) {\n result.toolCalls = [...result.toolCalls, ...toolCalls];\n }\n if (toolCallMessages) {\n result.toolCallMessages = [\n ...result.toolCallMessages,\n ...toolCallMessages,\n ];\n }\n if (analysis) {\n result.analysis = analysis;\n }\n if (isCompleted) {\n result.isCompleted = isCompleted;\n }\n } else {\n console.error('Result not found', resultId);\n }\n });\n}\n\ntype ProjectConfigWithAi = BaseProjectConfig & AiSliceConfig;\ntype ProjectStateWithAi = ProjectState<ProjectConfigWithAi> & AiSliceState;\n\nexport function useStoreWithAi<T>(\n selector: (state: ProjectStateWithAi) => T,\n): T {\n return useBaseProjectStore<\n BaseProjectConfig & AiSliceConfig,\n ProjectState<ProjectConfigWithAi>,\n T\n >((state) => selector(state as unknown as ProjectStateWithAi));\n}\n"]}
@@ -1,7 +1,21 @@
1
1
  import { AnalysisResultSchema } from './schemas';
2
- interface AnalysisResultProps {
2
+ /**
3
+ * Props for the AnalysisResult component
4
+ * @property {AnalysisResultSchema} result - The result of the analysis containing prompt, tool calls, and analysis data
5
+ */
6
+ type AnalysisResultProps = {
3
7
  result: AnalysisResultSchema;
4
- }
8
+ };
9
+ /**
10
+ * Component that displays the results of an AI analysis.
11
+ * Shows the original prompt, intermediate tool calls, final analysis text,
12
+ * and any tool results.
13
+ *
14
+ * @component
15
+ * @param props - Component props
16
+ * @param props.result - The analysis result data to display
17
+ * @returns A React component displaying the analysis results
18
+ */
5
19
  export declare const AnalysisResult: React.FC<AnalysisResultProps>;
6
20
  export {};
7
21
  //# sourceMappingURL=AnalysisResult.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"AnalysisResult.d.ts","sourceRoot":"","sources":["../src/AnalysisResult.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAC,oBAAoB,EAAC,MAAM,WAAW,CAAC;AAM/C,UAAU,mBAAmB;IAC3B,MAAM,EAAE,oBAAoB,CAAC;CAC9B;AAED,eAAO,MAAM,cAAc,EAAE,KAAK,CAAC,EAAE,CAAC,mBAAmB,CAwCxD,CAAC"}
1
+ {"version":3,"file":"AnalysisResult.d.ts","sourceRoot":"","sources":["../src/AnalysisResult.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAC,oBAAoB,EAAC,MAAM,WAAW,CAAC;AAK/C;;;GAGG;AACH,KAAK,mBAAmB,GAAG;IACzB,MAAM,EAAE,oBAAoB,CAAC;CAC9B,CAAC;AA8BF;;;;;;;;;GASG;AACH,eAAO,MAAM,cAAc,EAAE,KAAK,CAAC,EAAE,CAAC,mBAAmB,CAsDxD,CAAC"}