vzcode 1.58.0 → 1.59.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-C_tGhWXG.js → buildWorker-Dsx6rOdK.js} +1 -1
- package/dist/assets/{index-CtGus8Qk.js → index-BJI4JLx9.js} +83 -83
- package/dist/assets/{index-CE_xP06t.css → index-afP-wJTZ.css} +1 -1
- package/dist/assets/{worker-BrwN8AXx.js → worker-BSzbM0Uo.js} +180 -180
- package/dist/assets/{worker-CekYspLa.js → worker-y5jhqCTR.js} +1 -1
- package/dist/index.html +2 -2
- package/package.json +5 -5
- package/src/client/VZCodeContext.tsx +13 -3
- package/src/client/VZSidebar/AIChat/Message.tsx +2 -0
- package/src/client/VZSidebar/AIChat/MessageList.tsx +0 -2
- package/src/client/VZSidebar/AIChat/ThinkingScratchpad.tsx +121 -2
- package/src/client/VZSidebar/AIChat/index.tsx +1 -14
- package/src/client/VZSidebar/AIChat/styles.scss +16 -0
- package/src/server/aiChatHandler/index.ts +3 -0
- package/src/server/aiChatHandler/llmStreaming.ts +3 -0
package/dist/index.html
CHANGED
|
@@ -20,8 +20,8 @@
|
|
|
20
20
|
href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap"
|
|
21
21
|
rel="stylesheet"
|
|
22
22
|
/>
|
|
23
|
-
<script type="module" crossorigin src="/assets/index-
|
|
24
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
23
|
+
<script type="module" crossorigin src="/assets/index-BJI4JLx9.js"></script>
|
|
24
|
+
<link rel="stylesheet" crossorigin href="/assets/index-afP-wJTZ.css">
|
|
25
25
|
</head>
|
|
26
26
|
<body>
|
|
27
27
|
<div id="root"></div>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vzcode",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.59.0",
|
|
4
4
|
"description": "Multiplayer code editor system",
|
|
5
5
|
"main": "src/index.ts",
|
|
6
6
|
"type": "module",
|
|
@@ -117,8 +117,8 @@
|
|
|
117
117
|
"@codemirror/state": "^6.5.2",
|
|
118
118
|
"@codemirror/theme-one-dark": "^6.1.3",
|
|
119
119
|
"@codemirror/view": "^6.38.1",
|
|
120
|
-
"@langchain/core": "^0.3.
|
|
121
|
-
"@langchain/openai": "^0.6.
|
|
120
|
+
"@langchain/core": "^0.3.67",
|
|
121
|
+
"@langchain/openai": "^0.6.4",
|
|
122
122
|
"@lezer/highlight": "^1.2.1",
|
|
123
123
|
"@livekit/components-react": "^2.9.14",
|
|
124
124
|
"@replit/codemirror-indentation-markers": "^6.5.3",
|
|
@@ -179,7 +179,7 @@
|
|
|
179
179
|
"@tauri-apps/cli": "^2.7.1",
|
|
180
180
|
"@types/react": "^18",
|
|
181
181
|
"@types/react-dom": "^18",
|
|
182
|
-
"@vitejs/plugin-react": "^
|
|
182
|
+
"@vitejs/plugin-react": "^5.0.0",
|
|
183
183
|
"concurrently": "^9.2.0",
|
|
184
184
|
"cross-env": "^10.0.0",
|
|
185
185
|
"eslint": "^9.32.0",
|
|
@@ -189,7 +189,7 @@
|
|
|
189
189
|
"sass": "^1.90.0",
|
|
190
190
|
"ts-node": "^10.9.2",
|
|
191
191
|
"typescript": "^5.9.2",
|
|
192
|
-
"vite": "^7.0
|
|
192
|
+
"vite": "^7.1.0",
|
|
193
193
|
"vitest": "^3.2.4"
|
|
194
194
|
},
|
|
195
195
|
"optionalDependencies": {
|
|
@@ -202,7 +202,10 @@ export type VZCodeContextValue = {
|
|
|
202
202
|
currentChatId: string;
|
|
203
203
|
aiErrorMessage: string | null;
|
|
204
204
|
setAIErrorMessage: (state: string | null) => void;
|
|
205
|
-
handleSendMessage: (
|
|
205
|
+
handleSendMessage: (
|
|
206
|
+
messageToSend?: string,
|
|
207
|
+
options?: Record<string, string>,
|
|
208
|
+
) => void;
|
|
206
209
|
|
|
207
210
|
// Auto-fork functions for VizHub integration
|
|
208
211
|
autoForkAndRetryAI?: (
|
|
@@ -221,6 +224,10 @@ export type VZCodeContextValue = {
|
|
|
221
224
|
messageId: string;
|
|
222
225
|
chatId: string;
|
|
223
226
|
canUndo: boolean;
|
|
227
|
+
handleSendMessage?: (
|
|
228
|
+
messageToSend?: string,
|
|
229
|
+
options?: Record<string, string>,
|
|
230
|
+
) => void;
|
|
224
231
|
}>;
|
|
225
232
|
};
|
|
226
233
|
|
|
@@ -510,7 +517,10 @@ export const VZCodeProvider = ({
|
|
|
510
517
|
>(null);
|
|
511
518
|
|
|
512
519
|
const handleSendMessage = useCallback(
|
|
513
|
-
async (
|
|
520
|
+
async (
|
|
521
|
+
messageToSend?: string,
|
|
522
|
+
options?: Record<string, string>,
|
|
523
|
+
) => {
|
|
514
524
|
DEBUG &&
|
|
515
525
|
console.log(
|
|
516
526
|
'AIChat: handleSendMessage called with:',
|
|
@@ -544,10 +554,10 @@ export const VZCodeProvider = ({
|
|
|
544
554
|
},
|
|
545
555
|
body: JSON.stringify({
|
|
546
556
|
...aiChatOptions,
|
|
547
|
-
vizId: aiChatOptions.vizId,
|
|
548
557
|
content: messageContent.trim(),
|
|
549
558
|
chatId: currentChatId,
|
|
550
559
|
mode: aiChatMode,
|
|
560
|
+
...options,
|
|
551
561
|
}),
|
|
552
562
|
});
|
|
553
563
|
|
|
@@ -40,6 +40,7 @@ const MessageComponent = ({
|
|
|
40
40
|
aiChatUndoEndpoint,
|
|
41
41
|
aiChatOptions = {},
|
|
42
42
|
additionalWidgets,
|
|
43
|
+
handleSendMessage,
|
|
43
44
|
} = useContext(VZCodeContext);
|
|
44
45
|
|
|
45
46
|
// Memoize date formatting to avoid repeated computation
|
|
@@ -117,6 +118,7 @@ const MessageComponent = ({
|
|
|
117
118
|
messageId: id,
|
|
118
119
|
chatId: chatId,
|
|
119
120
|
canUndo: canUndo,
|
|
121
|
+
handleSendMessage,
|
|
120
122
|
})}
|
|
121
123
|
{!additionalWidgets && canUndo && beforeFiles && (
|
|
122
124
|
<div className="undo-button-container">
|
|
@@ -12,13 +12,11 @@ import { VizChatMessage } from '@vizhub/viz-types';
|
|
|
12
12
|
|
|
13
13
|
const MessageListComponent = ({
|
|
14
14
|
messages,
|
|
15
|
-
aiStatus,
|
|
16
15
|
isLoading,
|
|
17
16
|
chatId, // Add chatId prop
|
|
18
17
|
aiScratchpad, // Add aiScratchpad prop
|
|
19
18
|
}: {
|
|
20
19
|
messages: VizChatMessage[];
|
|
21
|
-
aiStatus?: string;
|
|
22
20
|
isLoading: boolean;
|
|
23
21
|
chatId?: string; // Add chatId to the type
|
|
24
22
|
aiScratchpad?: string; // Add aiScratchpad to the type
|
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
memo,
|
|
3
|
+
useRef,
|
|
4
|
+
useEffect,
|
|
5
|
+
useCallback,
|
|
6
|
+
useState,
|
|
7
|
+
} from 'react';
|
|
2
8
|
import Markdown from 'react-markdown';
|
|
3
9
|
import remarkGfm from 'remark-gfm';
|
|
4
10
|
|
|
@@ -11,6 +17,115 @@ const ThinkingScratchpadComponent = ({
|
|
|
11
17
|
content,
|
|
12
18
|
isVisible,
|
|
13
19
|
}: ThinkingScratchpadProps) => {
|
|
20
|
+
const contentRef = useRef<HTMLDivElement>(null);
|
|
21
|
+
const [isUserScrolled, setIsUserScrolled] =
|
|
22
|
+
useState(false);
|
|
23
|
+
const [autoScrollEnabled, setAutoScrollEnabled] =
|
|
24
|
+
useState(true);
|
|
25
|
+
const scrollTimeoutRef =
|
|
26
|
+
useRef<ReturnType<typeof setTimeout>>();
|
|
27
|
+
|
|
28
|
+
// Check if the user is scrolled to the bottom
|
|
29
|
+
const isScrolledToBottom = useCallback(() => {
|
|
30
|
+
const container = contentRef.current;
|
|
31
|
+
if (!container) return true;
|
|
32
|
+
|
|
33
|
+
const threshold = 10; // Allow 10px tolerance for "at bottom"
|
|
34
|
+
const { scrollTop, scrollHeight, clientHeight } =
|
|
35
|
+
container;
|
|
36
|
+
return (
|
|
37
|
+
scrollHeight - scrollTop - clientHeight < threshold
|
|
38
|
+
);
|
|
39
|
+
}, []);
|
|
40
|
+
|
|
41
|
+
// Smooth scroll to bottom
|
|
42
|
+
const scrollToBottom = useCallback(() => {
|
|
43
|
+
if (!autoScrollEnabled) return;
|
|
44
|
+
|
|
45
|
+
const container = contentRef.current;
|
|
46
|
+
if (container) {
|
|
47
|
+
container.scrollTo({
|
|
48
|
+
top: container.scrollHeight,
|
|
49
|
+
behavior: 'smooth',
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
}, [autoScrollEnabled]);
|
|
53
|
+
|
|
54
|
+
// Handle scroll events to detect user manual scrolling
|
|
55
|
+
const handleScroll = useCallback(() => {
|
|
56
|
+
const container = contentRef.current;
|
|
57
|
+
if (!container) return;
|
|
58
|
+
|
|
59
|
+
const isAtBottom = isScrolledToBottom();
|
|
60
|
+
|
|
61
|
+
// Clear any existing timeout
|
|
62
|
+
if (scrollTimeoutRef.current) {
|
|
63
|
+
clearTimeout(scrollTimeoutRef.current);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// If user scrolled up from bottom, disable auto-scroll
|
|
67
|
+
if (!isAtBottom && !isUserScrolled) {
|
|
68
|
+
setIsUserScrolled(true);
|
|
69
|
+
setAutoScrollEnabled(false);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// If user scrolled back to bottom, re-enable auto-scroll after a brief delay
|
|
73
|
+
if (isAtBottom && isUserScrolled) {
|
|
74
|
+
scrollTimeoutRef.current = setTimeout(() => {
|
|
75
|
+
setIsUserScrolled(false);
|
|
76
|
+
setAutoScrollEnabled(true);
|
|
77
|
+
}, 300); // 300ms delay to prevent flickering
|
|
78
|
+
}
|
|
79
|
+
}, [isUserScrolled, isScrolledToBottom]);
|
|
80
|
+
|
|
81
|
+
// Auto-scroll when content changes, but only if auto-scroll is enabled
|
|
82
|
+
useEffect(() => {
|
|
83
|
+
if (
|
|
84
|
+
autoScrollEnabled &&
|
|
85
|
+
!isUserScrolled &&
|
|
86
|
+
isVisible &&
|
|
87
|
+
content
|
|
88
|
+
) {
|
|
89
|
+
// Use a short debounce to prevent multiple scroll calls during rapid updates
|
|
90
|
+
if (scrollTimeoutRef.current) {
|
|
91
|
+
clearTimeout(scrollTimeoutRef.current);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
scrollTimeoutRef.current = setTimeout(() => {
|
|
95
|
+
scrollToBottom();
|
|
96
|
+
}, 50); // 50ms debounce
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return () => {
|
|
100
|
+
if (scrollTimeoutRef.current) {
|
|
101
|
+
clearTimeout(scrollTimeoutRef.current);
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
}, [
|
|
105
|
+
content,
|
|
106
|
+
autoScrollEnabled,
|
|
107
|
+
isUserScrolled,
|
|
108
|
+
isVisible,
|
|
109
|
+
scrollToBottom,
|
|
110
|
+
]);
|
|
111
|
+
|
|
112
|
+
// Clean up timeout on unmount
|
|
113
|
+
useEffect(() => {
|
|
114
|
+
return () => {
|
|
115
|
+
if (scrollTimeoutRef.current) {
|
|
116
|
+
clearTimeout(scrollTimeoutRef.current);
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
}, []);
|
|
120
|
+
|
|
121
|
+
// Reset scroll state when component becomes visible
|
|
122
|
+
useEffect(() => {
|
|
123
|
+
if (isVisible) {
|
|
124
|
+
setIsUserScrolled(false);
|
|
125
|
+
setAutoScrollEnabled(true);
|
|
126
|
+
}
|
|
127
|
+
}, [isVisible]);
|
|
128
|
+
|
|
14
129
|
if (!isVisible || !content) {
|
|
15
130
|
return null;
|
|
16
131
|
}
|
|
@@ -23,7 +138,11 @@ const ThinkingScratchpadComponent = ({
|
|
|
23
138
|
AI is thinking...
|
|
24
139
|
</span>
|
|
25
140
|
</div>
|
|
26
|
-
<div
|
|
141
|
+
<div
|
|
142
|
+
className="thinking-scratchpad-content"
|
|
143
|
+
ref={contentRef}
|
|
144
|
+
onScroll={handleScroll}
|
|
145
|
+
>
|
|
27
146
|
<Markdown remarkPlugins={[remarkGfm]}>
|
|
28
147
|
{content}
|
|
29
148
|
</Markdown>
|
|
@@ -1,18 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
useContext,
|
|
3
|
-
useState,
|
|
4
|
-
useCallback,
|
|
5
|
-
useMemo,
|
|
6
|
-
useEffect,
|
|
7
|
-
} from 'react';
|
|
1
|
+
import { useContext, useMemo, useEffect } from 'react';
|
|
8
2
|
import { VZCodeContext } from '../../VZCodeContext';
|
|
9
|
-
import { v4 as uuidv4 } from 'uuid';
|
|
10
3
|
import { MessageList } from './MessageList';
|
|
11
4
|
import { ChatInput } from './ChatInput';
|
|
12
5
|
import './styles.scss';
|
|
13
6
|
|
|
14
|
-
const defaultAIChatEndpoint = '/api/ai-chat/';
|
|
15
|
-
|
|
16
7
|
const DEBUG = false;
|
|
17
8
|
|
|
18
9
|
const showSuggestedRequests = true;
|
|
@@ -21,20 +12,16 @@ export const AIChat = () => {
|
|
|
21
12
|
const {
|
|
22
13
|
aiChatFocused,
|
|
23
14
|
content,
|
|
24
|
-
aiChatEndpoint = defaultAIChatEndpoint,
|
|
25
|
-
aiChatOptions = {},
|
|
26
15
|
aiChatMode,
|
|
27
16
|
aiChatMessage,
|
|
28
17
|
isLoading,
|
|
29
18
|
currentChatId,
|
|
30
19
|
aiErrorMessage,
|
|
31
20
|
setAIChatMode,
|
|
32
|
-
autoForkAndRetryAI,
|
|
33
21
|
clearStoredAIPrompt,
|
|
34
22
|
getStoredAIPrompt,
|
|
35
23
|
setAIChatMessage,
|
|
36
24
|
handleSendMessage,
|
|
37
|
-
setIsLoading,
|
|
38
25
|
setAIErrorMessage,
|
|
39
26
|
} = useContext(VZCodeContext);
|
|
40
27
|
|
|
@@ -182,6 +182,7 @@
|
|
|
182
182
|
.undo-button-container {
|
|
183
183
|
display: flex;
|
|
184
184
|
justify-content: flex-end;
|
|
185
|
+
gap: 8px;
|
|
185
186
|
margin-top: 16px;
|
|
186
187
|
}
|
|
187
188
|
|
|
@@ -560,6 +561,21 @@
|
|
|
560
561
|
max-height: 200px;
|
|
561
562
|
overflow-y: auto;
|
|
562
563
|
background: var(--vh-color-neutral-02);
|
|
564
|
+
scroll-behavior: smooth;
|
|
565
|
+
|
|
566
|
+
&::-webkit-scrollbar {
|
|
567
|
+
width: 6px;
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
&::-webkit-scrollbar-track {
|
|
571
|
+
background: var(--vh-color-neutral-02);
|
|
572
|
+
border-radius: 3px;
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
&::-webkit-scrollbar-thumb {
|
|
576
|
+
background: var(--vh-color-neutral-04);
|
|
577
|
+
border-radius: 3px;
|
|
578
|
+
}
|
|
563
579
|
|
|
564
580
|
// Style markdown content in thinking scratchpad
|
|
565
581
|
p {
|
|
@@ -24,11 +24,13 @@ export const handleAIChatMessage =
|
|
|
24
24
|
createAIEditLocalPresence,
|
|
25
25
|
onCreditDeduction,
|
|
26
26
|
getCurrentCommitId,
|
|
27
|
+
model,
|
|
27
28
|
}: {
|
|
28
29
|
shareDBDoc: ShareDBDoc<VizContent>;
|
|
29
30
|
createAIEditLocalPresence: () => any;
|
|
30
31
|
onCreditDeduction?: any;
|
|
31
32
|
getCurrentCommitId?: () => string | null;
|
|
33
|
+
model?: string;
|
|
32
34
|
}) =>
|
|
33
35
|
async (req: any, res: any) => {
|
|
34
36
|
const { content, chatId, mode = 'edit' } = req.body;
|
|
@@ -67,6 +69,7 @@ export const handleAIChatMessage =
|
|
|
67
69
|
shareDBDoc,
|
|
68
70
|
createAIEditLocalPresence,
|
|
69
71
|
chatId,
|
|
72
|
+
model,
|
|
70
73
|
});
|
|
71
74
|
|
|
72
75
|
// Create server-side runCode function using shareDBDoc
|
|
@@ -49,11 +49,13 @@ export const createLLMFunction = ({
|
|
|
49
49
|
// When false, reasoning tokens are not requested from the API
|
|
50
50
|
// and reasoning content is not processed in the streaming response.
|
|
51
51
|
enableReasoningTokens = false,
|
|
52
|
+
model,
|
|
52
53
|
}: {
|
|
53
54
|
shareDBDoc: ShareDBDoc<VizContent>;
|
|
54
55
|
createAIEditLocalPresence: () => any;
|
|
55
56
|
chatId: VizChatId;
|
|
56
57
|
enableReasoningTokens?: boolean;
|
|
58
|
+
model?: string;
|
|
57
59
|
}) => {
|
|
58
60
|
return async (fullPrompt: string) => {
|
|
59
61
|
const localPresence = enableStreamingEditing
|
|
@@ -200,6 +202,7 @@ export const createLLMFunction = ({
|
|
|
200
202
|
|
|
201
203
|
// Stream the response with reasoning tokens
|
|
202
204
|
const modelName =
|
|
205
|
+
model ||
|
|
203
206
|
process.env.VIZHUB_EDIT_WITH_AI_MODEL_NAME ||
|
|
204
207
|
'anthropic/claude-3.5-sonnet';
|
|
205
208
|
|