vzcode 1.60.0 → 1.61.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/bootstrap-icons-BeopsB42.woff +0 -0
- package/dist/assets/bootstrap-icons-mSm7cUeB.woff2 +0 -0
- package/dist/assets/{index-DMIy-XE4.css → index-Br76WttW.css} +5 -1
- package/dist/assets/{index-S-R8oY72.js → index-EWyCE9d7.js} +148 -148
- package/dist/index.html +2 -2
- package/package.json +7 -6
- package/src/client/Icons/AdjustmentSVG.tsx +19 -0
- package/src/client/Icons/index.tsx +1 -0
- package/src/client/VZCodeContext/types.ts +12 -1
- package/src/client/VZCodeContext/useVZCodeState.ts +81 -5
- package/src/client/VZRight.tsx +6 -3
- package/src/client/VZSidebar/AIChat/ChatInput.tsx +45 -2
- package/src/client/VZSidebar/AIChat/MessageList.tsx +2 -0
- package/src/client/VZSidebar/AIChat/index.tsx +12 -0
- package/src/client/VZSidebar/EmptyState.tsx +11 -0
- package/src/client/VZSidebar/VisualEditor.tsx +284 -0
- package/src/client/VZSidebar/index.tsx +64 -0
- package/src/client/VZSidebar/styles.scss +213 -1
- package/src/client/bootstrap.ts +3 -0
- package/src/client/useActions.ts +12 -0
- package/src/client/vzReducer/closeTabReducer.test.ts +33 -21
- package/src/client/vzReducer/createInitialState.ts +1 -0
- package/src/client/vzReducer/index.ts +9 -0
- package/src/client/vzReducer/searchReducer.test.ts +1 -1
- package/src/client/vzReducer/visualEditorReducer.ts +9 -0
- package/src/server/aiChatHandler/chatOperations.ts +22 -0
- package/src/server/aiChatHandler/errorHandling.ts +17 -4
- package/src/server/aiChatHandler/index.ts +131 -67
- package/src/server/aiChatHandler/llmStreaming.ts +76 -27
- package/src/types.ts +12 -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-EWyCE9d7.js"></script>
|
|
24
|
+
<link rel="stylesheet" crossorigin href="/assets/index-Br76WttW.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.61.0",
|
|
4
4
|
"description": "Multiplayer code editor system",
|
|
5
5
|
"main": "src/index.ts",
|
|
6
6
|
"type": "module",
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
],
|
|
12
12
|
"scripts": {
|
|
13
13
|
"test": "vitest run",
|
|
14
|
-
"test-interactive": "cd test/sampleDirectories/
|
|
14
|
+
"test-interactive": "cd test/sampleDirectories/visualEditor && node --import \"data:text/javascript,import { register } from 'node:module'; import { pathToFileURL } from 'node:url'; register('ts-node/esm', pathToFileURL('./'));\" ../../../src/server/index.ts",
|
|
15
15
|
"prettier": "prettier {*.*,**/*.*} --write",
|
|
16
16
|
"typecheck": "tsc --noEmit",
|
|
17
17
|
"dev": "cross-env EDITOR_PORT=5173 concurrently \"npm run test-interactive\" \"vite\"",
|
|
@@ -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.68",
|
|
121
|
+
"@langchain/openai": "^0.6.7",
|
|
122
122
|
"@lezer/highlight": "^1.2.1",
|
|
123
123
|
"@livekit/components-react": "^2.9.14",
|
|
124
124
|
"@replit/codemirror-indentation-markers": "^6.5.3",
|
|
@@ -141,6 +141,7 @@
|
|
|
141
141
|
"@vizhub/viz-types": "^0.4.0",
|
|
142
142
|
"@vizhub/viz-utils": "^1.4.0",
|
|
143
143
|
"body-parser": "^2.2.0",
|
|
144
|
+
"bootstrap-icons": "^1.13.1",
|
|
144
145
|
"codemirror": "^6.0.2",
|
|
145
146
|
"codemirror-copilot": "^0.0.7",
|
|
146
147
|
"codemirror-ot": "^5.0.0",
|
|
@@ -166,7 +167,7 @@
|
|
|
166
167
|
"react-bootstrap": "^2.10.10",
|
|
167
168
|
"react-dom": "^18",
|
|
168
169
|
"react-markdown": "^10.1.0",
|
|
169
|
-
"react-router-dom": "^7.
|
|
170
|
+
"react-router-dom": "^7.8.0",
|
|
170
171
|
"remark-gfm": "^4.0.1",
|
|
171
172
|
"sharedb": "^5.2.2",
|
|
172
173
|
"sharedb-client-browser": "^5.2.2",
|
|
@@ -189,7 +190,7 @@
|
|
|
189
190
|
"sass": "^1.90.0",
|
|
190
191
|
"ts-node": "^10.9.2",
|
|
191
192
|
"typescript": "^5.9.2",
|
|
192
|
-
"vite": "^7.1.
|
|
193
|
+
"vite": "^7.1.1",
|
|
193
194
|
"vitest": "^3.2.4"
|
|
194
195
|
},
|
|
195
196
|
"optionalDependencies": {
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
//From Hero Icons
|
|
2
|
+
export const AdjustmentSVG = () => (
|
|
3
|
+
<svg
|
|
4
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
5
|
+
fill="none"
|
|
6
|
+
viewBox="0 0 24 24"
|
|
7
|
+
strokeWidth={1.5}
|
|
8
|
+
stroke="currentColor"
|
|
9
|
+
className="size-6"
|
|
10
|
+
width={32}
|
|
11
|
+
height={32}
|
|
12
|
+
>
|
|
13
|
+
<path
|
|
14
|
+
strokeLinecap="round"
|
|
15
|
+
strokeLinejoin="round"
|
|
16
|
+
d="M10.5 6h9.75M10.5 6a1.5 1.5 0 1 1-3 0m3 0a1.5 1.5 0 1 0-3 0M3.75 6H7.5m3 12h9.75m-9.75 0a1.5 1.5 0 0 1-3 0m3 0a1.5 1.5 0 0 0-3 0m-3.75 0H7.5m9-6h3.75m-3.75 0a1.5 1.5 0 0 1-3 0m3 0a1.5 1.5 0 0 0-3 0m-9.75 0h9.75"
|
|
17
|
+
/>
|
|
18
|
+
</svg>
|
|
19
|
+
);
|
|
@@ -90,6 +90,11 @@ export type VZCodeContextValue = {
|
|
|
90
90
|
setIsSearchOpen: (isSearchOpen: boolean) => void;
|
|
91
91
|
setSearch: (pattern: string) => void;
|
|
92
92
|
|
|
93
|
+
isVisualEditorOpen: boolean;
|
|
94
|
+
setIsVisualEditorOpen: (
|
|
95
|
+
isVisualEditorOpen: boolean,
|
|
96
|
+
) => void;
|
|
97
|
+
|
|
93
98
|
isAIChatOpen: boolean;
|
|
94
99
|
setIsAIChatOpen: (isAIChatOpen: boolean) => void;
|
|
95
100
|
aiChatFocused: boolean;
|
|
@@ -137,6 +142,8 @@ export type VZCodeContextValue = {
|
|
|
137
142
|
|
|
138
143
|
codeEditorRef: React.RefObject<HTMLDivElement>;
|
|
139
144
|
|
|
145
|
+
iframeRef: React.MutableRefObject<HTMLIFrameElement>;
|
|
146
|
+
|
|
140
147
|
connected: boolean;
|
|
141
148
|
pending: boolean;
|
|
142
149
|
|
|
@@ -164,7 +171,6 @@ export type VZCodeContextValue = {
|
|
|
164
171
|
aiChatMessage: string;
|
|
165
172
|
setAIChatMessage: (message: string) => void;
|
|
166
173
|
isLoading: boolean;
|
|
167
|
-
setIsLoading: (state: boolean) => void;
|
|
168
174
|
currentChatId: string;
|
|
169
175
|
aiErrorMessage: string | null;
|
|
170
176
|
setAIErrorMessage: (state: string | null) => void;
|
|
@@ -173,6 +179,11 @@ export type VZCodeContextValue = {
|
|
|
173
179
|
options?: Record<string, string>,
|
|
174
180
|
) => void;
|
|
175
181
|
|
|
182
|
+
// Message history navigation
|
|
183
|
+
navigateMessageHistoryUp: () => void;
|
|
184
|
+
navigateMessageHistoryDown: () => void;
|
|
185
|
+
resetMessageHistoryNavigation: () => void;
|
|
186
|
+
|
|
176
187
|
// Auto-fork functions for VizHub integration
|
|
177
188
|
autoForkAndRetryAI?: (
|
|
178
189
|
prompt: string,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
useCallback,
|
|
3
|
+
useMemo,
|
|
3
4
|
useReducer,
|
|
4
5
|
useRef,
|
|
5
6
|
useState,
|
|
@@ -75,6 +76,8 @@ export const useVZCodeState = ({
|
|
|
75
76
|
|
|
76
77
|
const codeEditorRef = useRef(null);
|
|
77
78
|
|
|
79
|
+
const iframeRef = useRef(null);
|
|
80
|
+
|
|
78
81
|
// The error message shows errors in order of priority:
|
|
79
82
|
// * `runtimeError` - errors from runtime execution, highest priority
|
|
80
83
|
// * `prettierError` - errors from Prettier, client-side only
|
|
@@ -104,6 +107,7 @@ export const useVZCodeState = ({
|
|
|
104
107
|
theme,
|
|
105
108
|
search,
|
|
106
109
|
isSearchOpen,
|
|
110
|
+
isVisualEditorOpen,
|
|
107
111
|
isAIChatOpen,
|
|
108
112
|
aiChatFocused,
|
|
109
113
|
isSettingsOpen,
|
|
@@ -136,6 +140,7 @@ export const useVZCodeState = ({
|
|
|
136
140
|
setSearchLineVisibility,
|
|
137
141
|
setSearchFocusedIndex,
|
|
138
142
|
toggleSearchFocused,
|
|
143
|
+
setIsVisualEditorOpen,
|
|
139
144
|
setIsAIChatOpen,
|
|
140
145
|
toggleAIChatFocused,
|
|
141
146
|
setAIChatMode,
|
|
@@ -262,12 +267,72 @@ export const useVZCodeState = ({
|
|
|
262
267
|
|
|
263
268
|
const DEBUG = false;
|
|
264
269
|
|
|
265
|
-
|
|
270
|
+
// Compute isLoading based on the current chat's aiStatus
|
|
266
271
|
const [currentChatId] = useState(() => uuidv4());
|
|
272
|
+
const currentChat = content?.chats?.[currentChatId];
|
|
273
|
+
const isLoading = currentChat?.aiStatus === 'generating';
|
|
274
|
+
|
|
275
|
+
// Message history for up/down arrow navigation - using ShareDB document data
|
|
276
|
+
const messageHistory = useMemo(() => {
|
|
277
|
+
if (!currentChat?.messages) return [];
|
|
278
|
+
// Extract user messages in chronological order for history navigation
|
|
279
|
+
return currentChat.messages
|
|
280
|
+
.filter((msg) => msg.role === 'user')
|
|
281
|
+
.map((msg) => msg.content);
|
|
282
|
+
}, [currentChat?.messages]);
|
|
283
|
+
|
|
284
|
+
const [historyIndex, setHistoryIndex] = useState(-1);
|
|
285
|
+
const [currentDraft, setCurrentDraft] = useState('');
|
|
286
|
+
|
|
267
287
|
const [aiErrorMessage, setAIErrorMessage] = useState<
|
|
268
288
|
string | null
|
|
269
289
|
>(null);
|
|
270
290
|
|
|
291
|
+
// Message history navigation functions
|
|
292
|
+
const navigateMessageHistoryUp = useCallback(() => {
|
|
293
|
+
if (messageHistory.length === 0) return;
|
|
294
|
+
|
|
295
|
+
// If we're not navigating history, save current draft
|
|
296
|
+
if (historyIndex === -1) {
|
|
297
|
+
setCurrentDraft(aiChatMessage);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
const newIndex =
|
|
301
|
+
historyIndex < messageHistory.length - 1
|
|
302
|
+
? historyIndex + 1
|
|
303
|
+
: historyIndex;
|
|
304
|
+
setHistoryIndex(newIndex);
|
|
305
|
+
setAIChatMessage(
|
|
306
|
+
messageHistory[messageHistory.length - 1 - newIndex],
|
|
307
|
+
);
|
|
308
|
+
}, [messageHistory, historyIndex, aiChatMessage]);
|
|
309
|
+
|
|
310
|
+
const navigateMessageHistoryDown = useCallback(() => {
|
|
311
|
+
if (historyIndex === -1) return;
|
|
312
|
+
|
|
313
|
+
const newIndex = historyIndex - 1;
|
|
314
|
+
if (newIndex === -1) {
|
|
315
|
+
// Return to draft
|
|
316
|
+
setHistoryIndex(-1);
|
|
317
|
+
setAIChatMessage(currentDraft);
|
|
318
|
+
setCurrentDraft('');
|
|
319
|
+
} else {
|
|
320
|
+
setHistoryIndex(newIndex);
|
|
321
|
+
setAIChatMessage(
|
|
322
|
+
messageHistory[
|
|
323
|
+
messageHistory.length - 1 - newIndex
|
|
324
|
+
],
|
|
325
|
+
);
|
|
326
|
+
}
|
|
327
|
+
}, [messageHistory, historyIndex, currentDraft]);
|
|
328
|
+
|
|
329
|
+
const resetMessageHistoryNavigation = useCallback(() => {
|
|
330
|
+
if (historyIndex !== -1) {
|
|
331
|
+
setHistoryIndex(-1);
|
|
332
|
+
setCurrentDraft('');
|
|
333
|
+
}
|
|
334
|
+
}, [historyIndex]);
|
|
335
|
+
|
|
271
336
|
const handleSendMessage = useCallback(
|
|
272
337
|
async (
|
|
273
338
|
messageToSend?: string,
|
|
@@ -293,7 +358,11 @@ export const useVZCodeState = ({
|
|
|
293
358
|
|
|
294
359
|
const currentPrompt = aiChatMessage.trim();
|
|
295
360
|
setAIChatMessage('');
|
|
296
|
-
|
|
361
|
+
|
|
362
|
+
// Reset history navigation when sending a message
|
|
363
|
+
setHistoryIndex(-1);
|
|
364
|
+
setCurrentDraft('');
|
|
365
|
+
|
|
297
366
|
setAIErrorMessage(null); // Clear any previous errors
|
|
298
367
|
|
|
299
368
|
// Call backend endpoint for AI response
|
|
@@ -356,13 +425,12 @@ export const useVZCodeState = ({
|
|
|
356
425
|
}
|
|
357
426
|
|
|
358
427
|
// The backend handles all ShareDB operations for successful responses
|
|
428
|
+
// The loading state is now managed via ShareDB aiStatus
|
|
359
429
|
} catch (error) {
|
|
360
430
|
console.error('Error getting AI response:', error);
|
|
361
431
|
setAIErrorMessage(
|
|
362
432
|
'Failed to send message. Please try again.',
|
|
363
433
|
);
|
|
364
|
-
} finally {
|
|
365
|
-
setIsLoading(false);
|
|
366
434
|
}
|
|
367
435
|
},
|
|
368
436
|
[
|
|
@@ -415,6 +483,9 @@ export const useVZCodeState = ({
|
|
|
415
483
|
setSearchFocusedIndex,
|
|
416
484
|
toggleSearchFocused,
|
|
417
485
|
|
|
486
|
+
isVisualEditorOpen,
|
|
487
|
+
setIsVisualEditorOpen,
|
|
488
|
+
|
|
418
489
|
isAIChatOpen,
|
|
419
490
|
setIsAIChatOpen,
|
|
420
491
|
aiChatFocused,
|
|
@@ -463,6 +534,7 @@ export const useVZCodeState = ({
|
|
|
463
534
|
runCodeRef,
|
|
464
535
|
sidebarRef,
|
|
465
536
|
codeEditorRef,
|
|
537
|
+
iframeRef,
|
|
466
538
|
|
|
467
539
|
connected,
|
|
468
540
|
pending,
|
|
@@ -487,12 +559,16 @@ export const useVZCodeState = ({
|
|
|
487
559
|
aiChatMessage,
|
|
488
560
|
setAIChatMessage,
|
|
489
561
|
isLoading,
|
|
490
|
-
setIsLoading,
|
|
491
562
|
currentChatId,
|
|
492
563
|
aiErrorMessage,
|
|
493
564
|
setAIErrorMessage,
|
|
494
565
|
handleSendMessage,
|
|
495
566
|
|
|
567
|
+
// Message history navigation
|
|
568
|
+
navigateMessageHistoryUp,
|
|
569
|
+
navigateMessageHistoryDown,
|
|
570
|
+
resetMessageHistoryNavigation,
|
|
571
|
+
|
|
496
572
|
// Auto-fork functions for VizHub integration
|
|
497
573
|
autoForkAndRetryAI,
|
|
498
574
|
clearStoredAIPrompt,
|
package/src/client/VZRight.tsx
CHANGED
|
@@ -23,7 +23,6 @@ type ExtendedVizContent = VizContent & {
|
|
|
23
23
|
const enableIframe = true;
|
|
24
24
|
|
|
25
25
|
export const VZRight = () => {
|
|
26
|
-
const iframeRef = useRef<HTMLIFrameElement>(null);
|
|
27
26
|
const runtimeRef = useRef<VizHubRuntime | null>(null);
|
|
28
27
|
const isFirstRunRef = useRef(true);
|
|
29
28
|
const lastRunIdRef = useRef<string | undefined>(
|
|
@@ -31,8 +30,12 @@ export const VZRight = () => {
|
|
|
31
30
|
);
|
|
32
31
|
|
|
33
32
|
// Get access to the current files.
|
|
34
|
-
const {
|
|
35
|
-
|
|
33
|
+
const {
|
|
34
|
+
content,
|
|
35
|
+
handleRuntimeError,
|
|
36
|
+
clearRuntimeError,
|
|
37
|
+
iframeRef,
|
|
38
|
+
} = useContext(VZCodeContext);
|
|
36
39
|
|
|
37
40
|
const files = useMemo(
|
|
38
41
|
() =>
|
|
@@ -20,6 +20,9 @@ interface ChatInputProps {
|
|
|
20
20
|
focused: boolean;
|
|
21
21
|
aiChatMode: 'ask' | 'edit';
|
|
22
22
|
setAIChatMode: (mode: 'ask' | 'edit') => void;
|
|
23
|
+
navigateMessageHistoryUp: () => void;
|
|
24
|
+
navigateMessageHistoryDown: () => void;
|
|
25
|
+
resetMessageHistoryNavigation: () => void;
|
|
23
26
|
}
|
|
24
27
|
|
|
25
28
|
const ChatInputComponent = ({
|
|
@@ -30,6 +33,9 @@ const ChatInputComponent = ({
|
|
|
30
33
|
focused,
|
|
31
34
|
aiChatMode,
|
|
32
35
|
setAIChatMode,
|
|
36
|
+
navigateMessageHistoryUp,
|
|
37
|
+
navigateMessageHistoryDown,
|
|
38
|
+
resetMessageHistoryNavigation,
|
|
33
39
|
}: ChatInputProps) => {
|
|
34
40
|
const inputRef = useRef<HTMLTextAreaElement>(null);
|
|
35
41
|
|
|
@@ -45,9 +51,44 @@ const ChatInputComponent = ({
|
|
|
45
51
|
if (event.key === 'Enter' && !event.shiftKey) {
|
|
46
52
|
event.preventDefault();
|
|
47
53
|
onSendMessage();
|
|
54
|
+
} else if (event.key === 'ArrowUp') {
|
|
55
|
+
// Only navigate history if cursor is at the beginning of the first line
|
|
56
|
+
const textarea =
|
|
57
|
+
event.target as HTMLTextAreaElement;
|
|
58
|
+
const { selectionStart, value } = textarea;
|
|
59
|
+
const lines = value
|
|
60
|
+
.substring(0, selectionStart)
|
|
61
|
+
.split('\n');
|
|
62
|
+
|
|
63
|
+
// Check if we're at the beginning of the first line
|
|
64
|
+
if (lines.length === 1 && selectionStart === 0) {
|
|
65
|
+
event.preventDefault();
|
|
66
|
+
navigateMessageHistoryUp();
|
|
67
|
+
}
|
|
68
|
+
} else if (event.key === 'ArrowDown') {
|
|
69
|
+
// Only navigate history if cursor is at the end of the last line
|
|
70
|
+
const textarea =
|
|
71
|
+
event.target as HTMLTextAreaElement;
|
|
72
|
+
const { selectionStart, value } = textarea;
|
|
73
|
+
const remainingText =
|
|
74
|
+
value.substring(selectionStart);
|
|
75
|
+
const remainingLines = remainingText.split('\n');
|
|
76
|
+
|
|
77
|
+
// Check if we're at the end of the last line
|
|
78
|
+
if (
|
|
79
|
+
remainingLines.length === 1 &&
|
|
80
|
+
remainingLines[0] === ''
|
|
81
|
+
) {
|
|
82
|
+
event.preventDefault();
|
|
83
|
+
navigateMessageHistoryDown();
|
|
84
|
+
}
|
|
48
85
|
}
|
|
49
86
|
},
|
|
50
|
-
[
|
|
87
|
+
[
|
|
88
|
+
onSendMessage,
|
|
89
|
+
navigateMessageHistoryUp,
|
|
90
|
+
navigateMessageHistoryDown,
|
|
91
|
+
],
|
|
51
92
|
);
|
|
52
93
|
|
|
53
94
|
const handleSendClick = useCallback(() => {
|
|
@@ -57,8 +98,10 @@ const ChatInputComponent = ({
|
|
|
57
98
|
const handleChange = useCallback(
|
|
58
99
|
(event: React.ChangeEvent<HTMLTextAreaElement>) => {
|
|
59
100
|
setAIChatMessage(event.target.value);
|
|
101
|
+
// Reset history navigation when user starts typing
|
|
102
|
+
resetMessageHistoryNavigation();
|
|
60
103
|
},
|
|
61
|
-
[setAIChatMessage],
|
|
104
|
+
[setAIChatMessage, resetMessageHistoryNavigation],
|
|
62
105
|
);
|
|
63
106
|
|
|
64
107
|
return (
|
|
@@ -15,11 +15,13 @@ const MessageListComponent = ({
|
|
|
15
15
|
isLoading,
|
|
16
16
|
chatId, // Add chatId prop
|
|
17
17
|
aiScratchpad, // Add aiScratchpad prop
|
|
18
|
+
aiStatus, // Add aiStatus prop
|
|
18
19
|
}: {
|
|
19
20
|
messages: VizChatMessage[];
|
|
20
21
|
isLoading: boolean;
|
|
21
22
|
chatId?: string; // Add chatId to the type
|
|
22
23
|
aiScratchpad?: string; // Add aiScratchpad to the type
|
|
24
|
+
aiStatus?: string; // Add aiStatus to the type
|
|
23
25
|
}) => {
|
|
24
26
|
const messagesEndRef = useRef<HTMLDivElement>(null);
|
|
25
27
|
const messagesContainerRef = useRef<HTMLDivElement>(null);
|
|
@@ -23,6 +23,9 @@ export const AIChat = () => {
|
|
|
23
23
|
setAIChatMessage,
|
|
24
24
|
handleSendMessage,
|
|
25
25
|
setAIErrorMessage,
|
|
26
|
+
navigateMessageHistoryUp,
|
|
27
|
+
navigateMessageHistoryDown,
|
|
28
|
+
resetMessageHistoryNavigation,
|
|
26
29
|
} = useContext(VZCodeContext);
|
|
27
30
|
|
|
28
31
|
// Get current chat data from content
|
|
@@ -254,6 +257,15 @@ export const AIChat = () => {
|
|
|
254
257
|
focused={aiChatFocused}
|
|
255
258
|
aiChatMode={aiChatMode}
|
|
256
259
|
setAIChatMode={setAIChatMode}
|
|
260
|
+
navigateMessageHistoryUp={
|
|
261
|
+
navigateMessageHistoryUp
|
|
262
|
+
}
|
|
263
|
+
navigateMessageHistoryDown={
|
|
264
|
+
navigateMessageHistoryDown
|
|
265
|
+
}
|
|
266
|
+
resetMessageHistoryNavigation={
|
|
267
|
+
resetMessageHistoryNavigation
|
|
268
|
+
}
|
|
257
269
|
/>
|
|
258
270
|
</div>
|
|
259
271
|
</div>
|