vzcode 2.2.0 → 2.3.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.
Files changed (220) hide show
  1. package/dist/assets/{buildWorker-Dsx6rOdK.js → buildWorker-wLkQ0yz1.js} +64 -64
  2. package/dist/assets/{index-BM8tDh6M.css → index-BoFeK4GL.css} +1 -1
  3. package/dist/assets/{index-CpxqGhXj.js → index-DuUjtrt6.js} +150 -150
  4. package/dist/assets/{worker-BeBZGG1n.js → worker-DHxSPM7N.js} +78 -78
  5. package/dist/cli.js +113 -0
  6. package/dist/index.html +2 -2
  7. package/{src/ot.ts → dist/ot.js} +2 -14
  8. package/{src/randomId.ts → dist/randomId.js} +5 -6
  9. package/dist/runCode.js +20 -0
  10. package/dist/server/aiChatHandler/aiEditing.js +89 -0
  11. package/dist/server/aiChatHandler/chatOperations.js +360 -0
  12. package/dist/server/aiChatHandler/errorHandling.js +49 -0
  13. package/dist/server/aiChatHandler/index.js +112 -0
  14. package/dist/server/aiChatHandler/llmStreaming.js +284 -0
  15. package/dist/server/aiChatHandler/validation.js +19 -0
  16. package/dist/server/computeInitialDocument.js +146 -0
  17. package/{src/server/config.ts → dist/server/config.js} +4 -7
  18. package/{src/server/featureFlags.ts → dist/server/featureFlags.js} +0 -3
  19. package/dist/server/generateAIResponse.js +129 -0
  20. package/dist/server/handleAIAssist.js +39 -0
  21. package/dist/server/handleAICopilot.js +81 -0
  22. package/dist/server/index.js +297 -0
  23. package/dist/server/livekit.js +17 -0
  24. package/dist/server/prettier.js +90 -0
  25. package/{src/server/setupEnv.ts → dist/server/setupEnv.js} +1 -2
  26. package/dist/submitOperation.js +14 -0
  27. package/dist/types.js +1 -0
  28. package/dist/utils/fileDiff.js +66 -0
  29. package/package.json +22 -22
  30. package/src/client/AIAssist/AIAssistCodeMirrorKeyMap.ts +0 -42
  31. package/src/client/AIAssist/AIAssistWidget/index.tsx +0 -135
  32. package/src/client/AIAssist/AIAssistWidget/style.scss +0 -47
  33. package/src/client/AIAssist/Spinner.jsx +0 -76
  34. package/src/client/AIAssist/formatFile.ts +0 -27
  35. package/src/client/AIAssist/generateFilesContext.ts +0 -25
  36. package/src/client/AIAssist/index.ts +0 -2
  37. package/src/client/AIAssist/startAIAssist.ts +0 -95
  38. package/src/client/App/index.tsx +0 -153
  39. package/src/client/App/style.scss +0 -82
  40. package/src/client/App/usePending.ts +0 -51
  41. package/src/client/App/useShareDB.ts +0 -161
  42. package/src/client/CodeEditor/Copilot/index.ts +0 -74
  43. package/src/client/CodeEditor/InteractiveWidgets/boolToggler.ts +0 -12
  44. package/src/client/CodeEditor/InteractiveWidgets/colorPicker.ts +0 -68
  45. package/src/client/CodeEditor/InteractiveWidgets/colorsInTextPlugin.ts +0 -174
  46. package/src/client/CodeEditor/InteractiveWidgets/highlightWidgets.ts +0 -79
  47. package/src/client/CodeEditor/InteractiveWidgets/index.ts +0 -44
  48. package/src/client/CodeEditor/InteractiveWidgets/markdownCheckboxToggler.ts +0 -12
  49. package/src/client/CodeEditor/InteractiveWidgets/numberDragger.ts +0 -20
  50. package/src/client/CodeEditor/InteractiveWidgets/rotateWidget.ts +0 -143
  51. package/src/client/CodeEditor/InteractiveWidgets/urlClicker.test.ts +0 -48
  52. package/src/client/CodeEditor/InteractiveWidgets/urlClicker.ts +0 -12
  53. package/src/client/CodeEditor/InteractiveWidgets/vec2Slider.ts +0 -25
  54. package/src/client/CodeEditor/basicSetup.ts +0 -73
  55. package/src/client/CodeEditor/getOrCreateEditor.tsx +0 -615
  56. package/src/client/CodeEditor/index.tsx +0 -202
  57. package/src/client/CodeEditor/json1PresenceBroadcast.ts +0 -41
  58. package/src/client/CodeEditor/json1PresenceDisplay.ts +0 -350
  59. package/src/client/CodeEditor/rainbowBrackets.ts +0 -122
  60. package/src/client/CodeEditor/style.scss +0 -156
  61. package/src/client/CodeEditor/typescriptExtension/worker.ts +0 -32
  62. package/src/client/CodeErrorOverlay/index.tsx +0 -77
  63. package/src/client/CodeErrorOverlay/style.scss +0 -33
  64. package/src/client/Fonts/fonts.ts +0 -8
  65. package/src/client/Icons/AdjustmentSVG.tsx +0 -19
  66. package/src/client/Icons/BugSVG.tsx +0 -20
  67. package/src/client/Icons/CloseSVG.tsx +0 -19
  68. package/src/client/Icons/CssSVG.tsx +0 -16
  69. package/src/client/Icons/DirectoryArrowSVG.tsx +0 -19
  70. package/src/client/Icons/EditSVG.tsx +0 -19
  71. package/src/client/Icons/FileSVG.tsx +0 -19
  72. package/src/client/Icons/FolderSVG.tsx +0 -20
  73. package/src/client/Icons/GearSVG.tsx +0 -16
  74. package/src/client/Icons/HtmlSVG.tsx +0 -16
  75. package/src/client/Icons/JavaScriptSVG.tsx +0 -16
  76. package/src/client/Icons/JsonSVG.tsx +0 -16
  77. package/src/client/Icons/MarkdownSVG.tsx +0 -16
  78. package/src/client/Icons/MicOffSVG.tsx +0 -35
  79. package/src/client/Icons/MicSVG.tsx +0 -25
  80. package/src/client/Icons/NewSVG.tsx +0 -19
  81. package/src/client/Icons/PinSVG.tsx +0 -14
  82. package/src/client/Icons/PlaySVG.tsx +0 -16
  83. package/src/client/Icons/QuestionMarkSVG.tsx +0 -18
  84. package/src/client/Icons/ReactSVG.tsx +0 -16
  85. package/src/client/Icons/SearchSVG.tsx +0 -20
  86. package/src/client/Icons/SparklesSVG.tsx +0 -23
  87. package/src/client/Icons/SplitEditorSVG.tsx +0 -34
  88. package/src/client/Icons/StopSVG.tsx +0 -15
  89. package/src/client/Icons/SvelteSVG.tsx +0 -16
  90. package/src/client/Icons/TrashSVG.tsx +0 -19
  91. package/src/client/Icons/TypeScriptSVG.tsx +0 -16
  92. package/src/client/Icons/index.tsx +0 -26
  93. package/src/client/ImageViewer/index.tsx +0 -91
  94. package/src/client/ImageViewer/style.scss +0 -41
  95. package/src/client/PresenceNotifications/PresenceNotifications.test.ts +0 -134
  96. package/src/client/PresenceNotifications/index.tsx +0 -158
  97. package/src/client/PresenceNotifications/style.scss +0 -17
  98. package/src/client/RunCodeWidget/index.tsx +0 -117
  99. package/src/client/RunCodeWidget/style.scss +0 -24
  100. package/src/client/SplitPaneResizeContext.tsx +0 -159
  101. package/src/client/TabList/Tab.tsx +0 -73
  102. package/src/client/TabList/index.tsx +0 -35
  103. package/src/client/TabList/style.scss +0 -51
  104. package/src/client/VZCodeContext/index.tsx +0 -29
  105. package/src/client/VZCodeContext/types.ts +0 -249
  106. package/src/client/VZCodeContext/useVZCodeState.ts +0 -584
  107. package/src/client/VZKeyboardShortcutsDoc.tsx +0 -148
  108. package/src/client/VZLeft.tsx +0 -28
  109. package/src/client/VZMiddle.tsx +0 -172
  110. package/src/client/VZResizer/index.tsx +0 -128
  111. package/src/client/VZResizer/styles.scss +0 -33
  112. package/src/client/VZRight.tsx +0 -113
  113. package/src/client/VZSettings.tsx +0 -275
  114. package/src/client/VZSidebar/AIChat/ChatInput.tsx +0 -239
  115. package/src/client/VZSidebar/AIChat/DiffView.scss +0 -136
  116. package/src/client/VZSidebar/AIChat/DiffView.tsx +0 -176
  117. package/src/client/VZSidebar/AIChat/Message.tsx +0 -143
  118. package/src/client/VZSidebar/AIChat/MessageList.tsx +0 -205
  119. package/src/client/VZSidebar/AIChat/StreamingMessage.tsx +0 -35
  120. package/src/client/VZSidebar/AIChat/ThinkingScratchpad.tsx +0 -156
  121. package/src/client/VZSidebar/AIChat/TypingIndicator.tsx +0 -19
  122. package/src/client/VZSidebar/AIChat/index.tsx +0 -273
  123. package/src/client/VZSidebar/AIChat/styles.scss +0 -627
  124. package/src/client/VZSidebar/AIChat/useSpeechRecognition.ts +0 -117
  125. package/src/client/VZSidebar/CreateDirModal.tsx +0 -111
  126. package/src/client/VZSidebar/CreateFileModal.tsx +0 -111
  127. package/src/client/VZSidebar/DeleteConfirmationModal.tsx +0 -76
  128. package/src/client/VZSidebar/DirectoryListing.tsx +0 -89
  129. package/src/client/VZSidebar/EmptyState.tsx +0 -11
  130. package/src/client/VZSidebar/FileListing.tsx +0 -91
  131. package/src/client/VZSidebar/FileTypeIcon.tsx +0 -49
  132. package/src/client/VZSidebar/Item.tsx +0 -237
  133. package/src/client/VZSidebar/Listing.tsx +0 -47
  134. package/src/client/VZSidebar/Search.tsx +0 -527
  135. package/src/client/VZSidebar/VisualEditor.tsx +0 -282
  136. package/src/client/VZSidebar/VoiceChatModal.tsx +0 -121
  137. package/src/client/VZSidebar/aiCopyPaste.ts +0 -199
  138. package/src/client/VZSidebar/index.tsx +0 -728
  139. package/src/client/VZSidebar/styles.scss +0 -612
  140. package/src/client/VZSidebar/useDragAndDrop.tsx +0 -408
  141. package/src/client/bootstrap.ts +0 -26
  142. package/src/client/buildWorker.ts +0 -3
  143. package/src/client/featureFlags.ts +0 -8
  144. package/src/client/generateRequestId.ts +0 -6
  145. package/src/client/getFileTree.ts +0 -53
  146. package/src/client/index.ts +0 -19
  147. package/src/client/main.jsx +0 -10
  148. package/src/client/presenceColor.ts +0 -8
  149. package/src/client/shouldTriggerRun.ts +0 -31
  150. package/src/client/sortFileTree.ts +0 -21
  151. package/src/client/tabsSearchParameters.test.ts +0 -79
  152. package/src/client/tabsSearchParameters.ts +0 -137
  153. package/src/client/themes/index.ts +0 -7
  154. package/src/client/themes/themes.ts +0 -77
  155. package/src/client/themes/uiwImports.ts +0 -32
  156. package/src/client/themes/useDynamicTheme.ts +0 -29
  157. package/src/client/themes/vizhubTheme/colors.ts +0 -80
  158. package/src/client/themes/vizhubTheme/index.ts +0 -193
  159. package/src/client/useActions.ts +0 -288
  160. package/src/client/useESLint/index.ts +0 -72
  161. package/src/client/useESLint/worker.ts +0 -113
  162. package/src/client/useEditorCache.ts +0 -35
  163. package/src/client/useFileCRUD.ts +0 -228
  164. package/src/client/useKeyboardShortcuts.ts +0 -451
  165. package/src/client/useOpenDirectories.ts +0 -99
  166. package/src/client/usePresenceAutoFollow.ts +0 -85
  167. package/src/client/usePrettier/index.ts +0 -178
  168. package/src/client/usePrettier/worker.ts +0 -109
  169. package/src/client/useRunCode.tsx +0 -15
  170. package/src/client/useRuntimeError.ts +0 -32
  171. package/src/client/useSubmitOperation.ts +0 -15
  172. package/src/client/useURLSync.ts +0 -137
  173. package/src/client/usernameLocalStorage.ts +0 -43
  174. package/src/client/utils/fileExtension.ts +0 -10
  175. package/src/client/utils/isImageFile.ts +0 -12
  176. package/src/client/vzReducer/aiChatReducer.ts +0 -44
  177. package/src/client/vzReducer/closeTabReducer.test.ts +0 -205
  178. package/src/client/vzReducer/closeTabsReducer.ts +0 -96
  179. package/src/client/vzReducer/createInitialState.ts +0 -38
  180. package/src/client/vzReducer/editorNoLongerWantsFocusReducer.ts +0 -9
  181. package/src/client/vzReducer/findPane.ts +0 -19
  182. package/src/client/vzReducer/index.ts +0 -250
  183. package/src/client/vzReducer/openTabReducer.test.ts +0 -127
  184. package/src/client/vzReducer/openTabReducer.ts +0 -74
  185. package/src/client/vzReducer/searchReducer.test.ts +0 -292
  186. package/src/client/vzReducer/searchReducer.ts +0 -181
  187. package/src/client/vzReducer/setActiveFileIdReducer.ts +0 -28
  188. package/src/client/vzReducer/setActiveFileLeftRightReducer.ts +0 -76
  189. package/src/client/vzReducer/setIsDocOpenReducer.ts +0 -9
  190. package/src/client/vzReducer/setIsSettingsOpenReducer.ts +0 -9
  191. package/src/client/vzReducer/setThemeReducer.ts +0 -9
  192. package/src/client/vzReducer/setUsernameReducer.ts +0 -9
  193. package/src/client/vzReducer/splitCurrentPaneReducer.ts +0 -66
  194. package/src/client/vzReducer/toggleAutoFollowReducer.ts +0 -12
  195. package/src/client/vzReducer/updatePane.ts +0 -40
  196. package/src/client/vzReducer/updatePresenceIndicatorReducer.ts +0 -30
  197. package/src/client/vzReducer/visualEditorReducer.ts +0 -9
  198. package/src/reactRouterExports.ts +0 -15
  199. package/src/runCode.ts +0 -27
  200. package/src/server/aiChatHandler/aiEditing.ts +0 -152
  201. package/src/server/aiChatHandler/chatOperations.ts +0 -510
  202. package/src/server/aiChatHandler/errorHandling.ts +0 -66
  203. package/src/server/aiChatHandler/index.ts +0 -200
  204. package/src/server/aiChatHandler/llmStreaming.ts +0 -419
  205. package/src/server/aiChatHandler/undoHandler.ts +0 -97
  206. package/src/server/aiChatHandler/validation.ts +0 -24
  207. package/src/server/computeInitialDocument.ts +0 -220
  208. package/src/server/generateAIResponse.ts +0 -188
  209. package/src/server/handleAIAssist.ts +0 -53
  210. package/src/server/handleAIChatUndo.ts +0 -2
  211. package/src/server/handleAICopilot.ts +0 -97
  212. package/src/server/index.ts +0 -388
  213. package/src/server/livekit.ts +0 -24
  214. package/src/server/prettier.ts +0 -115
  215. package/src/submitOperation.ts +0 -25
  216. package/src/types.ts +0 -205
  217. package/src/utils/fileDiff.ts +0 -117
  218. package/src/vite-env.d.ts +0 -10
  219. /package/{src/server/handleAIChatMessage.ts → dist/server/handleAIChatMessage.js} +0 -0
  220. /package/{src/server/isDirectory.ts → dist/server/isDirectory.js} +0 -0
@@ -1,282 +0,0 @@
1
- import {
2
- useCallback,
3
- useContext,
4
- useState,
5
- useRef,
6
- useEffect,
7
- } from 'react';
8
- import { VZCodeContext } from '../VZCodeContext';
9
- import { VizContent, VizFileId } from '@vizhub/viz-types';
10
- import { VisualEditorConfigEntry } from '../../types';
11
- import { EmptyState } from './EmptyState';
12
-
13
- const CONFIG_FILE_NAME = 'config.json';
14
-
15
- // Helper function to calculate percentage for progress fill
16
- const calculatePercentage = (
17
- value: number,
18
- min: number,
19
- max: number,
20
- ) => {
21
- return ((value - min) / (max - min)) * 100;
22
- };
23
-
24
- // Helper function to format values nicely
25
- const formatValue = (
26
- value: number,
27
- min: number,
28
- max: number,
29
- ) => {
30
- // Determine decimal places based on the range
31
- const range = max - min;
32
- const decimalPlaces =
33
- range < 10 ? 2 : range < 100 ? 1 : 0;
34
- return Number(value).toFixed(decimalPlaces);
35
- };
36
-
37
- export const VisualEditor = () => {
38
- const { files, submitOperation, iframeRef } =
39
- useContext(VZCodeContext);
40
-
41
- // Local state to track slider values during user interaction
42
- const [localValues, setLocalValues] = useState<{
43
- [key: string]: number;
44
- }>({});
45
-
46
- let configFileId: VizFileId | null = null;
47
- for (const fileId in files) {
48
- if (files[fileId].name === CONFIG_FILE_NAME) {
49
- configFileId = fileId;
50
- break;
51
- }
52
- }
53
-
54
- if (configFileId === null) {
55
- return (
56
- <EmptyState>
57
- To begin using the visual editor, create a
58
- config.json.
59
- </EmptyState>
60
- );
61
- }
62
-
63
- let configData;
64
-
65
- try {
66
- configData = JSON.parse(files[configFileId].text);
67
- } catch (error) {
68
- return (
69
- <EmptyState>
70
- Your config.json file is not valid json.
71
- </EmptyState>
72
- );
73
- }
74
-
75
- if (!('visualEditorWidgets' in configData)) {
76
- return (
77
- <EmptyState>
78
- To begin using the visual editor, make sure your
79
- config.json has a key called "visualEditorWidgets",
80
- whose value is the config for the visual editor.
81
- </EmptyState>
82
- );
83
- }
84
-
85
- if (!Array.isArray(configData.visualEditorWidgets)) {
86
- return (
87
- <EmptyState>
88
- Your config.json file has "visualEditorWidgets" but
89
- it is not an array. Please make sure
90
- "visualEditorWidgets" is an array of widget
91
- configurations.
92
- </EmptyState>
93
- );
94
- }
95
-
96
- const onSliderChange = useCallback(
97
- (property: string) =>
98
- (event: React.ChangeEvent<HTMLInputElement>) => {
99
- const newValue = parseFloat(
100
- event.currentTarget.value,
101
- );
102
-
103
- // Update local state immediately for responsive UI
104
- setLocalValues((prev) => ({
105
- ...prev,
106
- [property]: newValue,
107
- }));
108
-
109
- // Update config.json
110
- const newConfigData = {
111
- ...configData,
112
- [property]: newValue,
113
- };
114
-
115
- submitOperation((document: VizContent) => ({
116
- ...document,
117
- files: {
118
- ...files,
119
- [configFileId]: {
120
- name: 'config.json',
121
- text: JSON.stringify(newConfigData, null, 2),
122
- },
123
- },
124
- }));
125
- },
126
- [configData, files, configFileId, setLocalValues],
127
- );
128
-
129
- const visualEditorWidgets: VisualEditorConfigEntry[] =
130
- configData.visualEditorWidgets;
131
-
132
- // Sync local values with config data when it changes (including remote updates)
133
- useEffect(() => {
134
- const newLocalValues: { [key: string]: number } = {};
135
- visualEditorWidgets.forEach((widget) => {
136
- if (widget.type === 'number') {
137
- newLocalValues[widget.property] =
138
- configData[widget.property];
139
- }
140
- });
141
- setLocalValues(newLocalValues);
142
- }, [configData, visualEditorWidgets]);
143
-
144
- // Track previous config state to detect changes from any source (remote clients, text editor, etc.)
145
- const previousConfigRef = useRef<any>(null);
146
-
147
- // Detect config.json changes and send updates to iframe
148
- useEffect(() => {
149
- if (!configFileId || !files || !files[configFileId]) {
150
- return;
151
- }
152
-
153
- let newConfigData;
154
- try {
155
- newConfigData = JSON.parse(files[configFileId].text);
156
- } catch (error) {
157
- // If config is invalid JSON, we can't process changes
158
- return;
159
- }
160
-
161
- const previousConfig = previousConfigRef.current;
162
-
163
- // Update the ref with the new config
164
- previousConfigRef.current = newConfigData;
165
-
166
- // Skip processing if this is the first time or if there's no previous config
167
- if (!previousConfig) {
168
- return;
169
- }
170
-
171
- // Find changed top-level properties
172
- const changedProperties: { [key: string]: any } = {};
173
-
174
- // Check all properties in the new config
175
- for (const key in newConfigData) {
176
- if (newConfigData[key] !== previousConfig[key]) {
177
- // Deep comparison for objects to detect actual changes
178
- if (
179
- typeof newConfigData[key] === 'object' &&
180
- typeof previousConfig[key] === 'object'
181
- ) {
182
- if (
183
- JSON.stringify(newConfigData[key]) !==
184
- JSON.stringify(previousConfig[key])
185
- ) {
186
- changedProperties[key] = newConfigData[key];
187
- }
188
- } else {
189
- changedProperties[key] = newConfigData[key];
190
- }
191
- }
192
- }
193
-
194
- // Check for deleted properties (properties that existed before but don't exist now)
195
- for (const key in previousConfig) {
196
- if (!(key in newConfigData)) {
197
- changedProperties[key] = undefined;
198
- }
199
- }
200
-
201
- // Send changed properties to iframe if any changes were detected
202
- if (Object.keys(changedProperties).length > 0) {
203
- try {
204
- iframeRef.current.contentWindow.postMessage(
205
- changedProperties,
206
- );
207
- } catch (error) {
208
- console.error(
209
- 'Failed to send config changes to iframe:',
210
- error,
211
- );
212
- }
213
- }
214
- }, [files, configFileId, iframeRef]);
215
-
216
- return (
217
- <div className="visual-editor">
218
- {visualEditorWidgets.map((widgetConfig, index) => {
219
- if (widgetConfig.type === 'number') {
220
- // Use local value if available, otherwise fall back to config value
221
- const currentValue =
222
- localValues[widgetConfig.property] ??
223
- configData[widgetConfig.property];
224
- const percentage = calculatePercentage(
225
- currentValue,
226
- widgetConfig.min,
227
- widgetConfig.max,
228
- );
229
-
230
- return (
231
- <div
232
- key={widgetConfig.property}
233
- className="visual-editor-slider"
234
- >
235
- <div className="slider-header">
236
- <label
237
- htmlFor={widgetConfig.property}
238
- className="slider-label"
239
- >
240
- {widgetConfig.label}
241
- </label>
242
- <span className="slider-value">
243
- {formatValue(
244
- currentValue,
245
- widgetConfig.min,
246
- widgetConfig.max,
247
- )}
248
- </span>
249
- </div>
250
- <div className="slider-container">
251
- <input
252
- type="range"
253
- id={widgetConfig.property}
254
- className="slider-input"
255
- min={widgetConfig.min}
256
- max={widgetConfig.max}
257
- step="any"
258
- value={currentValue}
259
- onChange={onSliderChange(
260
- widgetConfig.property,
261
- )}
262
- />
263
- <div
264
- className="slider-track-fill"
265
- style={{ width: `${percentage}%` }}
266
- />
267
- </div>
268
- <div className="slider-bounds">
269
- <span className="min-value">
270
- {widgetConfig.min}
271
- </span>
272
- <span className="max-value">
273
- {widgetConfig.max}
274
- </span>
275
- </div>
276
- </div>
277
- );
278
- }
279
- })}
280
- </div>
281
- );
282
- };
@@ -1,121 +0,0 @@
1
- import {
2
- ParticipantLoop,
3
- ParticipantName,
4
- useParticipants,
5
- useRoomContext,
6
- } from '@livekit/components-react';
7
- import { useContext, useState } from 'react';
8
- import { Button, Form, Modal } from 'react-bootstrap';
9
- import { v4 } from 'uuid';
10
- import { VZCodeContext } from '../VZCodeContext';
11
-
12
- export function VoiceChatModal() {
13
- const {
14
- liveKitRoomName,
15
- setLiveKitRoom,
16
- liveKitToken,
17
- setLiveKitToken,
18
- liveKitConnection,
19
- setLiveKitConnection,
20
- voiceChatModalOpen,
21
- setVoiceChatModalOpen,
22
- } = useContext(VZCodeContext);
23
- const participants = useParticipants();
24
-
25
- const [roomName, setRoomName] = useState(
26
- liveKitRoomName || '',
27
- );
28
- const [username, setUsername] = useState('');
29
- const room = useRoomContext();
30
-
31
- const handleConnect = () => {
32
- if (liveKitConnection) {
33
- setLiveKitConnection(false);
34
- setLiveKitRoom(`${v4()}`);
35
- setLiveKitToken('');
36
- room.disconnect(true);
37
- return;
38
- }
39
- setLiveKitRoom(roomName);
40
- const fetchToken = async () => {
41
- try {
42
- const res = await fetch(
43
- `/livekit-token?room=${roomName}&username=${username}`,
44
- {
45
- method: 'GET',
46
- },
47
- );
48
- const tokenResponse = await res.text();
49
- setLiveKitToken(tokenResponse);
50
- setLiveKitConnection(true);
51
- } catch (error) {
52
- console.error('Error fetching token:', error);
53
- }
54
- };
55
-
56
- fetchToken();
57
- };
58
-
59
- const handleClose = () => {
60
- setVoiceChatModalOpen(false);
61
- };
62
-
63
- return (
64
- <Modal
65
- className="vz-settings"
66
- show={voiceChatModalOpen}
67
- onHide={handleClose}
68
- animation={false}
69
- >
70
- <Modal.Header closeButton>
71
- <Modal.Title>Connect to LiveKit Room</Modal.Title>
72
- </Modal.Header>
73
- <Modal.Body>
74
- <Form>
75
- <Form.Group controlId="formRoomName">
76
- <Form.Label>Room Name</Form.Label>
77
- <Form.Control
78
- type="text"
79
- placeholder="Enter room name"
80
- value={roomName}
81
- onChange={(e) => setRoomName(e.target.value)}
82
- />
83
- </Form.Group>
84
- </Form>
85
- <Form>
86
- <Form.Group controlId="formUserName">
87
- <Form.Label>Username</Form.Label>
88
- <Form.Control
89
- type="text"
90
- placeholder="Enter Username"
91
- value={username}
92
- onChange={(e) => setUsername(e.target.value)}
93
- />
94
- </Form.Group>
95
- </Form>
96
- <div
97
- style={{
98
- display: 'flex',
99
- flexDirection: 'column',
100
- }}
101
- >
102
- <b>Users in Room: </b>
103
- <ParticipantLoop participants={participants}>
104
- <ParticipantName />
105
- </ParticipantLoop>
106
- </div>
107
- </Modal.Body>
108
- <Modal.Footer>
109
- <Button variant="secondary" onClick={handleClose}>
110
- Cancel
111
- </Button>
112
- <Button
113
- variant={liveKitConnection ? 'danger' : 'primary'}
114
- onClick={handleConnect}
115
- >
116
- {liveKitConnection ? 'Disconnect' : 'Connect'}
117
- </Button>
118
- </Modal.Footer>
119
- </Modal>
120
- );
121
- }
@@ -1,199 +0,0 @@
1
- import {
2
- formatMarkdownFiles,
3
- parseMarkdownFiles,
4
- } from 'llm-code-format';
5
- import {
6
- FORMAT_INSTRUCTIONS,
7
- mergeFileChanges,
8
- } from 'editcodewithai';
9
- import { VizFiles } from '@vizhub/viz-types';
10
- import {
11
- generateRunId,
12
- vizFilesToFileCollection,
13
- } from '@vizhub/viz-utils';
14
- import JSZip from 'jszip';
15
- import { generate } from '@langchain/core/dist/utils/fast-json-patch';
16
-
17
- export const createAICopyPasteHandlers = (
18
- files: VizFiles,
19
- submitOperation: any,
20
- setCopyButtonText: (text: string) => void,
21
- setPasteButtonText: (text: string) => void,
22
- setExportButtonText: (text: string) => void,
23
- ) => {
24
- // Copy for AI - formats all files and copies to clipboard
25
- const handleCopyForAI = async () => {
26
- if (!files || Object.keys(files).length === 0) {
27
- setCopyButtonText('No files to copy');
28
- setTimeout(
29
- () => setCopyButtonText('Copy for AI'),
30
- 2000,
31
- );
32
- return;
33
- }
34
-
35
- try {
36
- const fileCollection =
37
- vizFilesToFileCollection(files);
38
-
39
- // Format files for AI consumption
40
- const formattedFiles =
41
- formatMarkdownFiles(fileCollection) +
42
- '\n\n' +
43
- FORMAT_INSTRUCTIONS.whole;
44
-
45
- // Copy to clipboard
46
- await navigator.clipboard.writeText(formattedFiles);
47
-
48
- // Show success feedback
49
- setCopyButtonText('Copied!');
50
- setTimeout(
51
- () => setCopyButtonText('Copy for AI'),
52
- 2000,
53
- );
54
- } catch (error) {
55
- console.error('Failed to copy files for AI:', error);
56
- setCopyButtonText('Error');
57
- setTimeout(
58
- () => setCopyButtonText('Copy for AI'),
59
- 2000,
60
- );
61
- }
62
- };
63
-
64
- // Paste for AI - parses clipboard content and updates files
65
- const handlePasteForAI = async () => {
66
- if (!submitOperation) return;
67
-
68
- try {
69
- // Read from clipboard
70
- const clipboardText =
71
- await navigator.clipboard.readText();
72
-
73
- // Handle various line endings
74
- const normalized = clipboardText.replace(
75
- /\r\n?/g,
76
- '\n',
77
- );
78
-
79
- if (!normalized.trim()) {
80
- setPasteButtonText('Empty clipboard');
81
- setTimeout(
82
- () => setPasteButtonText('Paste for AI'),
83
- 2000,
84
- );
85
- return;
86
- }
87
-
88
- // Preprocess to remove formatting instructions section to avoid creating extra files
89
- const preprocessed = normalized
90
- .split('## Formatting Instructions')[0]
91
- .trim();
92
-
93
- // Parse the markdown files format
94
- const parsed = parseMarkdownFiles(
95
- preprocessed,
96
- 'bold',
97
- );
98
-
99
- if (
100
- parsed.files &&
101
- Object.keys(parsed.files).length > 0
102
- ) {
103
- // Use mergeFileChanges utility from editcodewithai
104
- const mergedFiles = mergeFileChanges(
105
- files || {},
106
- parsed.files,
107
- );
108
-
109
- // Update files using the submit operation
110
- submitOperation((document) => ({
111
- ...document,
112
- files: mergedFiles,
113
- runId: generateRunId(),
114
- }));
115
-
116
- const fileCount = Object.keys(parsed.files).length;
117
- setPasteButtonText('Pasted!');
118
- setTimeout(
119
- () => setPasteButtonText('Paste for AI'),
120
- 2000,
121
- );
122
- } else {
123
- setPasteButtonText('No files found');
124
- setTimeout(
125
- () => setPasteButtonText('Paste for AI'),
126
- 2000,
127
- );
128
- }
129
- } catch (error) {
130
- console.error(
131
- 'Failed to paste files from AI:',
132
- error,
133
- );
134
- setPasteButtonText('Error');
135
- setTimeout(
136
- () => setPasteButtonText('Paste for AI'),
137
- 2000,
138
- );
139
- }
140
- };
141
-
142
- // Export to ZIP - creates and downloads a ZIP file with all viz files
143
- const handleExportToZip = async () => {
144
- if (!files || Object.keys(files).length === 0) {
145
- setExportButtonText('No files to export');
146
- setTimeout(
147
- () => setExportButtonText('Export to ZIP'),
148
- 2000,
149
- );
150
- return;
151
- }
152
-
153
- try {
154
- // Create the ZIP
155
- const zip = new JSZip();
156
-
157
- // Add each file to the ZIP
158
- Object.entries(files).forEach(([fileId, file]) => {
159
- const fileName = file.name || fileId;
160
- const fileContent = file.text || '';
161
- zip.file(fileName, fileContent);
162
- });
163
-
164
- // Generate and download
165
- const blob = await zip.generateAsync({
166
- type: 'blob',
167
- });
168
- const url = URL.createObjectURL(blob);
169
- const a = document.createElement('a');
170
- a.href = url;
171
- a.download = 'viz-files.zip';
172
- a.click();
173
- URL.revokeObjectURL(url);
174
-
175
- // Show success feedback
176
- setExportButtonText('Exported!');
177
- setTimeout(
178
- () => setExportButtonText('Export to ZIP'),
179
- 2000,
180
- );
181
- } catch (error) {
182
- console.error(
183
- 'Failed to export files to ZIP:',
184
- error,
185
- );
186
- setExportButtonText('Error');
187
- setTimeout(
188
- () => setExportButtonText('Export to ZIP'),
189
- 2000,
190
- );
191
- }
192
- };
193
-
194
- return {
195
- handleCopyForAI,
196
- handlePasteForAI,
197
- handleExportToZip,
198
- };
199
- };