vzcode 2.22.0 → 2.26.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/assets/{buildWorker-Bi6wsfQk.js → buildWorker-DylWm2VX.js} +64 -72
- package/dist/assets/index-CkFweu5-.js +403 -0
- package/dist/assets/{index-fSroLVgi.css → index-Dyt9tpmu.css} +1 -5
- package/dist/assets/{worker-BSzbM0Uo.js → worker-VPLhQVba.js} +230 -230
- package/dist/assets/worker-b9bkZkXK.js +116 -0
- package/dist/assets/{worker-Cm3I3tnR.js → worker-k7HZ3t-V.js} +3 -20
- package/dist/index.html +2 -2
- package/dist/llm-streaming-server/chatOperations.js +19 -0
- package/dist/llm-streaming-server/llmStreaming.js +21 -14
- package/dist/server/aiChatHandler/index.js +6 -3
- package/package.json +23 -22
- package/src/llm-streaming-server/chatOperations.ts +27 -0
- package/src/llm-streaming-server/llmStreaming.ts +27 -14
- package/src/llm-streaming-ui/components/Message.tsx +8 -7
- package/src/llm-streaming-ui/components/MessageList.tsx +5 -0
- package/src/llm-streaming-ui/components/index.tsx +2 -2
- package/src/llm-streaming-ui/components/styles.scss +10 -0
- package/src/server/aiChatHandler/index.ts +9 -1
- package/src/types.ts +1 -0
- package/dist/assets/index-CfDs-dAu.js +0 -476
- package/dist/assets/worker-KiuLM-X4.js +0 -136
- package/dist/server/aiChatHandler/aiEditing.js +0 -58
- package/dist/server/aiChatHandler/chatOperations.js +0 -494
- package/dist/server/aiChatHandler/errorHandling.js +0 -49
- package/dist/server/aiChatHandler/llmStreaming.js +0 -265
- package/dist/server/aiChatHandler/validation.js +0 -19
- package/src/client/VZSidebar/AIChat/ChatInput.tsx +0 -237
- package/src/client/VZSidebar/AIChat/DiffView.scss +0 -173
- package/src/client/VZSidebar/AIChat/DiffView.tsx +0 -236
- package/src/client/VZSidebar/AIChat/FileEditingIndicator.tsx +0 -89
- package/src/client/VZSidebar/AIChat/IndividualFileDiff.tsx +0 -86
- package/src/client/VZSidebar/AIChat/JumpToLatestButton.tsx +0 -64
- package/src/client/VZSidebar/AIChat/Message.tsx +0 -145
- package/src/client/VZSidebar/AIChat/MessageList.tsx +0 -241
- package/src/client/VZSidebar/AIChat/ThinkingScratchpad.tsx +0 -42
- package/src/client/VZSidebar/AIChat/TypingIndicator.tsx +0 -19
- package/src/client/VZSidebar/AIChat/index.tsx +0 -388
- package/src/client/VZSidebar/AIChat/styles.scss +0 -831
- package/src/client/VZSidebar/AIChat/useSpeechRecognition.ts +0 -116
- package/src/server/aiChatHandler/aiEditing.ts +0 -102
- package/src/server/aiChatHandler/chatOperations.ts +0 -655
- package/src/server/aiChatHandler/errorHandling.ts +0 -66
- package/src/server/aiChatHandler/llmStreaming.ts +0 -403
- package/src/server/aiChatHandler/validation.ts +0 -24
|
@@ -1,655 +0,0 @@
|
|
|
1
|
-
import { dateToTimestamp } from '@vizhub/viz-utils';
|
|
2
|
-
import { randomId } from '../../randomId.js';
|
|
3
|
-
import {
|
|
4
|
-
ShareDBDoc,
|
|
5
|
-
StreamingEvent,
|
|
6
|
-
ExtendedVizContent,
|
|
7
|
-
} from '../../types.js';
|
|
8
|
-
import { diff } from '../../ot.js';
|
|
9
|
-
import {
|
|
10
|
-
VizChatId,
|
|
11
|
-
VizContent,
|
|
12
|
-
VizFiles,
|
|
13
|
-
} from '@vizhub/viz-types';
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Ensures the chats object exists in the ShareDB document
|
|
17
|
-
*/
|
|
18
|
-
export const ensureChatsExist = (shareDBDoc) => {
|
|
19
|
-
if (!shareDBDoc.data.chats) {
|
|
20
|
-
const op = diff(shareDBDoc.data, {
|
|
21
|
-
...shareDBDoc.data,
|
|
22
|
-
chats: {},
|
|
23
|
-
});
|
|
24
|
-
shareDBDoc.submitOp(op);
|
|
25
|
-
}
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Ensures a specific chat exists in the ShareDB document
|
|
30
|
-
*/
|
|
31
|
-
export const ensureChatExists = (
|
|
32
|
-
shareDBDoc: ShareDBDoc<VizContent>,
|
|
33
|
-
chatId: VizChatId,
|
|
34
|
-
) => {
|
|
35
|
-
if (!shareDBDoc.data.chats[chatId]) {
|
|
36
|
-
const op = diff(shareDBDoc.data, {
|
|
37
|
-
...shareDBDoc.data,
|
|
38
|
-
chats: {
|
|
39
|
-
...shareDBDoc.data.chats,
|
|
40
|
-
[chatId]: {
|
|
41
|
-
id: chatId,
|
|
42
|
-
messages: [],
|
|
43
|
-
createdAt: dateToTimestamp(new Date()),
|
|
44
|
-
updatedAt: dateToTimestamp(new Date()),
|
|
45
|
-
},
|
|
46
|
-
},
|
|
47
|
-
});
|
|
48
|
-
shareDBDoc.submitOp(op);
|
|
49
|
-
}
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Adds a user message to the chat
|
|
54
|
-
* Clears old messages to reflect that each prompt is a self-contained code transformation
|
|
55
|
-
*/
|
|
56
|
-
export const addUserMessage = (
|
|
57
|
-
shareDBDoc: ShareDBDoc<VizContent>,
|
|
58
|
-
chatId: VizChatId,
|
|
59
|
-
content: string,
|
|
60
|
-
) => {
|
|
61
|
-
const userMessage = {
|
|
62
|
-
id: `user-${Date.now()}`,
|
|
63
|
-
role: 'user',
|
|
64
|
-
content: content,
|
|
65
|
-
timestamp: dateToTimestamp(new Date()),
|
|
66
|
-
};
|
|
67
|
-
|
|
68
|
-
const userMessageOp = diff(shareDBDoc.data, {
|
|
69
|
-
...shareDBDoc.data,
|
|
70
|
-
chats: {
|
|
71
|
-
...shareDBDoc.data.chats,
|
|
72
|
-
[chatId]: {
|
|
73
|
-
...shareDBDoc.data.chats[chatId],
|
|
74
|
-
messages: [userMessage], // Replace old messages with just the new user message
|
|
75
|
-
updatedAt: dateToTimestamp(new Date()),
|
|
76
|
-
},
|
|
77
|
-
},
|
|
78
|
-
});
|
|
79
|
-
shareDBDoc.submitOp(userMessageOp);
|
|
80
|
-
|
|
81
|
-
return userMessage;
|
|
82
|
-
};
|
|
83
|
-
|
|
84
|
-
const DEBUG = false;
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* Updates AI status in the chat
|
|
88
|
-
*/
|
|
89
|
-
export const updateAIStatus = (
|
|
90
|
-
shareDBDoc: ShareDBDoc<VizContent>,
|
|
91
|
-
chatId: VizChatId,
|
|
92
|
-
status: string,
|
|
93
|
-
) => {
|
|
94
|
-
DEBUG &&
|
|
95
|
-
console.log(
|
|
96
|
-
`ChatOperations: updateAIStatus called with status: "${status}" for chatId: ${chatId}`,
|
|
97
|
-
);
|
|
98
|
-
|
|
99
|
-
const op = diff(shareDBDoc.data, {
|
|
100
|
-
...shareDBDoc.data,
|
|
101
|
-
chats: {
|
|
102
|
-
...shareDBDoc.data.chats,
|
|
103
|
-
[chatId]: {
|
|
104
|
-
...shareDBDoc.data.chats[chatId],
|
|
105
|
-
aiStatus: status,
|
|
106
|
-
},
|
|
107
|
-
},
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
DEBUG &&
|
|
111
|
-
console.log(
|
|
112
|
-
`ChatOperations: Submitting operation for status update:`,
|
|
113
|
-
op,
|
|
114
|
-
);
|
|
115
|
-
shareDBDoc.submitOp(op);
|
|
116
|
-
DEBUG &&
|
|
117
|
-
console.log(
|
|
118
|
-
`ChatOperations: Status update operation submitted successfully`,
|
|
119
|
-
);
|
|
120
|
-
};
|
|
121
|
-
|
|
122
|
-
/**
|
|
123
|
-
* Updates AI scratchpad content
|
|
124
|
-
*/
|
|
125
|
-
export const updateAIScratchpad = (
|
|
126
|
-
shareDBDoc: ShareDBDoc<VizContent>,
|
|
127
|
-
chatId: VizChatId,
|
|
128
|
-
content: string,
|
|
129
|
-
) => {
|
|
130
|
-
const op = diff(shareDBDoc.data, {
|
|
131
|
-
...shareDBDoc.data,
|
|
132
|
-
chats: {
|
|
133
|
-
...shareDBDoc.data.chats,
|
|
134
|
-
[chatId]: {
|
|
135
|
-
...shareDBDoc.data.chats[chatId],
|
|
136
|
-
aiScratchpad: content,
|
|
137
|
-
},
|
|
138
|
-
},
|
|
139
|
-
});
|
|
140
|
-
|
|
141
|
-
// op is `null` if there are no changes
|
|
142
|
-
// This can happen if the content is the same as before
|
|
143
|
-
// In that case, we don't need to submit an operation
|
|
144
|
-
if (op) {
|
|
145
|
-
shareDBDoc.submitOp(op);
|
|
146
|
-
}
|
|
147
|
-
};
|
|
148
|
-
|
|
149
|
-
/**
|
|
150
|
-
* Clears AI scratchpad and updates status
|
|
151
|
-
*/
|
|
152
|
-
export const clearAIScratchpadAndStatus = (
|
|
153
|
-
shareDBDoc: ShareDBDoc<VizContent>,
|
|
154
|
-
chatId: VizChatId,
|
|
155
|
-
status: string,
|
|
156
|
-
) => {
|
|
157
|
-
const op = diff(shareDBDoc.data, {
|
|
158
|
-
...shareDBDoc.data,
|
|
159
|
-
chats: {
|
|
160
|
-
...shareDBDoc.data.chats,
|
|
161
|
-
[chatId]: {
|
|
162
|
-
...shareDBDoc.data.chats[chatId],
|
|
163
|
-
aiScratchpad: undefined,
|
|
164
|
-
aiStatus: status,
|
|
165
|
-
},
|
|
166
|
-
},
|
|
167
|
-
});
|
|
168
|
-
shareDBDoc.submitOp(op);
|
|
169
|
-
};
|
|
170
|
-
|
|
171
|
-
/**
|
|
172
|
-
* Creates an initial empty AI message for streaming
|
|
173
|
-
*/
|
|
174
|
-
export const createAIMessage = (
|
|
175
|
-
shareDBDoc: ShareDBDoc<VizContent>,
|
|
176
|
-
chatId: VizChatId,
|
|
177
|
-
) => {
|
|
178
|
-
const aiMessage = {
|
|
179
|
-
id: `assistant-${Date.now()}`,
|
|
180
|
-
role: 'assistant',
|
|
181
|
-
content: '',
|
|
182
|
-
timestamp: dateToTimestamp(new Date()),
|
|
183
|
-
};
|
|
184
|
-
|
|
185
|
-
const messageOp = diff(shareDBDoc.data, {
|
|
186
|
-
...shareDBDoc.data,
|
|
187
|
-
chats: {
|
|
188
|
-
...shareDBDoc.data.chats,
|
|
189
|
-
[chatId]: {
|
|
190
|
-
...shareDBDoc.data.chats[chatId],
|
|
191
|
-
messages: [
|
|
192
|
-
...shareDBDoc.data.chats[chatId].messages,
|
|
193
|
-
aiMessage,
|
|
194
|
-
],
|
|
195
|
-
updatedAt: dateToTimestamp(new Date()),
|
|
196
|
-
},
|
|
197
|
-
},
|
|
198
|
-
});
|
|
199
|
-
shareDBDoc.submitOp(messageOp);
|
|
200
|
-
|
|
201
|
-
return aiMessage.id;
|
|
202
|
-
};
|
|
203
|
-
|
|
204
|
-
/**
|
|
205
|
-
* Updates the content of an AI message during streaming
|
|
206
|
-
*/
|
|
207
|
-
export const updateAIMessageContent = (
|
|
208
|
-
shareDBDoc: ShareDBDoc<VizContent>,
|
|
209
|
-
chatId: VizChatId,
|
|
210
|
-
messageId: string,
|
|
211
|
-
content: string,
|
|
212
|
-
) => {
|
|
213
|
-
const chat = shareDBDoc.data.chats[chatId];
|
|
214
|
-
const messageIndex = chat.messages.findIndex(
|
|
215
|
-
(msg) => msg.id === messageId,
|
|
216
|
-
);
|
|
217
|
-
|
|
218
|
-
if (messageIndex === -1) {
|
|
219
|
-
console.warn(
|
|
220
|
-
`AI message with id ${messageId} not found`,
|
|
221
|
-
);
|
|
222
|
-
return;
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
const updatedMessages = [...chat.messages];
|
|
226
|
-
updatedMessages[messageIndex] = {
|
|
227
|
-
...updatedMessages[messageIndex],
|
|
228
|
-
content,
|
|
229
|
-
};
|
|
230
|
-
|
|
231
|
-
const messageOp = diff(shareDBDoc.data, {
|
|
232
|
-
...shareDBDoc.data,
|
|
233
|
-
chats: {
|
|
234
|
-
...shareDBDoc.data.chats,
|
|
235
|
-
[chatId]: {
|
|
236
|
-
...chat,
|
|
237
|
-
messages: updatedMessages,
|
|
238
|
-
updatedAt: dateToTimestamp(new Date()),
|
|
239
|
-
},
|
|
240
|
-
},
|
|
241
|
-
});
|
|
242
|
-
shareDBDoc.submitOp(messageOp);
|
|
243
|
-
};
|
|
244
|
-
|
|
245
|
-
/**
|
|
246
|
-
* Sets the AI status for a chat
|
|
247
|
-
*/
|
|
248
|
-
export const setAIStatus = (
|
|
249
|
-
shareDBDoc: ShareDBDoc<VizContent>,
|
|
250
|
-
chatId: VizChatId,
|
|
251
|
-
status: string | undefined,
|
|
252
|
-
) => {
|
|
253
|
-
const op = diff(shareDBDoc.data, {
|
|
254
|
-
...shareDBDoc.data,
|
|
255
|
-
chats: {
|
|
256
|
-
...shareDBDoc.data.chats,
|
|
257
|
-
[chatId]: {
|
|
258
|
-
...shareDBDoc.data.chats[chatId],
|
|
259
|
-
aiStatus: status,
|
|
260
|
-
updatedAt: dateToTimestamp(new Date()),
|
|
261
|
-
},
|
|
262
|
-
},
|
|
263
|
-
});
|
|
264
|
-
shareDBDoc.submitOp(op);
|
|
265
|
-
};
|
|
266
|
-
|
|
267
|
-
/**
|
|
268
|
-
* Finalizes an AI message by clearing temporary fields
|
|
269
|
-
*/
|
|
270
|
-
export const finalizeAIMessage = (
|
|
271
|
-
shareDBDoc: ShareDBDoc<VizContent>,
|
|
272
|
-
chatId: VizChatId,
|
|
273
|
-
) => {
|
|
274
|
-
const op = diff(shareDBDoc.data, {
|
|
275
|
-
...shareDBDoc.data,
|
|
276
|
-
chats: {
|
|
277
|
-
...shareDBDoc.data.chats,
|
|
278
|
-
[chatId]: {
|
|
279
|
-
...shareDBDoc.data.chats[chatId],
|
|
280
|
-
aiScratchpad: undefined,
|
|
281
|
-
aiStatus: undefined,
|
|
282
|
-
updatedAt: dateToTimestamp(new Date()),
|
|
283
|
-
},
|
|
284
|
-
},
|
|
285
|
-
});
|
|
286
|
-
shareDBDoc.submitOp(op);
|
|
287
|
-
};
|
|
288
|
-
|
|
289
|
-
/**
|
|
290
|
-
* Adds diff data to the most recent AI message
|
|
291
|
-
*/
|
|
292
|
-
export const addDiffToAIMessage = (
|
|
293
|
-
shareDBDoc: ShareDBDoc<VizContent>,
|
|
294
|
-
chatId: VizChatId,
|
|
295
|
-
diffData: any,
|
|
296
|
-
beforeCommitId?: string, // Commit ID before AI changes for VizHub integration
|
|
297
|
-
) => {
|
|
298
|
-
const chat = shareDBDoc.data.chats[chatId];
|
|
299
|
-
const messages = [...chat.messages];
|
|
300
|
-
|
|
301
|
-
// Find the most recent AI message
|
|
302
|
-
const lastAIMessageIndex = messages.length - 1;
|
|
303
|
-
if (
|
|
304
|
-
lastAIMessageIndex >= 0 &&
|
|
305
|
-
messages[lastAIMessageIndex].role === 'assistant'
|
|
306
|
-
) {
|
|
307
|
-
const newMessage = {
|
|
308
|
-
...messages[lastAIMessageIndex],
|
|
309
|
-
diffData,
|
|
310
|
-
...(beforeCommitId && { beforeCommitId }), // Add beforeCommitId for VizHub integration
|
|
311
|
-
};
|
|
312
|
-
// Use type assertion to extend the message with diffData
|
|
313
|
-
(messages[lastAIMessageIndex] as any) = newMessage;
|
|
314
|
-
|
|
315
|
-
const messageOp = diff(shareDBDoc.data, {
|
|
316
|
-
...shareDBDoc.data,
|
|
317
|
-
chats: {
|
|
318
|
-
...shareDBDoc.data.chats,
|
|
319
|
-
[chatId]: {
|
|
320
|
-
...chat,
|
|
321
|
-
messages,
|
|
322
|
-
updatedAt: dateToTimestamp(new Date()),
|
|
323
|
-
},
|
|
324
|
-
},
|
|
325
|
-
});
|
|
326
|
-
|
|
327
|
-
shareDBDoc.submitOp(messageOp);
|
|
328
|
-
}
|
|
329
|
-
};
|
|
330
|
-
|
|
331
|
-
/**
|
|
332
|
-
* Adds an AI response message to the chat (legacy function, kept for compatibility)
|
|
333
|
-
*/
|
|
334
|
-
export const addAIMessage = (
|
|
335
|
-
shareDBDoc: ShareDBDoc<VizContent>,
|
|
336
|
-
chatId: VizChatId,
|
|
337
|
-
content?: string,
|
|
338
|
-
) => {
|
|
339
|
-
const aiResponse = {
|
|
340
|
-
id: Date.now() + 1,
|
|
341
|
-
role: 'assistant',
|
|
342
|
-
content: content || 'AI edit completed successfully.',
|
|
343
|
-
timestamp: dateToTimestamp(new Date()),
|
|
344
|
-
};
|
|
345
|
-
|
|
346
|
-
const messageOp = diff(shareDBDoc.data, {
|
|
347
|
-
...shareDBDoc.data,
|
|
348
|
-
chats: {
|
|
349
|
-
...shareDBDoc.data.chats,
|
|
350
|
-
[chatId]: {
|
|
351
|
-
...shareDBDoc.data.chats[chatId],
|
|
352
|
-
messages: [
|
|
353
|
-
...shareDBDoc.data.chats[chatId].messages,
|
|
354
|
-
aiResponse,
|
|
355
|
-
],
|
|
356
|
-
updatedAt: dateToTimestamp(new Date()),
|
|
357
|
-
aiStatus: undefined,
|
|
358
|
-
},
|
|
359
|
-
},
|
|
360
|
-
});
|
|
361
|
-
shareDBDoc.submitOp(messageOp);
|
|
362
|
-
|
|
363
|
-
return aiResponse;
|
|
364
|
-
};
|
|
365
|
-
|
|
366
|
-
/**
|
|
367
|
-
* Updates files in the ShareDB document
|
|
368
|
-
*/
|
|
369
|
-
export const updateFiles = (
|
|
370
|
-
shareDBDoc: ShareDBDoc<VizContent>,
|
|
371
|
-
files: VizFiles,
|
|
372
|
-
) => {
|
|
373
|
-
const filesOp = diff(shareDBDoc.data, {
|
|
374
|
-
...shareDBDoc.data,
|
|
375
|
-
files,
|
|
376
|
-
});
|
|
377
|
-
DEBUG && console.log('updateFiles op:');
|
|
378
|
-
DEBUG && console.log(JSON.stringify(filesOp, null, 2));
|
|
379
|
-
shareDBDoc.submitOp(filesOp);
|
|
380
|
-
return filesOp;
|
|
381
|
-
};
|
|
382
|
-
|
|
383
|
-
/**
|
|
384
|
-
* Finds a file ID by searching for a matching file name
|
|
385
|
-
*/
|
|
386
|
-
export const resolveFileId = (
|
|
387
|
-
fileName: string,
|
|
388
|
-
shareDBDoc: any,
|
|
389
|
-
) => {
|
|
390
|
-
const files = shareDBDoc.data.files;
|
|
391
|
-
|
|
392
|
-
// Search through all files to find matching name
|
|
393
|
-
for (const [fileId, file] of Object.entries(files)) {
|
|
394
|
-
if ((file as any).name === fileName) {
|
|
395
|
-
return fileId;
|
|
396
|
-
}
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
// If file doesn't exist, return null
|
|
400
|
-
return null;
|
|
401
|
-
};
|
|
402
|
-
|
|
403
|
-
/**
|
|
404
|
-
* Creates a new file with a random ID
|
|
405
|
-
*/
|
|
406
|
-
export const createNewFile = (
|
|
407
|
-
shareDBDoc: ShareDBDoc<VizContent>,
|
|
408
|
-
fileName: string,
|
|
409
|
-
) => {
|
|
410
|
-
// Generate a new random file ID
|
|
411
|
-
const newFileId = randomId();
|
|
412
|
-
|
|
413
|
-
const newState = {
|
|
414
|
-
...shareDBDoc.data,
|
|
415
|
-
files: {
|
|
416
|
-
...shareDBDoc.data.files,
|
|
417
|
-
[newFileId]: {
|
|
418
|
-
name: fileName,
|
|
419
|
-
text: '',
|
|
420
|
-
},
|
|
421
|
-
},
|
|
422
|
-
};
|
|
423
|
-
|
|
424
|
-
const op = diff(shareDBDoc.data, newState);
|
|
425
|
-
shareDBDoc.submitOp(op);
|
|
426
|
-
return newFileId;
|
|
427
|
-
};
|
|
428
|
-
|
|
429
|
-
// ============================================================================
|
|
430
|
-
// Streaming Chat Operations
|
|
431
|
-
// ============================================================================
|
|
432
|
-
|
|
433
|
-
/**
|
|
434
|
-
* Creates a streaming AI message with events array
|
|
435
|
-
*/
|
|
436
|
-
export const createStreamingAIMessage = (
|
|
437
|
-
shareDBDoc: ShareDBDoc<ExtendedVizContent>,
|
|
438
|
-
chatId: VizChatId,
|
|
439
|
-
) => {
|
|
440
|
-
const aiMessage = {
|
|
441
|
-
id: `assistant-${Date.now()}`,
|
|
442
|
-
role: 'assistant',
|
|
443
|
-
content: '',
|
|
444
|
-
timestamp: dateToTimestamp(new Date()),
|
|
445
|
-
streamingEvents: [],
|
|
446
|
-
isProgressive: true,
|
|
447
|
-
};
|
|
448
|
-
|
|
449
|
-
const messageOp = diff(shareDBDoc.data, {
|
|
450
|
-
...shareDBDoc.data,
|
|
451
|
-
chats: {
|
|
452
|
-
...shareDBDoc.data.chats,
|
|
453
|
-
[chatId]: {
|
|
454
|
-
...shareDBDoc.data.chats[chatId],
|
|
455
|
-
messages: [
|
|
456
|
-
...shareDBDoc.data.chats[chatId].messages,
|
|
457
|
-
aiMessage,
|
|
458
|
-
],
|
|
459
|
-
updatedAt: dateToTimestamp(new Date()),
|
|
460
|
-
isStreaming: true,
|
|
461
|
-
},
|
|
462
|
-
},
|
|
463
|
-
});
|
|
464
|
-
shareDBDoc.submitOp(messageOp);
|
|
465
|
-
|
|
466
|
-
return aiMessage.id;
|
|
467
|
-
};
|
|
468
|
-
|
|
469
|
-
/**
|
|
470
|
-
* Adds a streaming event to the most recent AI message
|
|
471
|
-
*/
|
|
472
|
-
export const addStreamingEvent = (
|
|
473
|
-
shareDBDoc: ShareDBDoc<ExtendedVizContent>,
|
|
474
|
-
chatId: VizChatId,
|
|
475
|
-
event: StreamingEvent,
|
|
476
|
-
) => {
|
|
477
|
-
DEBUG &&
|
|
478
|
-
console.log(
|
|
479
|
-
`ChatOperations: Adding streaming event:`,
|
|
480
|
-
event,
|
|
481
|
-
);
|
|
482
|
-
|
|
483
|
-
const chat = shareDBDoc.data.chats[chatId];
|
|
484
|
-
const messages = [...chat.messages];
|
|
485
|
-
const lastMessageIndex = messages.length - 1;
|
|
486
|
-
|
|
487
|
-
if (
|
|
488
|
-
lastMessageIndex >= 0 &&
|
|
489
|
-
messages[lastMessageIndex].role === 'assistant'
|
|
490
|
-
) {
|
|
491
|
-
const lastMessage = messages[lastMessageIndex] as any;
|
|
492
|
-
const updatedEvents = [
|
|
493
|
-
...(lastMessage.streamingEvents || []),
|
|
494
|
-
event,
|
|
495
|
-
];
|
|
496
|
-
|
|
497
|
-
messages[lastMessageIndex] = {
|
|
498
|
-
...lastMessage,
|
|
499
|
-
streamingEvents: updatedEvents,
|
|
500
|
-
};
|
|
501
|
-
|
|
502
|
-
const messageOp = diff(shareDBDoc.data, {
|
|
503
|
-
...shareDBDoc.data,
|
|
504
|
-
chats: {
|
|
505
|
-
...shareDBDoc.data.chats,
|
|
506
|
-
[chatId]: {
|
|
507
|
-
...chat,
|
|
508
|
-
messages,
|
|
509
|
-
updatedAt: dateToTimestamp(new Date()),
|
|
510
|
-
},
|
|
511
|
-
},
|
|
512
|
-
});
|
|
513
|
-
shareDBDoc.submitOp(messageOp);
|
|
514
|
-
}
|
|
515
|
-
};
|
|
516
|
-
|
|
517
|
-
/**
|
|
518
|
-
* Updates streaming status for a chat
|
|
519
|
-
*/
|
|
520
|
-
export const updateStreamingStatus = (
|
|
521
|
-
shareDBDoc: ShareDBDoc<ExtendedVizContent>,
|
|
522
|
-
chatId: VizChatId,
|
|
523
|
-
status: string,
|
|
524
|
-
isStreaming: boolean = true,
|
|
525
|
-
) => {
|
|
526
|
-
DEBUG &&
|
|
527
|
-
console.log(
|
|
528
|
-
`ChatOperations: Updating streaming status: "${status}"`,
|
|
529
|
-
);
|
|
530
|
-
|
|
531
|
-
const op = diff(shareDBDoc.data, {
|
|
532
|
-
...shareDBDoc.data,
|
|
533
|
-
chats: {
|
|
534
|
-
...shareDBDoc.data.chats,
|
|
535
|
-
[chatId]: {
|
|
536
|
-
...shareDBDoc.data.chats[chatId],
|
|
537
|
-
currentStatus: status,
|
|
538
|
-
isStreaming,
|
|
539
|
-
updatedAt: dateToTimestamp(new Date()),
|
|
540
|
-
},
|
|
541
|
-
},
|
|
542
|
-
});
|
|
543
|
-
shareDBDoc.submitOp(op);
|
|
544
|
-
};
|
|
545
|
-
|
|
546
|
-
/**
|
|
547
|
-
* Finalizes streaming message and clears streaming state
|
|
548
|
-
*/
|
|
549
|
-
export const finalizeStreamingMessage = (
|
|
550
|
-
shareDBDoc: ShareDBDoc<ExtendedVizContent>,
|
|
551
|
-
chatId: VizChatId,
|
|
552
|
-
) => {
|
|
553
|
-
DEBUG &&
|
|
554
|
-
console.log(
|
|
555
|
-
`ChatOperations: Finalizing streaming message`,
|
|
556
|
-
);
|
|
557
|
-
|
|
558
|
-
const chat = shareDBDoc.data.chats[chatId];
|
|
559
|
-
const messages = [...chat.messages];
|
|
560
|
-
const lastMessageIndex = messages.length - 1;
|
|
561
|
-
|
|
562
|
-
if (
|
|
563
|
-
lastMessageIndex >= 0 &&
|
|
564
|
-
messages[lastMessageIndex].role === 'assistant'
|
|
565
|
-
) {
|
|
566
|
-
const lastMessage = messages[lastMessageIndex] as any;
|
|
567
|
-
|
|
568
|
-
messages[lastMessageIndex] = {
|
|
569
|
-
...lastMessage,
|
|
570
|
-
isComplete: true,
|
|
571
|
-
};
|
|
572
|
-
|
|
573
|
-
const messageOp = diff(shareDBDoc.data, {
|
|
574
|
-
...shareDBDoc.data,
|
|
575
|
-
chats: {
|
|
576
|
-
...shareDBDoc.data.chats,
|
|
577
|
-
[chatId]: {
|
|
578
|
-
...chat,
|
|
579
|
-
messages,
|
|
580
|
-
currentStatus: 'Done',
|
|
581
|
-
isStreaming: false,
|
|
582
|
-
updatedAt: dateToTimestamp(new Date()),
|
|
583
|
-
},
|
|
584
|
-
},
|
|
585
|
-
});
|
|
586
|
-
shareDBDoc.submitOp(messageOp);
|
|
587
|
-
}
|
|
588
|
-
};
|
|
589
|
-
|
|
590
|
-
// /**
|
|
591
|
-
// * Ensures a file exists, creating it if necessary
|
|
592
|
-
// */
|
|
593
|
-
// export const ensureFileExists = (shareDBDoc, fileName) => {
|
|
594
|
-
// let fileId = resolveFileId(fileName, shareDBDoc);
|
|
595
|
-
|
|
596
|
-
// if (!fileId) {
|
|
597
|
-
// // File doesn't exist, create it
|
|
598
|
-
// fileId = createNewFile(shareDBDoc, fileName);
|
|
599
|
-
// }
|
|
600
|
-
|
|
601
|
-
// return fileId;
|
|
602
|
-
// };
|
|
603
|
-
|
|
604
|
-
// /**
|
|
605
|
-
// * Clears the content of a file
|
|
606
|
-
// */
|
|
607
|
-
// export const clearFileContent = (
|
|
608
|
-
// shareDBDoc: ShareDBDoc<VizContent>,
|
|
609
|
-
// fileId: VizFileId,
|
|
610
|
-
// ) => {
|
|
611
|
-
// const currentFile = shareDBDoc.data.files[fileId];
|
|
612
|
-
|
|
613
|
-
// if (currentFile && currentFile.text) {
|
|
614
|
-
// // Clear the file content
|
|
615
|
-
// const newState = {
|
|
616
|
-
// ...shareDBDoc.data,
|
|
617
|
-
// files: {
|
|
618
|
-
// ...shareDBDoc.data.files,
|
|
619
|
-
// [fileId]: {
|
|
620
|
-
// ...currentFile,
|
|
621
|
-
// text: '',
|
|
622
|
-
// },
|
|
623
|
-
// },
|
|
624
|
-
// };
|
|
625
|
-
|
|
626
|
-
// const op = diff(shareDBDoc.data, newState);
|
|
627
|
-
// shareDBDoc.submitOp(op);
|
|
628
|
-
// }
|
|
629
|
-
// };
|
|
630
|
-
|
|
631
|
-
// /**
|
|
632
|
-
// * Appends a line to a file using OT operations
|
|
633
|
-
// */
|
|
634
|
-
// export const appendLineToFile = (
|
|
635
|
-
// shareDBDoc: ShareDBDoc<VizContent>,
|
|
636
|
-
// fileId: VizFileId,
|
|
637
|
-
// line: string,
|
|
638
|
-
// ) => {
|
|
639
|
-
// const currentFile = shareDBDoc.data.files[fileId];
|
|
640
|
-
// const currentContent = currentFile?.text || '';
|
|
641
|
-
// const newContent = currentContent + line + '\n';
|
|
642
|
-
|
|
643
|
-
// const newDocState = {
|
|
644
|
-
// ...shareDBDoc.data,
|
|
645
|
-
// files: {
|
|
646
|
-
// ...shareDBDoc.data.files,
|
|
647
|
-
// [fileId]: {
|
|
648
|
-
// ...currentFile,
|
|
649
|
-
// text: newContent,
|
|
650
|
-
// },
|
|
651
|
-
// },
|
|
652
|
-
// };
|
|
653
|
-
|
|
654
|
-
// shareDBDoc.submitOp(diff(shareDBDoc.data, newDocState));
|
|
655
|
-
// };
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
import { dateToTimestamp } from '@vizhub/viz-utils';
|
|
2
|
-
import { diff } from '../../ot.js';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Handles errors by adding an error message to the chat and clearing AI state
|
|
6
|
-
*/
|
|
7
|
-
export const handleError = (
|
|
8
|
-
shareDBDoc,
|
|
9
|
-
chatId,
|
|
10
|
-
error,
|
|
11
|
-
res,
|
|
12
|
-
) => {
|
|
13
|
-
console.error('[handleAIChatMessage] error:', error);
|
|
14
|
-
|
|
15
|
-
// Clear scratchpad and add error message on error
|
|
16
|
-
try {
|
|
17
|
-
const errorResponse = {
|
|
18
|
-
id: `error-${Date.now()}`,
|
|
19
|
-
role: 'assistant',
|
|
20
|
-
content:
|
|
21
|
-
'Sorry, I encountered an error while processing your message. Please try again.',
|
|
22
|
-
timestamp: dateToTimestamp(new Date()),
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
const errorOp = diff(shareDBDoc.data, {
|
|
26
|
-
...shareDBDoc.data,
|
|
27
|
-
chats: {
|
|
28
|
-
...shareDBDoc.data.chats,
|
|
29
|
-
[chatId]: {
|
|
30
|
-
...shareDBDoc.data.chats[chatId],
|
|
31
|
-
messages: [
|
|
32
|
-
...shareDBDoc.data.chats[chatId].messages,
|
|
33
|
-
errorResponse,
|
|
34
|
-
],
|
|
35
|
-
aiScratchpad: undefined,
|
|
36
|
-
aiStatus: undefined,
|
|
37
|
-
updatedAt: dateToTimestamp(new Date()),
|
|
38
|
-
},
|
|
39
|
-
},
|
|
40
|
-
});
|
|
41
|
-
shareDBDoc.submitOp(errorOp);
|
|
42
|
-
} catch (opError) {
|
|
43
|
-
console.error(
|
|
44
|
-
'[handleAIChatMessage] error handling error state:',
|
|
45
|
-
opError,
|
|
46
|
-
);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
if (res) {
|
|
50
|
-
res.status(500).json({
|
|
51
|
-
error: 'Internal server error',
|
|
52
|
-
message: error.message,
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Handles errors in background processing (without HTTP response)
|
|
59
|
-
*/
|
|
60
|
-
export const handleBackgroundError = (
|
|
61
|
-
shareDBDoc,
|
|
62
|
-
chatId,
|
|
63
|
-
error,
|
|
64
|
-
) => {
|
|
65
|
-
handleError(shareDBDoc, chatId, error, null);
|
|
66
|
-
};
|