vzcode 1.32.0 → 1.33.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/README.md +0 -1
- package/dist/assets/index-DPIrco_g.js +235 -0
- package/dist/assets/index-DnunmWjy.css +1 -0
- package/dist/assets/worker-BrwN8AXx.js +330 -0
- package/dist/assets/worker-CkHcCP1n.js +136 -0
- package/dist/assets/worker-DkYJN5WQ.js +453 -0
- package/dist/index.html +2 -2
- package/package.json +37 -37
- package/src/client/CodeEditor/getOrCreateEditor.ts +18 -5
- package/src/client/Icons/MicSVG.tsx +1 -1
- package/src/client/VZCodeContext.tsx +18 -2
- package/src/client/VZSidebar/AIChat.tsx +142 -0
- package/src/client/VZSidebar/index.tsx +53 -8
- package/src/client/VZSidebar/styles.scss +178 -1
- package/src/client/featureFlags.ts +2 -0
- package/src/client/useActions.ts +20 -0
- package/src/client/useEditorCache.ts +1 -0
- package/src/client/useFileCRUD.ts +47 -0
- package/src/client/useOpenDirectories.ts +43 -12
- package/src/client/utils/fileExtension.ts +10 -0
- package/src/client/vzReducer/aiChatReducer.ts +31 -0
- package/src/client/vzReducer/createInitialState.ts +2 -0
- package/src/client/vzReducer/index.ts +20 -0
- package/dist/assets/index-DTtcN2MP.css +0 -1
- package/dist/assets/index-sreAszZh.js +0 -240
- package/dist/assets/worker-BKfYWklR.js +0 -136
- package/dist/assets/worker-COyDRdqW.js +0 -453
- package/dist/assets/worker-CWsWXMyk.js +0 -335
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-DPIrco_g.js"></script>
|
|
24
|
+
<link rel="stylesheet" crossorigin href="/assets/index-DnunmWjy.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.33.0",
|
|
4
4
|
"description": "Multiplayer code editor system",
|
|
5
5
|
"main": "src/index.ts",
|
|
6
6
|
"type": "module",
|
|
@@ -108,78 +108,78 @@
|
|
|
108
108
|
"@codemirror/lang-css": "^6.3.1",
|
|
109
109
|
"@codemirror/lang-html": "^6.4.9",
|
|
110
110
|
"@codemirror/lang-javascript": "^6.2.4",
|
|
111
|
-
"@codemirror/lang-json": "^6.0.
|
|
112
|
-
"@codemirror/lang-markdown": "^6.3.
|
|
111
|
+
"@codemirror/lang-json": "^6.0.2",
|
|
112
|
+
"@codemirror/lang-markdown": "^6.3.3",
|
|
113
113
|
"@codemirror/lint": "^6.8.5",
|
|
114
114
|
"@codemirror/state": "^6.5.2",
|
|
115
|
-
"@codemirror/theme-one-dark": "^6.1.
|
|
116
|
-
"@codemirror/view": "^6.
|
|
117
|
-
"@langchain/core": "^0.3.
|
|
118
|
-
"@langchain/openai": "^0.
|
|
115
|
+
"@codemirror/theme-one-dark": "^6.1.3",
|
|
116
|
+
"@codemirror/view": "^6.38.1",
|
|
117
|
+
"@langchain/core": "^0.3.65",
|
|
118
|
+
"@langchain/openai": "^0.6.2",
|
|
119
119
|
"@lezer/highlight": "^1.2.1",
|
|
120
|
-
"@livekit/components-react": "^2.9.
|
|
120
|
+
"@livekit/components-react": "^2.9.14",
|
|
121
121
|
"@replit/codemirror-indentation-markers": "^6.5.3",
|
|
122
122
|
"@replit/codemirror-interact": "^6.3.1",
|
|
123
123
|
"@replit/codemirror-lang-svelte": "^6.0.0",
|
|
124
124
|
"@replit/codemirror-vscode-keymap": "^6.0.2",
|
|
125
125
|
"@teamwork/websocket-json-stream": "^2.0.0",
|
|
126
126
|
"@typescript/vfs": "^1.6.1",
|
|
127
|
-
"@uiw/codemirror-theme-abcdef": "^4.
|
|
128
|
-
"@uiw/codemirror-theme-dracula": "^4.
|
|
129
|
-
"@uiw/codemirror-theme-eclipse": "^4.
|
|
130
|
-
"@uiw/codemirror-theme-github": "^4.
|
|
131
|
-
"@uiw/codemirror-theme-material": "^4.
|
|
132
|
-
"@uiw/codemirror-theme-nord": "^4.
|
|
133
|
-
"@uiw/codemirror-theme-okaidia": "^4.
|
|
134
|
-
"@uiw/codemirror-theme-xcode": "^4.
|
|
135
|
-
"@uiw/codemirror-themes": "^4.
|
|
127
|
+
"@uiw/codemirror-theme-abcdef": "^4.24.1",
|
|
128
|
+
"@uiw/codemirror-theme-dracula": "^4.24.1",
|
|
129
|
+
"@uiw/codemirror-theme-eclipse": "^4.24.1",
|
|
130
|
+
"@uiw/codemirror-theme-github": "^4.24.1",
|
|
131
|
+
"@uiw/codemirror-theme-material": "^4.24.1",
|
|
132
|
+
"@uiw/codemirror-theme-nord": "^4.24.1",
|
|
133
|
+
"@uiw/codemirror-theme-okaidia": "^4.24.1",
|
|
134
|
+
"@uiw/codemirror-theme-xcode": "^4.24.1",
|
|
135
|
+
"@uiw/codemirror-themes": "^4.24.1",
|
|
136
136
|
"@valtown/codemirror-ts": "^2.3.1",
|
|
137
|
-
"@vizhub/viz-types": "^0.
|
|
137
|
+
"@vizhub/viz-types": "^0.2.0",
|
|
138
138
|
"body-parser": "^2.2.0",
|
|
139
|
-
"codemirror": "^6.0.
|
|
139
|
+
"codemirror": "^6.0.2",
|
|
140
140
|
"codemirror-copilot": "^0.0.7",
|
|
141
141
|
"codemirror-ot": "^4.4.0",
|
|
142
142
|
"color-hash": "^2.0.2",
|
|
143
143
|
"comlink": "^4.4.2",
|
|
144
144
|
"d3-array": "^3.2.4",
|
|
145
145
|
"diff-match-patch": "^1.0.5",
|
|
146
|
-
"dotenv": "^
|
|
147
|
-
"eslint": "^9.
|
|
148
|
-
"eslint-linter-browserify": "^9.
|
|
146
|
+
"dotenv": "^17.2.0",
|
|
147
|
+
"eslint": "^9.31.0",
|
|
148
|
+
"eslint-linter-browserify": "^9.31.0",
|
|
149
149
|
"express": "^5.1.0",
|
|
150
|
-
"globals": "^16.
|
|
150
|
+
"globals": "^16.3.0",
|
|
151
151
|
"ignore": "^7.0.5",
|
|
152
152
|
"json0-ot-diff": "^1.1.2",
|
|
153
|
-
"livekit-server-sdk": "^2.13.
|
|
153
|
+
"livekit-server-sdk": "^2.13.1",
|
|
154
154
|
"ngrok": "^5.0.0-beta.2",
|
|
155
|
-
"npm": "^11.4.
|
|
156
|
-
"open": "^10.
|
|
155
|
+
"npm": "^11.4.2",
|
|
156
|
+
"open": "^10.2.0",
|
|
157
157
|
"prettier-plugin-svelte": "^3.4.0",
|
|
158
158
|
"react": "^18",
|
|
159
159
|
"react-bootstrap": "^2.10.10",
|
|
160
160
|
"react-dom": "^18",
|
|
161
|
-
"react-router-dom": "^7.
|
|
161
|
+
"react-router-dom": "^7.7.0",
|
|
162
162
|
"sharedb": "^5.2.2",
|
|
163
163
|
"sharedb-client-browser": "^5.2.2",
|
|
164
164
|
"uuid": "^11.1.0",
|
|
165
|
-
"vizhub-ui": "^3.
|
|
166
|
-
"ws": "^8.18.
|
|
165
|
+
"vizhub-ui": "^3.24.0",
|
|
166
|
+
"ws": "^8.18.3"
|
|
167
167
|
},
|
|
168
168
|
"devDependencies": {
|
|
169
169
|
"@types/react": "^18",
|
|
170
170
|
"@types/react-dom": "^18",
|
|
171
|
-
"@vitejs/plugin-react": "^4.
|
|
172
|
-
"concurrently": "^9.
|
|
171
|
+
"@vitejs/plugin-react": "^4.7.0",
|
|
172
|
+
"concurrently": "^9.2.0",
|
|
173
173
|
"cross-env": "^7.0.3",
|
|
174
174
|
"npm-check-updates": "^18.0.1",
|
|
175
|
-
"prettier": "^3.
|
|
176
|
-
"sass": "^1.89.
|
|
175
|
+
"prettier": "^3.6.2",
|
|
176
|
+
"sass": "^1.89.2",
|
|
177
177
|
"typescript": "^5.8.3",
|
|
178
|
-
"vite": "^
|
|
179
|
-
"vitest": "^3.2.
|
|
178
|
+
"vite": "^7.0.5",
|
|
179
|
+
"vitest": "^3.2.4"
|
|
180
180
|
},
|
|
181
181
|
"optionalDependencies": {
|
|
182
|
-
"@rollup/rollup-darwin-arm64": "^4.
|
|
183
|
-
"@rollup/rollup-win32-x64-msvc": "^4.
|
|
182
|
+
"@rollup/rollup-darwin-arm64": "^4.45.1",
|
|
183
|
+
"@rollup/rollup-win32-x64-msvc": "^4.45.1"
|
|
184
184
|
}
|
|
185
185
|
}
|
|
@@ -59,6 +59,7 @@ import {
|
|
|
59
59
|
tsLinterWorker,
|
|
60
60
|
tsSyncWorker,
|
|
61
61
|
} from '@valtown/codemirror-ts';
|
|
62
|
+
import { getFileExtension } from '../utils/fileExtension';
|
|
62
63
|
|
|
63
64
|
const DEBUG = false;
|
|
64
65
|
|
|
@@ -131,6 +132,14 @@ const languageExtensions = {
|
|
|
131
132
|
svelte,
|
|
132
133
|
};
|
|
133
134
|
|
|
135
|
+
// Exported utility function to get language extension for a file extension
|
|
136
|
+
export const getLanguageExtension = (
|
|
137
|
+
fileExtension: string,
|
|
138
|
+
) => {
|
|
139
|
+
const languageFunc = languageExtensions[fileExtension];
|
|
140
|
+
return languageFunc ? languageFunc() : undefined;
|
|
141
|
+
};
|
|
142
|
+
|
|
134
143
|
// Gets a value at a path in an object.
|
|
135
144
|
// e.g. getAtPath({a: {b: 1}}, ['a', 'b']) === 1
|
|
136
145
|
const getAtPath = (obj, path) => {
|
|
@@ -146,6 +155,7 @@ const getAtPath = (obj, path) => {
|
|
|
146
155
|
interface ExtendedEditorCacheValue
|
|
147
156
|
extends EditorCacheValue {
|
|
148
157
|
themeCompartment: Compartment;
|
|
158
|
+
languageCompartment: Compartment;
|
|
149
159
|
rainbowBracketsCompartment: Compartment;
|
|
150
160
|
updateRainbowBrackets: (enabled: boolean) => void;
|
|
151
161
|
}
|
|
@@ -227,7 +237,8 @@ export const getOrCreateEditor = async ({
|
|
|
227
237
|
const namePath = [...filesPath, fileId, 'name'];
|
|
228
238
|
const text = getAtPath(content, textPath);
|
|
229
239
|
const name = getAtPath(content, namePath);
|
|
230
|
-
|
|
240
|
+
|
|
241
|
+
const fileExtension = getFileExtension(name);
|
|
231
242
|
|
|
232
243
|
// Create a compartment for the theme so that it can be changed dynamically.
|
|
233
244
|
// Inspired by: https://github.com/craftzdog/cm6-themes/blob/main/example/index.ts
|
|
@@ -321,10 +332,6 @@ export const getOrCreateEditor = async ({
|
|
|
321
332
|
// using a Compartment.
|
|
322
333
|
const languageCompartment = new Compartment();
|
|
323
334
|
// See https://github.com/vizhub-core/vzcode/issues/55
|
|
324
|
-
const getLanguageExtension = (fileExtension: string) => {
|
|
325
|
-
const languageFunc = languageExtensions[fileExtension];
|
|
326
|
-
return languageFunc ? languageFunc() : undefined;
|
|
327
|
-
};
|
|
328
335
|
|
|
329
336
|
const languageExtension =
|
|
330
337
|
getLanguageExtension(fileExtension);
|
|
@@ -346,6 +353,11 @@ export const getOrCreateEditor = async ({
|
|
|
346
353
|
extensions.push(languageCompartment.of([]));
|
|
347
354
|
}
|
|
348
355
|
|
|
356
|
+
// Enable line wrapping for Markdown files
|
|
357
|
+
if (fileExtension === 'md') {
|
|
358
|
+
extensions.push(EditorView.lineWrapping);
|
|
359
|
+
}
|
|
360
|
+
|
|
349
361
|
// Add interactive widgets.
|
|
350
362
|
// Includes the Alt+drag functionality for numbers.
|
|
351
363
|
// Calls `onInteract` when one of those widgets is interacted with.
|
|
@@ -458,6 +470,7 @@ export const getOrCreateEditor = async ({
|
|
|
458
470
|
const editorCacheValue: ExtendedEditorCacheValue = {
|
|
459
471
|
editor,
|
|
460
472
|
themeCompartment,
|
|
473
|
+
languageCompartment,
|
|
461
474
|
rainbowBracketsCompartment,
|
|
462
475
|
updateRainbowBrackets: (enabled) => {
|
|
463
476
|
editor.dispatch({
|
|
@@ -113,6 +113,11 @@ export type VZCodeContextValue = {
|
|
|
113
113
|
isSearchOpen: boolean;
|
|
114
114
|
setIsSearchOpen: (isSearchOpen: boolean) => void;
|
|
115
115
|
setSearch: (pattern: string) => void;
|
|
116
|
+
|
|
117
|
+
isAIChatOpen: boolean;
|
|
118
|
+
setIsAIChatOpen: (isAIChatOpen: boolean) => void;
|
|
119
|
+
aiChatFocused: boolean;
|
|
120
|
+
toggleAIChatFocused: () => void;
|
|
116
121
|
setSearchResults: (files: ShareDBDoc<VizContent>) => void;
|
|
117
122
|
setSearchFileVisibility: (
|
|
118
123
|
files: ShareDBDoc<VizContent>,
|
|
@@ -252,6 +257,8 @@ export const VZCodeProvider = ({
|
|
|
252
257
|
theme,
|
|
253
258
|
search,
|
|
254
259
|
isSearchOpen,
|
|
260
|
+
isAIChatOpen,
|
|
261
|
+
aiChatFocused,
|
|
255
262
|
isSettingsOpen,
|
|
256
263
|
isDocOpen,
|
|
257
264
|
editorWantsFocus,
|
|
@@ -260,7 +267,7 @@ export const VZCodeProvider = ({
|
|
|
260
267
|
sidebarPresenceIndicators,
|
|
261
268
|
} = state;
|
|
262
269
|
|
|
263
|
-
const activePane = findPane(pane, activePaneId);
|
|
270
|
+
const activePane: Pane = findPane(pane, activePaneId);
|
|
264
271
|
if (activePane.type !== 'leafPane') {
|
|
265
272
|
// Should never happen
|
|
266
273
|
throw new Error('Expected leafPane');
|
|
@@ -281,6 +288,8 @@ export const VZCodeProvider = ({
|
|
|
281
288
|
setSearchLineVisibility,
|
|
282
289
|
setSearchFocusedIndex,
|
|
283
290
|
toggleSearchFocused,
|
|
291
|
+
setIsAIChatOpen,
|
|
292
|
+
toggleAIChatFocused,
|
|
284
293
|
setIsSettingsOpen,
|
|
285
294
|
setIsDocOpen,
|
|
286
295
|
closeSettings,
|
|
@@ -304,7 +313,7 @@ export const VZCodeProvider = ({
|
|
|
304
313
|
// The set of open directories.
|
|
305
314
|
// TODO move this into reducer/useActions
|
|
306
315
|
const { isDirectoryOpen, toggleDirectory } =
|
|
307
|
-
useOpenDirectories();
|
|
316
|
+
useOpenDirectories({ activePane, content });
|
|
308
317
|
|
|
309
318
|
// Cache of CodeMirror editors by file id.
|
|
310
319
|
const editorCache: EditorCache = useEditorCache();
|
|
@@ -324,6 +333,8 @@ export const VZCodeProvider = ({
|
|
|
324
333
|
submitOperation,
|
|
325
334
|
closeTabs,
|
|
326
335
|
openTab,
|
|
336
|
+
editorCache,
|
|
337
|
+
content,
|
|
327
338
|
});
|
|
328
339
|
|
|
329
340
|
// State to control the create file modal's visibility
|
|
@@ -435,6 +446,11 @@ export const VZCodeProvider = ({
|
|
|
435
446
|
setSearchFocusedIndex,
|
|
436
447
|
toggleSearchFocused,
|
|
437
448
|
|
|
449
|
+
isAIChatOpen,
|
|
450
|
+
setIsAIChatOpen,
|
|
451
|
+
aiChatFocused,
|
|
452
|
+
toggleAIChatFocused,
|
|
453
|
+
|
|
438
454
|
isSettingsOpen,
|
|
439
455
|
setIsSettingsOpen,
|
|
440
456
|
closeSettings,
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import {
|
|
2
|
+
useRef,
|
|
3
|
+
useEffect,
|
|
4
|
+
useContext,
|
|
5
|
+
useState,
|
|
6
|
+
useCallback,
|
|
7
|
+
} from 'react';
|
|
8
|
+
import { Form, Button } from '../bootstrap';
|
|
9
|
+
import { VZCodeContext } from '../VZCodeContext';
|
|
10
|
+
|
|
11
|
+
export const AIChat = () => {
|
|
12
|
+
const [message, setMessage] = useState('');
|
|
13
|
+
const [messages, setMessages] = useState([
|
|
14
|
+
{
|
|
15
|
+
id: 1,
|
|
16
|
+
type: 'assistant',
|
|
17
|
+
content:
|
|
18
|
+
"Hello! I'm your AI assistant. How can I help you with your code today?",
|
|
19
|
+
timestamp: new Date(),
|
|
20
|
+
},
|
|
21
|
+
]);
|
|
22
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
23
|
+
const inputRef = useRef(null);
|
|
24
|
+
const messagesEndRef = useRef(null);
|
|
25
|
+
|
|
26
|
+
const { aiChatFocused } = useContext(VZCodeContext);
|
|
27
|
+
|
|
28
|
+
const scrollToBottom = () => {
|
|
29
|
+
messagesEndRef.current?.scrollIntoView({
|
|
30
|
+
behavior: 'smooth',
|
|
31
|
+
});
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
useEffect(() => {
|
|
35
|
+
scrollToBottom();
|
|
36
|
+
}, [messages]);
|
|
37
|
+
|
|
38
|
+
useEffect(() => {
|
|
39
|
+
// Focus the input when the AI chat is focused
|
|
40
|
+
if (aiChatFocused && inputRef.current) {
|
|
41
|
+
inputRef.current.focus();
|
|
42
|
+
}
|
|
43
|
+
}, [aiChatFocused]);
|
|
44
|
+
|
|
45
|
+
const handleSendMessage = useCallback(async () => {
|
|
46
|
+
if (!message.trim() || isLoading) return;
|
|
47
|
+
|
|
48
|
+
const userMessage = {
|
|
49
|
+
id: Date.now(),
|
|
50
|
+
type: 'user',
|
|
51
|
+
content: message.trim(),
|
|
52
|
+
timestamp: new Date(),
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
setMessages((prev) => [...prev, userMessage]);
|
|
56
|
+
setMessage('');
|
|
57
|
+
setIsLoading(true);
|
|
58
|
+
|
|
59
|
+
// Simulate AI response (replace with actual AI integration later)
|
|
60
|
+
setTimeout(() => {
|
|
61
|
+
const aiResponse = {
|
|
62
|
+
id: Date.now() + 1,
|
|
63
|
+
type: 'assistant',
|
|
64
|
+
content:
|
|
65
|
+
'I understand you\'re asking about: "' +
|
|
66
|
+
userMessage.content +
|
|
67
|
+
'". This is a placeholder response. The AI chat feature is still being developed!',
|
|
68
|
+
timestamp: new Date(),
|
|
69
|
+
};
|
|
70
|
+
setMessages((prev) => [...prev, aiResponse]);
|
|
71
|
+
setIsLoading(false);
|
|
72
|
+
}, 1000);
|
|
73
|
+
}, [message, isLoading]);
|
|
74
|
+
|
|
75
|
+
const handleKeyDown = (event) => {
|
|
76
|
+
if (event.key === 'Enter' && !event.shiftKey) {
|
|
77
|
+
event.preventDefault();
|
|
78
|
+
handleSendMessage();
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
return (
|
|
83
|
+
<div className="ai-chat-container">
|
|
84
|
+
<div className="ai-chat-messages">
|
|
85
|
+
{messages.map((msg) => (
|
|
86
|
+
<div
|
|
87
|
+
key={msg.id}
|
|
88
|
+
className={`ai-chat-message ${msg.type === 'user' ? 'user' : 'assistant'}`}
|
|
89
|
+
>
|
|
90
|
+
<div className="ai-chat-message-content">
|
|
91
|
+
{msg.content}
|
|
92
|
+
</div>
|
|
93
|
+
<div className="ai-chat-message-time">
|
|
94
|
+
{msg.timestamp.toLocaleTimeString([], {
|
|
95
|
+
hour: '2-digit',
|
|
96
|
+
minute: '2-digit',
|
|
97
|
+
})}
|
|
98
|
+
</div>
|
|
99
|
+
</div>
|
|
100
|
+
))}
|
|
101
|
+
{isLoading && (
|
|
102
|
+
<div className="ai-chat-message assistant">
|
|
103
|
+
<div className="ai-chat-message-content">
|
|
104
|
+
<div className="ai-chat-typing">
|
|
105
|
+
<span></span>
|
|
106
|
+
<span></span>
|
|
107
|
+
<span></span>
|
|
108
|
+
</div>
|
|
109
|
+
</div>
|
|
110
|
+
</div>
|
|
111
|
+
)}
|
|
112
|
+
<div ref={messagesEndRef} />
|
|
113
|
+
</div>
|
|
114
|
+
|
|
115
|
+
<div className="ai-chat-input-container">
|
|
116
|
+
<Form.Group className="ai-chat-input-group">
|
|
117
|
+
<Form.Control
|
|
118
|
+
as="textarea"
|
|
119
|
+
rows={2}
|
|
120
|
+
value={message}
|
|
121
|
+
onChange={(event) =>
|
|
122
|
+
setMessage(event.target.value)
|
|
123
|
+
}
|
|
124
|
+
onKeyDown={handleKeyDown}
|
|
125
|
+
ref={inputRef}
|
|
126
|
+
placeholder="Ask me anything about your code..."
|
|
127
|
+
spellCheck="false"
|
|
128
|
+
disabled={isLoading}
|
|
129
|
+
/>
|
|
130
|
+
<Button
|
|
131
|
+
variant="primary"
|
|
132
|
+
onClick={handleSendMessage}
|
|
133
|
+
disabled={!message.trim() || isLoading}
|
|
134
|
+
className="ai-chat-send-button"
|
|
135
|
+
>
|
|
136
|
+
Send
|
|
137
|
+
</Button>
|
|
138
|
+
</Form.Group>
|
|
139
|
+
</div>
|
|
140
|
+
</div>
|
|
141
|
+
);
|
|
142
|
+
};
|
|
@@ -25,15 +25,20 @@ import {
|
|
|
25
25
|
PinSVG,
|
|
26
26
|
QuestionMarkSVG,
|
|
27
27
|
SearchSVG,
|
|
28
|
+
SparklesSVG,
|
|
28
29
|
} from '../Icons';
|
|
29
30
|
import { MicSVG } from '../Icons/MicSVG';
|
|
30
31
|
import { sortFileTree } from '../sortFileTree';
|
|
31
32
|
import { SplitPaneResizeContext } from '../SplitPaneResizeContext';
|
|
32
33
|
import { VZCodeContext } from '../VZCodeContext';
|
|
34
|
+
import { AIChat } from './AIChat';
|
|
33
35
|
import { Listing } from './Listing';
|
|
34
36
|
import { Search } from './Search';
|
|
35
37
|
import { useDragAndDrop } from './useDragAndDrop';
|
|
36
|
-
import {
|
|
38
|
+
import {
|
|
39
|
+
enableLiveKit,
|
|
40
|
+
enableAIChat,
|
|
41
|
+
} from '../featureFlags';
|
|
37
42
|
import './styles.scss';
|
|
38
43
|
|
|
39
44
|
// TODO turn this UI back on when we are actually detecting
|
|
@@ -105,6 +110,11 @@ export const VZSidebar = ({
|
|
|
105
110
|
<strong>Open Voice Chat Menu</strong>
|
|
106
111
|
</div>
|
|
107
112
|
),
|
|
113
|
+
aiChatToolTipText = (
|
|
114
|
+
<div>
|
|
115
|
+
<strong>AI Chat</strong>
|
|
116
|
+
</div>
|
|
117
|
+
),
|
|
108
118
|
}: {
|
|
109
119
|
createFileTooltipText?: React.ReactNode;
|
|
110
120
|
createDirTooltipText?: React.ReactNode;
|
|
@@ -116,6 +126,7 @@ export const VZSidebar = ({
|
|
|
116
126
|
enableAutoFollowTooltipText?: React.ReactNode;
|
|
117
127
|
disableAutoFollowTooltipText?: React.ReactNode;
|
|
118
128
|
voiceChatToolTipText?: React.ReactNode;
|
|
129
|
+
aiChatToolTipText?: React.ReactNode;
|
|
119
130
|
}) => {
|
|
120
131
|
const {
|
|
121
132
|
files,
|
|
@@ -124,6 +135,8 @@ export const VZSidebar = ({
|
|
|
124
135
|
setIsDocOpen,
|
|
125
136
|
isSearchOpen,
|
|
126
137
|
setIsSearchOpen,
|
|
138
|
+
isAIChatOpen,
|
|
139
|
+
setIsAIChatOpen,
|
|
127
140
|
handleOpenCreateFileModal,
|
|
128
141
|
handleOpenCreateDirModal,
|
|
129
142
|
connected,
|
|
@@ -270,7 +283,10 @@ export const VZSidebar = ({
|
|
|
270
283
|
<i
|
|
271
284
|
id="files-icon"
|
|
272
285
|
className="icon-button icon-button-dark"
|
|
273
|
-
onClick={() =>
|
|
286
|
+
onClick={() => {
|
|
287
|
+
setIsSearchOpen(false);
|
|
288
|
+
setIsAIChatOpen(false);
|
|
289
|
+
}}
|
|
274
290
|
>
|
|
275
291
|
<FolderSVG />
|
|
276
292
|
</i>
|
|
@@ -287,12 +303,37 @@ export const VZSidebar = ({
|
|
|
287
303
|
<i
|
|
288
304
|
id="search-icon"
|
|
289
305
|
className="icon-button icon-button-dark"
|
|
290
|
-
onClick={() =>
|
|
306
|
+
onClick={() => {
|
|
307
|
+
setIsSearchOpen(true);
|
|
308
|
+
setIsAIChatOpen(false);
|
|
309
|
+
}}
|
|
291
310
|
>
|
|
292
311
|
<SearchSVG />
|
|
293
312
|
</i>
|
|
294
313
|
</OverlayTrigger>
|
|
295
314
|
|
|
315
|
+
{enableAIChat && (
|
|
316
|
+
<OverlayTrigger
|
|
317
|
+
placement="right"
|
|
318
|
+
overlay={
|
|
319
|
+
<Tooltip id="ai-chat-tooltip">
|
|
320
|
+
{aiChatToolTipText}
|
|
321
|
+
</Tooltip>
|
|
322
|
+
}
|
|
323
|
+
>
|
|
324
|
+
<i
|
|
325
|
+
id="ai-chat-icon"
|
|
326
|
+
className="icon-button icon-button-dark"
|
|
327
|
+
onClick={() => {
|
|
328
|
+
setIsAIChatOpen(true);
|
|
329
|
+
setIsSearchOpen(false);
|
|
330
|
+
}}
|
|
331
|
+
>
|
|
332
|
+
<SparklesSVG />
|
|
333
|
+
</i>
|
|
334
|
+
</OverlayTrigger>
|
|
335
|
+
)}
|
|
336
|
+
|
|
296
337
|
<OverlayTrigger
|
|
297
338
|
placement="right"
|
|
298
339
|
overlay={
|
|
@@ -438,7 +479,15 @@ export const VZSidebar = ({
|
|
|
438
479
|
onDragLeave={handleDragLeave}
|
|
439
480
|
onDrop={handleDrop}
|
|
440
481
|
>
|
|
441
|
-
{
|
|
482
|
+
{isAIChatOpen ? (
|
|
483
|
+
<div className="sidebar-ai-chat">
|
|
484
|
+
<AIChat />
|
|
485
|
+
</div>
|
|
486
|
+
) : isSearchOpen ? (
|
|
487
|
+
<div className="sidebar-search">
|
|
488
|
+
<Search />
|
|
489
|
+
</div>
|
|
490
|
+
) : (
|
|
442
491
|
<div className="sidebar-files">
|
|
443
492
|
{isDragOver ? (
|
|
444
493
|
<div className="empty drag-over">
|
|
@@ -480,10 +529,6 @@ export const VZSidebar = ({
|
|
|
480
529
|
</div>
|
|
481
530
|
)}
|
|
482
531
|
</div>
|
|
483
|
-
) : (
|
|
484
|
-
<div className="sidebar-search">
|
|
485
|
-
<Search />
|
|
486
|
-
</div>
|
|
487
532
|
)}
|
|
488
533
|
</div>
|
|
489
534
|
</div>
|