vzcode 2.15.0 → 2.16.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/{index-BpUpNto4.js → index-C2BLPyQP.js} +138 -125
- package/dist/assets/{index-DLm5FQ0E.css → index-DVR90LwF.css} +1 -1
- package/dist/index.html +2 -2
- package/dist/server/aiChatHandler/chatOperations.js +168 -35
- package/dist/server/aiChatHandler/index.js +11 -30
- package/dist/server/aiChatHandler/llmStreaming.js +105 -118
- package/package.json +11 -11
- package/src/client/AIAssist/AIAssistWidget/index.tsx +12 -1
- package/src/client/App/useShareDB.ts +1 -1
- package/src/client/CodeEditor/index.tsx +9 -10
- package/src/client/VZCodeContext/types.ts +3 -1
- package/src/client/VZCodeContext/useVZCodeState.ts +7 -5
- package/src/client/VZRight.tsx +10 -2
- package/src/client/VZSidebar/AIChat/ChatInput.tsx +1 -7
- package/src/client/VZSidebar/AIChat/DiffView.scss +1 -0
- package/src/client/VZSidebar/AIChat/DiffView.tsx +72 -29
- package/src/client/VZSidebar/AIChat/FileEditingIndicator.tsx +81 -0
- package/src/client/VZSidebar/AIChat/IndividualFileDiff.tsx +86 -0
- package/src/client/VZSidebar/AIChat/JumpToLatestButton.tsx +64 -0
- package/src/client/VZSidebar/AIChat/Message.tsx +68 -53
- package/src/client/VZSidebar/AIChat/MessageList.tsx +139 -118
- package/src/client/VZSidebar/AIChat/StreamingMessage.tsx +63 -21
- package/src/client/VZSidebar/AIChat/ThinkingScratchpad.tsx +4 -118
- package/src/client/VZSidebar/AIChat/index.tsx +62 -19
- package/src/client/VZSidebar/AIChat/styles.scss +159 -16
- package/src/client/VZSidebar/Item.tsx +2 -2
- package/src/client/VZSidebar/Search.tsx +13 -6
- package/src/client/VZSidebar/VisualEditor/VisualEditor.tsx +39 -23
- package/src/client/VZSidebar/VisualEditor/utils.ts +1 -1
- package/src/client/VZSidebar/index.tsx +12 -10
- package/src/client/VZSidebar/useDragAndDrop.tsx +225 -214
- package/src/client/featureFlags.ts +3 -0
- package/src/client/hooks/useAutoScroll.ts +329 -0
- package/src/client/tabsSearchParameters.ts +1 -17
- package/src/client/useFileCRUD.ts +5 -2
- package/src/client/useKeyboardShortcuts.ts +7 -0
- package/src/client/useOpenDirectories.ts +2 -1
- package/src/client/usePrettier/index.ts +1 -1
- package/src/client/useURLSync.ts +1 -0
- package/src/client/utils/scrollUtils.ts +170 -0
- package/src/client/vzReducer/searchReducer.ts +6 -3
- package/src/server/aiChatHandler/chatOperations.ts +224 -43
- package/src/server/aiChatHandler/index.ts +8 -48
- package/src/server/aiChatHandler/llmStreaming.ts +149 -170
- package/src/types.ts +81 -1
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import { dateToTimestamp } from '@vizhub/viz-utils';
|
|
2
2
|
import { randomId } from '../../randomId.js';
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
ShareDBDoc,
|
|
5
|
+
StreamingEvent,
|
|
6
|
+
ExtendedVizContent,
|
|
7
|
+
} from '../../types.js';
|
|
4
8
|
import { diff } from '../../ot.js';
|
|
5
9
|
import {
|
|
6
10
|
VizChatId,
|
|
7
11
|
VizContent,
|
|
8
|
-
VizFileId,
|
|
9
12
|
VizFiles,
|
|
10
13
|
} from '@vizhub/viz-types';
|
|
11
14
|
|
|
@@ -80,6 +83,8 @@ export const addUserMessage = (
|
|
|
80
83
|
return userMessage;
|
|
81
84
|
};
|
|
82
85
|
|
|
86
|
+
const DEBUG = false;
|
|
87
|
+
|
|
83
88
|
/**
|
|
84
89
|
* Updates AI status in the chat
|
|
85
90
|
*/
|
|
@@ -88,6 +93,11 @@ export const updateAIStatus = (
|
|
|
88
93
|
chatId: VizChatId,
|
|
89
94
|
status: string,
|
|
90
95
|
) => {
|
|
96
|
+
DEBUG &&
|
|
97
|
+
console.log(
|
|
98
|
+
`ChatOperations: updateAIStatus called with status: "${status}" for chatId: ${chatId}`,
|
|
99
|
+
);
|
|
100
|
+
|
|
91
101
|
const op = diff(shareDBDoc.data, {
|
|
92
102
|
...shareDBDoc.data,
|
|
93
103
|
chats: {
|
|
@@ -98,7 +108,17 @@ export const updateAIStatus = (
|
|
|
98
108
|
},
|
|
99
109
|
},
|
|
100
110
|
});
|
|
111
|
+
|
|
112
|
+
DEBUG &&
|
|
113
|
+
console.log(
|
|
114
|
+
`ChatOperations: Submitting operation for status update:`,
|
|
115
|
+
op,
|
|
116
|
+
);
|
|
101
117
|
shareDBDoc.submitOp(op);
|
|
118
|
+
DEBUG &&
|
|
119
|
+
console.log(
|
|
120
|
+
`ChatOperations: Status update operation submitted successfully`,
|
|
121
|
+
);
|
|
102
122
|
};
|
|
103
123
|
|
|
104
124
|
/**
|
|
@@ -405,69 +425,230 @@ export const createNewFile = (
|
|
|
405
425
|
return newFileId;
|
|
406
426
|
};
|
|
407
427
|
|
|
428
|
+
// ============================================================================
|
|
429
|
+
// Streaming Chat Operations
|
|
430
|
+
// ============================================================================
|
|
431
|
+
|
|
408
432
|
/**
|
|
409
|
-
*
|
|
433
|
+
* Creates a streaming AI message with events array
|
|
410
434
|
*/
|
|
411
|
-
export const
|
|
412
|
-
|
|
435
|
+
export const createStreamingAIMessage = (
|
|
436
|
+
shareDBDoc: ShareDBDoc<ExtendedVizContent>,
|
|
437
|
+
chatId: VizChatId,
|
|
438
|
+
) => {
|
|
439
|
+
const aiMessage = {
|
|
440
|
+
id: `assistant-${Date.now()}`,
|
|
441
|
+
role: 'assistant',
|
|
442
|
+
content: '',
|
|
443
|
+
timestamp: dateToTimestamp(new Date()),
|
|
444
|
+
streamingEvents: [],
|
|
445
|
+
isProgressive: true,
|
|
446
|
+
};
|
|
413
447
|
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
448
|
+
const messageOp = diff(shareDBDoc.data, {
|
|
449
|
+
...shareDBDoc.data,
|
|
450
|
+
chats: {
|
|
451
|
+
...shareDBDoc.data.chats,
|
|
452
|
+
[chatId]: {
|
|
453
|
+
...shareDBDoc.data.chats[chatId],
|
|
454
|
+
messages: [
|
|
455
|
+
...shareDBDoc.data.chats[chatId].messages,
|
|
456
|
+
aiMessage,
|
|
457
|
+
],
|
|
458
|
+
updatedAt: dateToTimestamp(new Date()),
|
|
459
|
+
isStreaming: true,
|
|
460
|
+
},
|
|
461
|
+
},
|
|
462
|
+
});
|
|
463
|
+
shareDBDoc.submitOp(messageOp);
|
|
418
464
|
|
|
419
|
-
return
|
|
465
|
+
return aiMessage.id;
|
|
420
466
|
};
|
|
421
467
|
|
|
422
468
|
/**
|
|
423
|
-
*
|
|
469
|
+
* Adds a streaming event to the most recent AI message
|
|
424
470
|
*/
|
|
425
|
-
export const
|
|
426
|
-
shareDBDoc: ShareDBDoc<
|
|
427
|
-
|
|
471
|
+
export const addStreamingEvent = (
|
|
472
|
+
shareDBDoc: ShareDBDoc<ExtendedVizContent>,
|
|
473
|
+
chatId: VizChatId,
|
|
474
|
+
event: StreamingEvent,
|
|
428
475
|
) => {
|
|
429
|
-
|
|
476
|
+
DEBUG &&
|
|
477
|
+
console.log(
|
|
478
|
+
`ChatOperations: Adding streaming event:`,
|
|
479
|
+
event,
|
|
480
|
+
);
|
|
430
481
|
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
482
|
+
const chat = shareDBDoc.data.chats[chatId];
|
|
483
|
+
const messages = [...chat.messages];
|
|
484
|
+
const lastMessageIndex = messages.length - 1;
|
|
485
|
+
|
|
486
|
+
if (
|
|
487
|
+
lastMessageIndex >= 0 &&
|
|
488
|
+
messages[lastMessageIndex].role === 'assistant'
|
|
489
|
+
) {
|
|
490
|
+
const lastMessage = messages[lastMessageIndex] as any;
|
|
491
|
+
const updatedEvents = [
|
|
492
|
+
...(lastMessage.streamingEvents || []),
|
|
493
|
+
event,
|
|
494
|
+
];
|
|
495
|
+
|
|
496
|
+
messages[lastMessageIndex] = {
|
|
497
|
+
...lastMessage,
|
|
498
|
+
streamingEvents: updatedEvents,
|
|
499
|
+
};
|
|
500
|
+
|
|
501
|
+
const messageOp = diff(shareDBDoc.data, {
|
|
434
502
|
...shareDBDoc.data,
|
|
435
|
-
|
|
436
|
-
...shareDBDoc.data.
|
|
437
|
-
[
|
|
438
|
-
...
|
|
439
|
-
|
|
503
|
+
chats: {
|
|
504
|
+
...shareDBDoc.data.chats,
|
|
505
|
+
[chatId]: {
|
|
506
|
+
...chat,
|
|
507
|
+
messages,
|
|
508
|
+
updatedAt: dateToTimestamp(new Date()),
|
|
440
509
|
},
|
|
441
510
|
},
|
|
442
|
-
};
|
|
443
|
-
|
|
444
|
-
const op = diff(shareDBDoc.data, newState);
|
|
445
|
-
shareDBDoc.submitOp(op);
|
|
511
|
+
});
|
|
512
|
+
shareDBDoc.submitOp(messageOp);
|
|
446
513
|
}
|
|
447
514
|
};
|
|
448
515
|
|
|
449
516
|
/**
|
|
450
|
-
*
|
|
517
|
+
* Updates streaming status for a chat
|
|
451
518
|
*/
|
|
452
|
-
export const
|
|
453
|
-
shareDBDoc: ShareDBDoc<
|
|
454
|
-
|
|
455
|
-
|
|
519
|
+
export const updateStreamingStatus = (
|
|
520
|
+
shareDBDoc: ShareDBDoc<ExtendedVizContent>,
|
|
521
|
+
chatId: VizChatId,
|
|
522
|
+
status: string,
|
|
523
|
+
isStreaming: boolean = true,
|
|
456
524
|
) => {
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
525
|
+
DEBUG &&
|
|
526
|
+
console.log(
|
|
527
|
+
`ChatOperations: Updating streaming status: "${status}"`,
|
|
528
|
+
);
|
|
460
529
|
|
|
461
|
-
const
|
|
530
|
+
const op = diff(shareDBDoc.data, {
|
|
462
531
|
...shareDBDoc.data,
|
|
463
|
-
|
|
464
|
-
...shareDBDoc.data.
|
|
465
|
-
[
|
|
466
|
-
...
|
|
467
|
-
|
|
532
|
+
chats: {
|
|
533
|
+
...shareDBDoc.data.chats,
|
|
534
|
+
[chatId]: {
|
|
535
|
+
...shareDBDoc.data.chats[chatId],
|
|
536
|
+
currentStatus: status,
|
|
537
|
+
isStreaming,
|
|
538
|
+
updatedAt: dateToTimestamp(new Date()),
|
|
468
539
|
},
|
|
469
540
|
},
|
|
470
|
-
};
|
|
541
|
+
});
|
|
542
|
+
shareDBDoc.submitOp(op);
|
|
543
|
+
};
|
|
471
544
|
|
|
472
|
-
|
|
545
|
+
/**
|
|
546
|
+
* Finalizes streaming message and clears streaming state
|
|
547
|
+
*/
|
|
548
|
+
export const finalizeStreamingMessage = (
|
|
549
|
+
shareDBDoc: ShareDBDoc<ExtendedVizContent>,
|
|
550
|
+
chatId: VizChatId,
|
|
551
|
+
) => {
|
|
552
|
+
DEBUG &&
|
|
553
|
+
console.log(
|
|
554
|
+
`ChatOperations: Finalizing streaming message`,
|
|
555
|
+
);
|
|
556
|
+
|
|
557
|
+
const chat = shareDBDoc.data.chats[chatId];
|
|
558
|
+
const messages = [...chat.messages];
|
|
559
|
+
const lastMessageIndex = messages.length - 1;
|
|
560
|
+
|
|
561
|
+
if (
|
|
562
|
+
lastMessageIndex >= 0 &&
|
|
563
|
+
messages[lastMessageIndex].role === 'assistant'
|
|
564
|
+
) {
|
|
565
|
+
const lastMessage = messages[lastMessageIndex] as any;
|
|
566
|
+
|
|
567
|
+
messages[lastMessageIndex] = {
|
|
568
|
+
...lastMessage,
|
|
569
|
+
isComplete: true,
|
|
570
|
+
};
|
|
571
|
+
|
|
572
|
+
const messageOp = diff(shareDBDoc.data, {
|
|
573
|
+
...shareDBDoc.data,
|
|
574
|
+
chats: {
|
|
575
|
+
...shareDBDoc.data.chats,
|
|
576
|
+
[chatId]: {
|
|
577
|
+
...chat,
|
|
578
|
+
messages,
|
|
579
|
+
currentStatus: 'Done',
|
|
580
|
+
isStreaming: false,
|
|
581
|
+
updatedAt: dateToTimestamp(new Date()),
|
|
582
|
+
},
|
|
583
|
+
},
|
|
584
|
+
});
|
|
585
|
+
shareDBDoc.submitOp(messageOp);
|
|
586
|
+
}
|
|
473
587
|
};
|
|
588
|
+
|
|
589
|
+
// /**
|
|
590
|
+
// * Ensures a file exists, creating it if necessary
|
|
591
|
+
// */
|
|
592
|
+
// export const ensureFileExists = (shareDBDoc, fileName) => {
|
|
593
|
+
// let fileId = resolveFileId(fileName, shareDBDoc);
|
|
594
|
+
|
|
595
|
+
// if (!fileId) {
|
|
596
|
+
// // File doesn't exist, create it
|
|
597
|
+
// fileId = createNewFile(shareDBDoc, fileName);
|
|
598
|
+
// }
|
|
599
|
+
|
|
600
|
+
// return fileId;
|
|
601
|
+
// };
|
|
602
|
+
|
|
603
|
+
// /**
|
|
604
|
+
// * Clears the content of a file
|
|
605
|
+
// */
|
|
606
|
+
// export const clearFileContent = (
|
|
607
|
+
// shareDBDoc: ShareDBDoc<VizContent>,
|
|
608
|
+
// fileId: VizFileId,
|
|
609
|
+
// ) => {
|
|
610
|
+
// const currentFile = shareDBDoc.data.files[fileId];
|
|
611
|
+
|
|
612
|
+
// if (currentFile && currentFile.text) {
|
|
613
|
+
// // Clear the file content
|
|
614
|
+
// const newState = {
|
|
615
|
+
// ...shareDBDoc.data,
|
|
616
|
+
// files: {
|
|
617
|
+
// ...shareDBDoc.data.files,
|
|
618
|
+
// [fileId]: {
|
|
619
|
+
// ...currentFile,
|
|
620
|
+
// text: '',
|
|
621
|
+
// },
|
|
622
|
+
// },
|
|
623
|
+
// };
|
|
624
|
+
|
|
625
|
+
// const op = diff(shareDBDoc.data, newState);
|
|
626
|
+
// shareDBDoc.submitOp(op);
|
|
627
|
+
// }
|
|
628
|
+
// };
|
|
629
|
+
|
|
630
|
+
// /**
|
|
631
|
+
// * Appends a line to a file using OT operations
|
|
632
|
+
// */
|
|
633
|
+
// export const appendLineToFile = (
|
|
634
|
+
// shareDBDoc: ShareDBDoc<VizContent>,
|
|
635
|
+
// fileId: VizFileId,
|
|
636
|
+
// line: string,
|
|
637
|
+
// ) => {
|
|
638
|
+
// const currentFile = shareDBDoc.data.files[fileId];
|
|
639
|
+
// const currentContent = currentFile?.text || '';
|
|
640
|
+
// const newContent = currentContent + line + '\n';
|
|
641
|
+
|
|
642
|
+
// const newDocState = {
|
|
643
|
+
// ...shareDBDoc.data,
|
|
644
|
+
// files: {
|
|
645
|
+
// ...shareDBDoc.data.files,
|
|
646
|
+
// [fileId]: {
|
|
647
|
+
// ...currentFile,
|
|
648
|
+
// text: newContent,
|
|
649
|
+
// },
|
|
650
|
+
// },
|
|
651
|
+
// };
|
|
652
|
+
|
|
653
|
+
// shareDBDoc.submitOp(diff(shareDBDoc.data, newDocState));
|
|
654
|
+
// };
|
|
@@ -3,14 +3,10 @@ import {
|
|
|
3
3
|
ensureChatsExist,
|
|
4
4
|
ensureChatExists,
|
|
5
5
|
addUserMessage,
|
|
6
|
-
addDiffToAIMessage,
|
|
7
6
|
setAIStatus,
|
|
8
7
|
} from './chatOperations.js';
|
|
9
8
|
import { createLLMFunction } from './llmStreaming.js';
|
|
10
|
-
import {
|
|
11
|
-
performAIEditing,
|
|
12
|
-
performAIChat,
|
|
13
|
-
} from './aiEditing.js';
|
|
9
|
+
import { performAIEditing } from './aiEditing.js';
|
|
14
10
|
import {
|
|
15
11
|
handleError,
|
|
16
12
|
handleBackgroundError,
|
|
@@ -27,18 +23,16 @@ export const handleAIChatMessage =
|
|
|
27
23
|
({
|
|
28
24
|
shareDBDoc,
|
|
29
25
|
onCreditDeduction,
|
|
30
|
-
getCurrentCommitId,
|
|
31
26
|
model,
|
|
32
27
|
aiRequestOptions,
|
|
33
28
|
}: {
|
|
34
29
|
shareDBDoc: ShareDBDoc<VizContent>;
|
|
35
30
|
onCreditDeduction?: any;
|
|
36
|
-
getCurrentCommitId?: () => string | null;
|
|
37
31
|
model?: string;
|
|
38
32
|
aiRequestOptions?: any;
|
|
39
33
|
}) =>
|
|
40
34
|
async (req: any, res: any) => {
|
|
41
|
-
const { content, chatId
|
|
35
|
+
const { content, chatId } = req.body;
|
|
42
36
|
|
|
43
37
|
if (DEBUG) {
|
|
44
38
|
console.log(
|
|
@@ -67,16 +61,11 @@ export const handleAIChatMessage =
|
|
|
67
61
|
// Return success immediately - AI generation continues in background
|
|
68
62
|
res.status(200).json('success');
|
|
69
63
|
|
|
70
|
-
// Set AI status to indicate generation is starting
|
|
71
|
-
setAIStatus(shareDBDoc, chatId, 'generating');
|
|
72
|
-
|
|
73
64
|
// Continue AI processing in background (don't await)
|
|
74
65
|
processAIRequestAsync({
|
|
75
66
|
shareDBDoc,
|
|
76
67
|
chatId,
|
|
77
68
|
content,
|
|
78
|
-
mode,
|
|
79
|
-
getCurrentCommitId,
|
|
80
69
|
model,
|
|
81
70
|
aiRequestOptions,
|
|
82
71
|
onCreditDeduction,
|
|
@@ -100,8 +89,6 @@ const processAIRequestAsync = async ({
|
|
|
100
89
|
shareDBDoc,
|
|
101
90
|
chatId,
|
|
102
91
|
content,
|
|
103
|
-
mode,
|
|
104
|
-
getCurrentCommitId,
|
|
105
92
|
model,
|
|
106
93
|
aiRequestOptions,
|
|
107
94
|
onCreditDeduction,
|
|
@@ -109,18 +96,11 @@ const processAIRequestAsync = async ({
|
|
|
109
96
|
shareDBDoc: ShareDBDoc<VizContent>;
|
|
110
97
|
chatId: string;
|
|
111
98
|
content: string;
|
|
112
|
-
mode: string;
|
|
113
|
-
getCurrentCommitId?: () => string | null;
|
|
114
99
|
model?: string;
|
|
115
100
|
aiRequestOptions?: any;
|
|
116
101
|
onCreditDeduction?: any;
|
|
117
102
|
}) => {
|
|
118
103
|
try {
|
|
119
|
-
// Capture the current commit ID before making changes (for VizHub integration)
|
|
120
|
-
const beforeCommitId = getCurrentCommitId
|
|
121
|
-
? getCurrentCommitId()
|
|
122
|
-
: null;
|
|
123
|
-
|
|
124
104
|
// Create LLM function for streaming
|
|
125
105
|
const llmFunction = createLLMFunction({
|
|
126
106
|
shareDBDoc,
|
|
@@ -135,32 +115,12 @@ const processAIRequestAsync = async ({
|
|
|
135
115
|
const runCode = createRunCodeFunction(submitOperation);
|
|
136
116
|
|
|
137
117
|
// Perform AI editing or chat based on mode
|
|
138
|
-
const editResult =
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
})
|
|
145
|
-
: await performAIEditing({
|
|
146
|
-
prompt: content,
|
|
147
|
-
shareDBDoc,
|
|
148
|
-
llmFunction,
|
|
149
|
-
runCode,
|
|
150
|
-
});
|
|
151
|
-
|
|
152
|
-
// Add diff data to the AI message if there are changes
|
|
153
|
-
if (
|
|
154
|
-
editResult.diffData &&
|
|
155
|
-
Object.keys(editResult.diffData).length > 0
|
|
156
|
-
) {
|
|
157
|
-
addDiffToAIMessage(
|
|
158
|
-
shareDBDoc,
|
|
159
|
-
chatId,
|
|
160
|
-
editResult.diffData,
|
|
161
|
-
beforeCommitId, // Pass the commit ID before AI changes (for VizHub integration)
|
|
162
|
-
);
|
|
163
|
-
}
|
|
118
|
+
const editResult = await performAIEditing({
|
|
119
|
+
prompt: content,
|
|
120
|
+
shareDBDoc,
|
|
121
|
+
llmFunction,
|
|
122
|
+
runCode,
|
|
123
|
+
});
|
|
164
124
|
|
|
165
125
|
// Handle credit deduction if callback is provided
|
|
166
126
|
if (onCreditDeduction && editResult.generationId) {
|