vzcode 1.40.0 → 1.41.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/bindings_wasm_bg-BQfW5T_2.wasm +0 -0
- package/dist/assets/buildWorker-B-vXZ9gA.js +579 -0
- package/dist/assets/index-DPAeYEiH.js +329 -0
- package/dist/index.html +1 -1
- package/package.json +13 -12
- package/src/client/CodeEditor/getOrCreateEditor.ts +2 -5
- package/src/client/CodeEditor/index.tsx +1 -1
- package/src/client/VZRight.tsx +67 -6
- package/src/client/VZSidebar/AIChat/ChatInput.tsx +17 -5
- package/src/client/VZSidebar/AIChat/Message.tsx +21 -8
- package/src/client/VZSidebar/AIChat/MessageList.tsx +11 -4
- package/src/client/VZSidebar/AIChat/StreamingMessage.tsx +6 -1
- package/src/client/VZSidebar/AIChat/TypingIndicator.tsx +7 -1
- package/src/client/VZSidebar/AIChat/index.tsx +22 -7
- package/src/client/buildWorker.ts +3 -0
- package/src/server/aiChatHandler/llmStreaming.ts +8 -5
- package/dist/assets/index-ubSLcdJf.js +0 -327
package/dist/index.html
CHANGED
|
@@ -20,7 +20,7 @@
|
|
|
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-
|
|
23
|
+
<script type="module" crossorigin src="/assets/index-DPAeYEiH.js"></script>
|
|
24
24
|
<link rel="stylesheet" crossorigin href="/assets/index-DKLiE98a.css">
|
|
25
25
|
</head>
|
|
26
26
|
<body>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vzcode",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.41.0",
|
|
4
4
|
"description": "Multiplayer code editor system",
|
|
5
5
|
"main": "src/index.ts",
|
|
6
6
|
"type": "module",
|
|
@@ -115,7 +115,7 @@
|
|
|
115
115
|
"@codemirror/theme-one-dark": "^6.1.3",
|
|
116
116
|
"@codemirror/view": "^6.38.1",
|
|
117
117
|
"@langchain/core": "^0.3.66",
|
|
118
|
-
"@langchain/openai": "^0.6.
|
|
118
|
+
"@langchain/openai": "^0.6.3",
|
|
119
119
|
"@lezer/highlight": "^1.2.1",
|
|
120
120
|
"@livekit/components-react": "^2.9.14",
|
|
121
121
|
"@replit/codemirror-indentation-markers": "^6.5.3",
|
|
@@ -134,33 +134,34 @@
|
|
|
134
134
|
"@uiw/codemirror-theme-xcode": "^4.24.1",
|
|
135
135
|
"@uiw/codemirror-themes": "^4.24.1",
|
|
136
136
|
"@valtown/codemirror-ts": "^2.3.1",
|
|
137
|
+
"@vizhub/runtime": "^4.1.0",
|
|
137
138
|
"@vizhub/viz-types": "^0.3.0",
|
|
138
139
|
"@vizhub/viz-utils": "^1.3.0",
|
|
139
140
|
"body-parser": "^2.2.0",
|
|
140
141
|
"codemirror": "^6.0.2",
|
|
141
142
|
"codemirror-copilot": "^0.0.7",
|
|
142
|
-
"codemirror-ot": "^4.
|
|
143
|
+
"codemirror-ot": "^4.6.0",
|
|
143
144
|
"color-hash": "^2.0.2",
|
|
144
145
|
"comlink": "^4.4.2",
|
|
145
146
|
"d3-array": "^3.2.4",
|
|
146
147
|
"diff-match-patch": "^1.0.5",
|
|
147
|
-
"dotenv": "^17.2.
|
|
148
|
-
"editcodewithai": "^2.
|
|
148
|
+
"dotenv": "^17.2.1",
|
|
149
|
+
"editcodewithai": "^2.3.0",
|
|
149
150
|
"eslint-linter-browserify": "^9.31.0",
|
|
150
151
|
"express": "^5.1.0",
|
|
151
152
|
"ignore": "^7.0.5",
|
|
152
153
|
"json0-ot-diff": "^1.1.2",
|
|
153
154
|
"livekit-server-sdk": "^2.13.1",
|
|
154
|
-
"llm-code-format": "^
|
|
155
|
+
"llm-code-format": "^3.0.0",
|
|
155
156
|
"ngrok": "^5.0.0-beta.2",
|
|
156
|
-
"npm": "^11.
|
|
157
|
+
"npm": "^11.5.1",
|
|
157
158
|
"open": "^10.2.0",
|
|
158
159
|
"prettier-plugin-svelte": "^3.4.0",
|
|
159
160
|
"react": "^18",
|
|
160
161
|
"react-bootstrap": "^2.10.10",
|
|
161
162
|
"react-dom": "^18",
|
|
162
163
|
"react-markdown": "^10.1.0",
|
|
163
|
-
"react-router-dom": "^7.7.
|
|
164
|
+
"react-router-dom": "^7.7.1",
|
|
164
165
|
"remark-gfm": "^4.0.1",
|
|
165
166
|
"sharedb": "^5.2.2",
|
|
166
167
|
"sharedb-client-browser": "^5.2.2",
|
|
@@ -169,20 +170,20 @@
|
|
|
169
170
|
"ws": "^8.18.3"
|
|
170
171
|
},
|
|
171
172
|
"devDependencies": {
|
|
172
|
-
"@eslint/js": "^9.
|
|
173
|
+
"@eslint/js": "^9.32.0",
|
|
173
174
|
"@types/react": "^18",
|
|
174
175
|
"@types/react-dom": "^18",
|
|
175
176
|
"@vitejs/plugin-react": "^4.7.0",
|
|
176
177
|
"concurrently": "^9.2.0",
|
|
177
178
|
"cross-env": "^7.0.3",
|
|
178
|
-
"eslint": "^9.
|
|
179
|
+
"eslint": "^9.32.0",
|
|
179
180
|
"globals": "^16.3.0",
|
|
180
|
-
"npm-check-updates": "^18.0.
|
|
181
|
+
"npm-check-updates": "^18.0.2",
|
|
181
182
|
"prettier": "^3.6.2",
|
|
182
183
|
"sass": "^1.89.2",
|
|
183
184
|
"ts-node": "^10.9.2",
|
|
184
185
|
"typescript": "^5.8.3",
|
|
185
|
-
"vite": "^7.0.
|
|
186
|
+
"vite": "^7.0.6",
|
|
186
187
|
"vitest": "^3.2.4"
|
|
187
188
|
},
|
|
188
189
|
"optionalDependencies": {
|
|
@@ -166,7 +166,6 @@ export const getOrCreateEditor = async ({
|
|
|
166
166
|
paneId = 'root',
|
|
167
167
|
fileId,
|
|
168
168
|
shareDBDoc,
|
|
169
|
-
content,
|
|
170
169
|
filesPath,
|
|
171
170
|
localPresence,
|
|
172
171
|
docPresence,
|
|
@@ -194,10 +193,7 @@ export const getOrCreateEditor = async ({
|
|
|
194
193
|
// This can be `undefined` in the case where we are
|
|
195
194
|
// viewing files read-only, in which case multiplayer
|
|
196
195
|
// editing is not enabled.
|
|
197
|
-
shareDBDoc: ShareDBDoc<VizContent
|
|
198
|
-
|
|
199
|
-
// The initial content to present.
|
|
200
|
-
content: VizContent;
|
|
196
|
+
shareDBDoc: ShareDBDoc<VizContent>;
|
|
201
197
|
|
|
202
198
|
filesPath: string[];
|
|
203
199
|
localPresence: any;
|
|
@@ -233,6 +229,7 @@ export const getOrCreateEditor = async ({
|
|
|
233
229
|
// Compute `text` and `fileExtension` from the ShareDB document.
|
|
234
230
|
const textPath = [...filesPath, fileId, 'text'];
|
|
235
231
|
const namePath = [...filesPath, fileId, 'name'];
|
|
232
|
+
const content = shareDBDoc.data;
|
|
236
233
|
const text = getAtPath(content, textPath);
|
|
237
234
|
const name = getAtPath(content, namePath);
|
|
238
235
|
|
|
@@ -91,13 +91,13 @@ export const CodeEditor = ({
|
|
|
91
91
|
// Get the editor corresponding to the active file.
|
|
92
92
|
// Looks in `editorCache` first, and if not found, creates a new editor.
|
|
93
93
|
useEffect(() => {
|
|
94
|
+
if (!shareDBDoc) return;
|
|
94
95
|
let isMounted = true;
|
|
95
96
|
|
|
96
97
|
const initEditor = async () => {
|
|
97
98
|
const editor = await getOrCreateEditor({
|
|
98
99
|
fileId: activePane.activeFileId,
|
|
99
100
|
shareDBDoc,
|
|
100
|
-
content,
|
|
101
101
|
filesPath,
|
|
102
102
|
localPresence,
|
|
103
103
|
docPresence,
|
package/src/client/VZRight.tsx
CHANGED
|
@@ -1,14 +1,75 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
import { useContext, useEffect, useMemo } from 'react';
|
|
2
|
+
import {
|
|
3
|
+
createRuntime,
|
|
4
|
+
VizHubRuntime,
|
|
5
|
+
} from '@vizhub/runtime';
|
|
6
|
+
import BuildWorker from './buildWorker?worker';
|
|
7
|
+
import { VZCodeContext } from './VZCodeContext';
|
|
8
|
+
import { vizFilesToFileCollection } from '@vizhub/viz-utils';
|
|
9
|
+
|
|
10
|
+
const enableIframe = true;
|
|
11
|
+
|
|
12
|
+
// Singleton runtime instance
|
|
13
|
+
// TODO use refs, and cleanup on unmount
|
|
14
|
+
let runtime: VizHubRuntime = null;
|
|
15
|
+
let isFirstRun = true;
|
|
6
16
|
|
|
7
17
|
export const VZRight = () => {
|
|
18
|
+
// Get access to the current files.
|
|
19
|
+
const { content } = useContext(VZCodeContext);
|
|
20
|
+
|
|
21
|
+
const files = useMemo(
|
|
22
|
+
() =>
|
|
23
|
+
content
|
|
24
|
+
? vizFilesToFileCollection(content.files)
|
|
25
|
+
: null,
|
|
26
|
+
[content?.files],
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
const isInteracting = content?.isInteracting || false;
|
|
30
|
+
|
|
31
|
+
useEffect(() => {
|
|
32
|
+
if (!files) return;
|
|
33
|
+
|
|
34
|
+
// Initialize the runtime only once
|
|
35
|
+
if (!runtime) {
|
|
36
|
+
const worker = new BuildWorker();
|
|
37
|
+
const iframe = document.getElementById(
|
|
38
|
+
'viz-iframe',
|
|
39
|
+
) as HTMLIFrameElement;
|
|
40
|
+
runtime = createRuntime({
|
|
41
|
+
iframe,
|
|
42
|
+
worker,
|
|
43
|
+
setBuildErrorMessage: (error) => {
|
|
44
|
+
if (error) {
|
|
45
|
+
console.error('Build error:', error);
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Run code in the iframe
|
|
52
|
+
if (isFirstRun || isInteracting) {
|
|
53
|
+
runtime.run({
|
|
54
|
+
files,
|
|
55
|
+
enableHotReloading: true,
|
|
56
|
+
enableSourcemap: true,
|
|
57
|
+
vizId: 'example-viz',
|
|
58
|
+
});
|
|
59
|
+
isFirstRun = false;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// TODO use refs, and cleanup on unmount
|
|
63
|
+
// return () => {
|
|
64
|
+
// runtime.cleanup();
|
|
65
|
+
// worker.terminate();
|
|
66
|
+
// };
|
|
67
|
+
}, [files, isInteracting]);
|
|
68
|
+
|
|
8
69
|
return (
|
|
9
70
|
<div className="right">
|
|
10
71
|
{enableIframe ? (
|
|
11
|
-
<iframe
|
|
72
|
+
<iframe id="viz-iframe"></iframe>
|
|
12
73
|
) : null}
|
|
13
74
|
</div>
|
|
14
75
|
);
|
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
useRef,
|
|
3
|
+
useEffect,
|
|
4
|
+
useCallback,
|
|
5
|
+
memo,
|
|
6
|
+
} from 'react';
|
|
2
7
|
import { Form, Button } from '../../bootstrap';
|
|
3
8
|
|
|
4
9
|
interface ChatInputProps {
|
|
@@ -9,7 +14,7 @@ interface ChatInputProps {
|
|
|
9
14
|
focused: boolean;
|
|
10
15
|
}
|
|
11
16
|
|
|
12
|
-
|
|
17
|
+
const ChatInputComponent = ({
|
|
13
18
|
message,
|
|
14
19
|
setMessage,
|
|
15
20
|
onSendMessage,
|
|
@@ -35,6 +40,13 @@ export const ChatInput = ({
|
|
|
35
40
|
[onSendMessage],
|
|
36
41
|
);
|
|
37
42
|
|
|
43
|
+
const handleChange = useCallback(
|
|
44
|
+
(event: React.ChangeEvent<HTMLTextAreaElement>) => {
|
|
45
|
+
setMessage(event.target.value);
|
|
46
|
+
},
|
|
47
|
+
[setMessage],
|
|
48
|
+
);
|
|
49
|
+
|
|
38
50
|
return (
|
|
39
51
|
<div className="ai-chat-input-container">
|
|
40
52
|
<Form.Group className="ai-chat-input-group">
|
|
@@ -42,9 +54,7 @@ export const ChatInput = ({
|
|
|
42
54
|
as="textarea"
|
|
43
55
|
rows={2}
|
|
44
56
|
value={message}
|
|
45
|
-
onChange={
|
|
46
|
-
setMessage(event.target.value)
|
|
47
|
-
}
|
|
57
|
+
onChange={handleChange}
|
|
48
58
|
onKeyDown={handleKeyDown}
|
|
49
59
|
ref={inputRef}
|
|
50
60
|
placeholder="Describe what you'd like me to change in your code..."
|
|
@@ -63,3 +73,5 @@ export const ChatInput = ({
|
|
|
63
73
|
</div>
|
|
64
74
|
);
|
|
65
75
|
};
|
|
76
|
+
|
|
77
|
+
export const ChatInput = memo(ChatInputComponent);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { timestampToDate } from '@vizhub/viz-utils';
|
|
2
2
|
import Markdown from 'react-markdown';
|
|
3
3
|
import remarkGfm from 'remark-gfm';
|
|
4
|
+
import { useMemo, memo } from 'react';
|
|
4
5
|
|
|
5
6
|
interface MessageProps {
|
|
6
7
|
id: string;
|
|
@@ -10,27 +11,39 @@ interface MessageProps {
|
|
|
10
11
|
isStreaming?: boolean;
|
|
11
12
|
}
|
|
12
13
|
|
|
13
|
-
|
|
14
|
+
const MessageComponent = ({
|
|
14
15
|
role,
|
|
15
16
|
content,
|
|
16
17
|
timestamp,
|
|
17
18
|
isStreaming,
|
|
18
19
|
}: MessageProps) => {
|
|
20
|
+
// Memoize date formatting to avoid repeated computation
|
|
21
|
+
const formattedTime = useMemo(() => {
|
|
22
|
+
return timestampToDate(timestamp).toLocaleTimeString(
|
|
23
|
+
[],
|
|
24
|
+
{
|
|
25
|
+
hour: '2-digit',
|
|
26
|
+
minute: '2-digit',
|
|
27
|
+
},
|
|
28
|
+
);
|
|
29
|
+
}, [timestamp]);
|
|
30
|
+
|
|
31
|
+
// Memoize the className string to avoid recreation
|
|
32
|
+
const messageClassName = useMemo(() => {
|
|
33
|
+
return `ai-chat-message ${role}${isStreaming ? ' streaming' : ''}`;
|
|
34
|
+
}, [role, isStreaming]);
|
|
19
35
|
return (
|
|
20
|
-
<div
|
|
21
|
-
className={`ai-chat-message ${role}${isStreaming ? ' streaming' : ''}`}
|
|
22
|
-
>
|
|
36
|
+
<div className={messageClassName}>
|
|
23
37
|
<div className="ai-chat-message-content">
|
|
24
38
|
<Markdown remarkPlugins={[remarkGfm]}>
|
|
25
39
|
{content}
|
|
26
40
|
</Markdown>
|
|
27
41
|
</div>
|
|
28
42
|
<div className="ai-chat-message-time">
|
|
29
|
-
{
|
|
30
|
-
hour: '2-digit',
|
|
31
|
-
minute: '2-digit',
|
|
32
|
-
})}
|
|
43
|
+
{formattedTime}
|
|
33
44
|
</div>
|
|
34
45
|
</div>
|
|
35
46
|
);
|
|
36
47
|
};
|
|
48
|
+
|
|
49
|
+
export const Message = memo(MessageComponent);
|
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
useRef,
|
|
3
|
+
useEffect,
|
|
4
|
+
useCallback,
|
|
5
|
+
memo,
|
|
6
|
+
} from 'react';
|
|
2
7
|
import { Message } from './Message';
|
|
3
8
|
import { StreamingMessage } from './StreamingMessage';
|
|
4
9
|
import { TypingIndicator } from './TypingIndicator';
|
|
@@ -17,7 +22,7 @@ interface MessageListProps {
|
|
|
17
22
|
isLoading: boolean;
|
|
18
23
|
}
|
|
19
24
|
|
|
20
|
-
|
|
25
|
+
const MessageListComponent = ({
|
|
21
26
|
messages,
|
|
22
27
|
aiScratchpad,
|
|
23
28
|
aiStatus,
|
|
@@ -25,11 +30,11 @@ export const MessageList = ({
|
|
|
25
30
|
}: MessageListProps) => {
|
|
26
31
|
const messagesEndRef = useRef<HTMLDivElement>(null);
|
|
27
32
|
|
|
28
|
-
const scrollToBottom = () => {
|
|
33
|
+
const scrollToBottom = useCallback(() => {
|
|
29
34
|
messagesEndRef.current?.scrollIntoView({
|
|
30
35
|
behavior: 'smooth',
|
|
31
36
|
});
|
|
32
|
-
};
|
|
37
|
+
}, []);
|
|
33
38
|
|
|
34
39
|
useEffect(() => {
|
|
35
40
|
scrollToBottom();
|
|
@@ -60,3 +65,5 @@ export const MessageList = ({
|
|
|
60
65
|
</div>
|
|
61
66
|
);
|
|
62
67
|
};
|
|
68
|
+
|
|
69
|
+
export const MessageList = memo(MessageListComponent);
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import Markdown from 'react-markdown';
|
|
2
2
|
import remarkGfm from 'remark-gfm';
|
|
3
|
+
import { memo } from 'react';
|
|
3
4
|
|
|
4
5
|
interface StreamingMessageProps {
|
|
5
6
|
content: string;
|
|
6
7
|
status?: string;
|
|
7
8
|
}
|
|
8
9
|
|
|
9
|
-
|
|
10
|
+
const StreamingMessageComponent = ({
|
|
10
11
|
content,
|
|
11
12
|
status,
|
|
12
13
|
}: StreamingMessageProps) => {
|
|
@@ -23,3 +24,7 @@ export const StreamingMessage = ({
|
|
|
23
24
|
</div>
|
|
24
25
|
);
|
|
25
26
|
};
|
|
27
|
+
|
|
28
|
+
export const StreamingMessage = memo(
|
|
29
|
+
StreamingMessageComponent,
|
|
30
|
+
);
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
import { memo } from 'react';
|
|
2
|
+
|
|
3
|
+
const TypingIndicatorComponent = () => {
|
|
2
4
|
return (
|
|
3
5
|
<div className="ai-chat-message assistant">
|
|
4
6
|
<div className="ai-chat-message-content">
|
|
@@ -11,3 +13,7 @@ export const TypingIndicator = () => {
|
|
|
11
13
|
</div>
|
|
12
14
|
);
|
|
13
15
|
};
|
|
16
|
+
|
|
17
|
+
export const TypingIndicator = memo(
|
|
18
|
+
TypingIndicatorComponent,
|
|
19
|
+
);
|
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
useContext,
|
|
3
|
+
useState,
|
|
4
|
+
useCallback,
|
|
5
|
+
useMemo,
|
|
6
|
+
} from 'react';
|
|
2
7
|
import { VZCodeContext } from '../../VZCodeContext';
|
|
3
8
|
import { v4 as uuidv4 } from 'uuid';
|
|
4
9
|
import { MessageList } from './MessageList';
|
|
@@ -25,11 +30,15 @@ export const AIChat = () => {
|
|
|
25
30
|
const aiScratchpad = currentChat?.aiScratchpad;
|
|
26
31
|
const aiStatus = currentChat?.aiStatus;
|
|
27
32
|
|
|
28
|
-
// Transform messages to ensure they have required id field
|
|
29
|
-
const messages =
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
+
// Transform messages to ensure they have required id field - memoized to avoid recreation
|
|
34
|
+
const messages = useMemo(
|
|
35
|
+
() =>
|
|
36
|
+
rawMessages.map((msg, index) => ({
|
|
37
|
+
...msg,
|
|
38
|
+
id: msg.id || `msg-${index}`,
|
|
39
|
+
})),
|
|
40
|
+
[rawMessages],
|
|
41
|
+
);
|
|
33
42
|
|
|
34
43
|
const handleSendMessage = useCallback(async () => {
|
|
35
44
|
if (!message.trim() || isLoading) return;
|
|
@@ -66,7 +75,13 @@ export const AIChat = () => {
|
|
|
66
75
|
} finally {
|
|
67
76
|
setIsLoading(false);
|
|
68
77
|
}
|
|
69
|
-
}, [
|
|
78
|
+
}, [
|
|
79
|
+
message,
|
|
80
|
+
isLoading,
|
|
81
|
+
aiChatEndpoint,
|
|
82
|
+
aiChatOptions,
|
|
83
|
+
currentChatId,
|
|
84
|
+
]);
|
|
70
85
|
|
|
71
86
|
return (
|
|
72
87
|
<div className="ai-chat-container">
|
|
@@ -69,7 +69,10 @@ export const createLLMFunction = ({
|
|
|
69
69
|
|
|
70
70
|
// Define callbacks for streaming parser
|
|
71
71
|
const callbacks = {
|
|
72
|
-
onFileNameChange: (
|
|
72
|
+
onFileNameChange: async (
|
|
73
|
+
fileName: string,
|
|
74
|
+
format: string,
|
|
75
|
+
) => {
|
|
73
76
|
DEBUG &&
|
|
74
77
|
console.log(
|
|
75
78
|
`File changed to: ${fileName} (${format})`,
|
|
@@ -111,7 +114,7 @@ export const createLLMFunction = ({
|
|
|
111
114
|
'Editing ' + fileName,
|
|
112
115
|
);
|
|
113
116
|
},
|
|
114
|
-
onCodeLine: (line) => {
|
|
117
|
+
onCodeLine: async (line: string) => {
|
|
115
118
|
DEBUG && console.log(`Code line: ${line}`);
|
|
116
119
|
|
|
117
120
|
if (currentEditingFileId) {
|
|
@@ -154,7 +157,7 @@ export const createLLMFunction = ({
|
|
|
154
157
|
}
|
|
155
158
|
}
|
|
156
159
|
},
|
|
157
|
-
onNonCodeLine: (line) => {
|
|
160
|
+
onNonCodeLine: async (line: string) => {
|
|
158
161
|
// We want to report a file edited only if the line is not empty,
|
|
159
162
|
// because sometimes the LLMs leave a newline between the file name
|
|
160
163
|
// declaration and th
|
|
@@ -176,14 +179,14 @@ export const createLLMFunction = ({
|
|
|
176
179
|
if (chunk.content) {
|
|
177
180
|
const chunkContent = String(chunk.content);
|
|
178
181
|
chunks.push(chunkContent);
|
|
179
|
-
parser.processChunk(chunkContent);
|
|
182
|
+
await parser.processChunk(chunkContent);
|
|
180
183
|
}
|
|
181
184
|
|
|
182
185
|
if (!generationId && chunk.lc_kwargs?.id) {
|
|
183
186
|
generationId = chunk.lc_kwargs.id;
|
|
184
187
|
}
|
|
185
188
|
}
|
|
186
|
-
parser.flushRemaining();
|
|
189
|
+
await parser.flushRemaining();
|
|
187
190
|
reportFileEdited();
|
|
188
191
|
updateAIStatus(shareDBDoc, chatId, 'Done editing.');
|
|
189
192
|
updateAIScratchpad(shareDBDoc, chatId, fullContent);
|