vzcode 1.59.0 → 1.60.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.
@@ -1,237 +1,33 @@
1
1
  import {
2
- Context,
3
- createContext,
4
2
  useCallback,
5
3
  useReducer,
6
4
  useRef,
7
5
  useState,
8
6
  } from 'react';
7
+ import { VizContent } from '@vizhub/viz-types';
8
+ import { defaultTheme, useDynamicTheme } from '../themes';
9
+ import { useActions } from '../useActions';
10
+ import { useEditorCache } from '../useEditorCache';
11
+ import { useFileCRUD } from '../useFileCRUD';
12
+ import { useKeyboardShortcuts } from '../useKeyboardShortcuts';
13
+ import { useOpenDirectories } from '../useOpenDirectories';
14
+ import { usePrettier } from '../usePrettier';
15
+ import { useRunCode } from '../useRunCode';
16
+ import { useRuntimeError } from '../useRuntimeError';
17
+ import { useURLSync } from '../useURLSync';
9
18
  import {
10
- ItemId,
11
- LeafPane,
12
- Pane,
13
- PaneId,
14
- PresenceIndicator,
15
- SearchFileVisibility,
16
- SearchResults,
17
- ShareDBDoc,
18
- SubmitOperation,
19
- TabState,
20
- Username,
21
- } from '../types';
22
- import { VizFiles, VizContent } from '@vizhub/viz-types';
23
- import {
24
- ThemeLabel,
25
- defaultTheme,
26
- useDynamicTheme,
27
- } from './themes';
28
- import { useActions } from './useActions';
29
- import {
30
- EditorCache,
31
- useEditorCache,
32
- } from './useEditorCache';
33
- import { useFileCRUD } from './useFileCRUD';
34
- import { useKeyboardShortcuts } from './useKeyboardShortcuts';
35
- import { useOpenDirectories } from './useOpenDirectories';
36
- import { usePrettier } from './usePrettier';
37
- import { useRunCode } from './useRunCode';
38
- import { useRuntimeError } from './useRuntimeError';
39
- import { useURLSync } from './useURLSync';
40
- import { createInitialState, vzReducer } from './vzReducer';
41
- import { findPane } from './vzReducer/findPane';
42
- import { usePresenceAutoFollow } from './usePresenceAutoFollow';
19
+ createInitialState,
20
+ vzReducer,
21
+ } from '../vzReducer';
22
+ import { findPane } from '../vzReducer/findPane';
23
+ import { usePresenceAutoFollow } from '../usePresenceAutoFollow';
43
24
  import { v4 as uuidv4 } from 'uuid';
25
+ import {
26
+ VZCodeContextValue,
27
+ VZCodeProviderProps,
28
+ } from './types';
44
29
 
45
- // This context centralizes all the "smart" logic
46
- // to do with the application state. This includes
47
- // * Accessing and manipulating ShareDB data
48
- // * Centralized application state
49
- export const VZCodeContext =
50
- createContext<VZCodeContextValue>(null);
51
-
52
- // The type of the object provided by this context.
53
- export type VZCodeContextValue = {
54
- content: VizContent | null;
55
- shareDBDoc: ShareDBDoc<VizContent> | null;
56
- submitOperation: (
57
- next: (content: VizContent) => VizContent,
58
- ) => void;
59
- // TODO pull in this type from ShareDB if possible
60
- localPresence: any;
61
- // TODO pull in this type from ShareDB if possible
62
- docPresence: any;
63
-
64
- files: VizFiles | null;
65
- createFile: (fileName: string, text?: string) => void;
66
- renameFile: (fileId: string, fileName: string) => void;
67
- deleteFile: (fileId: string) => void;
68
- createDirectory: (
69
- fileName: string,
70
- text?: string,
71
- ) => void;
72
- renameDirectory: (
73
- directoryId: string,
74
- directoryOldName: string,
75
- directoryName: string,
76
- ) => void;
77
- deleteDirectory: (directoryId: string) => void;
78
-
79
- setActiveFileId: (fileId: string | null) => void;
80
- setActiveFileLeft: () => void;
81
- setActiveFileRight: () => void;
82
-
83
- activePaneId: PaneId;
84
- pane: Pane;
85
- activePane: LeafPane;
86
-
87
- openTab: (tabState: TabState) => void;
88
- closeTabs: (fileIds: string[]) => void;
89
-
90
- isSettingsOpen: boolean;
91
- setIsSettingsOpen: (isSettingsOpen: boolean) => void;
92
- closeSettings: () => void;
93
-
94
- isDocOpen: boolean;
95
- setIsDocOpen: (isDocOpen: boolean) => void;
96
- closeDoc: () => void;
97
-
98
- theme: ThemeLabel;
99
- setTheme: (theme: ThemeLabel) => void;
100
-
101
- username: Username;
102
- setUsername: (username: Username) => void;
103
-
104
- isDirectoryOpen: (path: string) => boolean;
105
- toggleDirectory: (path: string) => void;
106
-
107
- editorCache: EditorCache;
108
-
109
- // Whether the editor should be focused.
110
- editorWantsFocus: boolean;
111
- // Signals that the editor no longer wants focus.
112
- editorNoLongerWantsFocus: () => void;
113
-
114
- errorMessage: string | null;
115
-
116
- // Runtime error handling
117
- handleRuntimeError: (
118
- formattedErrorMessage: string,
119
- ) => void;
120
- clearRuntimeError: () => void;
121
-
122
- search: SearchResults;
123
- isSearchOpen: boolean;
124
- setIsSearchOpen: (isSearchOpen: boolean) => void;
125
- setSearch: (pattern: string) => void;
126
-
127
- isAIChatOpen: boolean;
128
- setIsAIChatOpen: (isAIChatOpen: boolean) => void;
129
- aiChatFocused: boolean;
130
- toggleAIChatFocused: () => void;
131
- aiChatMode: 'ask' | 'edit';
132
- setAIChatMode: (mode: 'ask' | 'edit') => void;
133
- aiChatEndpoint?: string;
134
- aiChatUndoEndpoint?: string;
135
- aiChatOptions?: { [key: string]: any };
136
- setSearchResults: (files: ShareDBDoc<VizContent>) => void;
137
- setSearchFileVisibility: (
138
- files: ShareDBDoc<VizContent>,
139
- id: string,
140
- visibility: SearchFileVisibility,
141
- ) => void;
142
- setSearchLineVisibility: (
143
- files: ShareDBDoc<VizContent>,
144
- id: string,
145
- line: number,
146
- ) => void;
147
- setSearchFocusedIndex: (
148
- focusedIndex: number,
149
- childIndex: number,
150
- ) => void;
151
- toggleSearchFocused: () => void;
152
-
153
- isCreateFileModalOpen: boolean;
154
- handleOpenCreateFileModal: () => void;
155
- handleCloseCreateFileModal: () => void;
156
- handleCreateFileClick: (newFileName: string) => void;
157
-
158
- isCreateDirModalOpen: boolean;
159
- handleOpenCreateDirModal: () => void;
160
- handleCloseCreateDirModal: () => void;
161
- handleCreateDirClick: (newFileName: string) => void;
162
-
163
- runPrettierRef: React.MutableRefObject<
164
- null | (() => void)
165
- >;
166
- runCodeRef: React.MutableRefObject<
167
- null | ((hardRerun?: boolean) => void)
168
- >;
169
-
170
- sidebarRef: React.RefObject<HTMLDivElement>;
171
-
172
- codeEditorRef: React.RefObject<HTMLDivElement>;
173
-
174
- connected: boolean;
175
- pending: boolean;
176
-
177
- hoveredItemId: ItemId | null;
178
- setHoveredItemId: (itemId: ItemId | null) => void;
179
-
180
- enableAutoFollow: boolean;
181
- toggleAutoFollow: () => void;
182
-
183
- updatePresenceIndicator: (
184
- presenceIndicator: PresenceIndicator,
185
- ) => void;
186
-
187
- sidebarPresenceIndicators: Array<PresenceIndicator>;
188
- splitCurrentPane: () => void;
189
-
190
- liveKitToken: string;
191
- setLiveKitToken: (state: string) => void;
192
- liveKitRoomName: string;
193
- setLiveKitRoom: (state: string) => void;
194
- liveKitConnection: boolean;
195
- setLiveKitConnection: (state: boolean) => void;
196
- voiceChatModalOpen: boolean;
197
- setVoiceChatModalOpen: (state: boolean) => void;
198
- aiChatMessage: string;
199
- setAIChatMessage: (message: string) => void;
200
- isLoading: boolean;
201
- setIsLoading: (state: boolean) => void;
202
- currentChatId: string;
203
- aiErrorMessage: string | null;
204
- setAIErrorMessage: (state: string | null) => void;
205
- handleSendMessage: (
206
- messageToSend?: string,
207
- options?: Record<string, string>,
208
- ) => void;
209
-
210
- // Auto-fork functions for VizHub integration
211
- autoForkAndRetryAI?: (
212
- prompt: string,
213
- modelName: string,
214
- commitId?: string,
215
- ) => Promise<void>;
216
- clearStoredAIPrompt?: () => void;
217
- getStoredAIPrompt?: () => {
218
- prompt: string;
219
- modelName: string;
220
- } | null;
221
-
222
- // Additional widgets that can be rendered in AI chat messages
223
- additionalWidgets?: React.ComponentType<{
224
- messageId: string;
225
- chatId: string;
226
- canUndo: boolean;
227
- handleSendMessage?: (
228
- messageToSend?: string,
229
- options?: Record<string, string>,
230
- ) => void;
231
- }>;
232
- };
233
-
234
- export const VZCodeProvider = ({
30
+ export const useVZCodeState = ({
235
31
  content,
236
32
  shareDBDoc,
237
33
  submitOperation,
@@ -239,7 +35,6 @@ export const VZCodeProvider = ({
239
35
  docPresence,
240
36
  prettierWorker,
241
37
  initialUsername,
242
- children,
243
38
  codeError = null,
244
39
  connected,
245
40
  pending,
@@ -256,44 +51,11 @@ export const VZCodeProvider = ({
256
51
  clearStoredAIPrompt,
257
52
  getStoredAIPrompt,
258
53
  additionalWidgets,
259
- }: {
260
- content: VizContent;
261
- shareDBDoc: ShareDBDoc<VizContent>;
262
- submitOperation: SubmitOperation;
263
- localPresence: any;
264
- docPresence: any;
265
- prettierWorker: Worker;
266
- initialUsername: Username;
267
- children: React.ReactNode;
268
- codeError?: string | null;
269
- connected?: boolean;
270
- pending?: boolean;
271
- liveKitToken?: string | undefined;
272
- setLiveKitToken?: (state: string) => void;
273
- liveKitRoomName?: string | undefined;
274
- setLiveKitRoom?: (state: string) => void;
275
- liveKitConnection?: boolean;
276
- setLiveKitConnection?: (state: boolean) => void;
277
- aiChatEndpoint?: string;
278
- aiChatUndoEndpoint?: string;
279
- aiChatOptions?: { [key: string]: any };
280
- autoForkAndRetryAI?: (
281
- prompt: string,
282
- modelName: string,
283
- commitId?: string,
284
- ) => Promise<void>;
285
- clearStoredAIPrompt?: () => void;
286
- getStoredAIPrompt?: () => {
287
- prompt: string;
288
- modelName: string;
289
- } | null;
290
- additionalWidgets?: React.ComponentType<{
291
- messageId: string;
292
- chatId: string;
293
- canUndo: boolean;
294
- }>;
295
- }) => {
296
- // Auto-run Pretter after local changes.
54
+ }: Omit<
55
+ VZCodeProviderProps,
56
+ 'children'
57
+ >): VZCodeContextValue => {
58
+ // Auto-run Prettier after local changes.
297
59
  const { prettierError, runPrettierRef } = usePrettier({
298
60
  shareDBDoc,
299
61
  submitOperation,
@@ -336,8 +98,6 @@ export const VZCodeProvider = ({
336
98
  );
337
99
 
338
100
  // Unpack state.
339
- // print the state object to see what it contains
340
- // console.log('state: ', state);
341
101
  const {
342
102
  pane,
343
103
  activePaneId,
@@ -355,7 +115,7 @@ export const VZCodeProvider = ({
355
115
  aiChatMode,
356
116
  } = state;
357
117
 
358
- const activePane: Pane = findPane(pane, activePaneId);
118
+ const activePane = findPane(pane, activePaneId);
359
119
  if (activePane.type !== 'leafPane') {
360
120
  // Should never happen
361
121
  throw new Error('Expected leafPane');
@@ -400,12 +160,11 @@ export const VZCodeProvider = ({
400
160
  });
401
161
 
402
162
  // The set of open directories.
403
- // TODO move this into reducer/useActions
404
163
  const { isDirectoryOpen, toggleDirectory } =
405
164
  useOpenDirectories({ activePane, content });
406
165
 
407
166
  // Cache of CodeMirror editors by file id.
408
- const editorCache: EditorCache = useEditorCache();
167
+ const editorCache = useEditorCache();
409
168
 
410
169
  // Handle dynamic theme changes.
411
170
  useDynamicTheme(editorCache, theme);
@@ -467,13 +226,10 @@ export const VZCodeProvider = ({
467
226
  );
468
227
 
469
228
  // Isolate the files object from the document.
470
- const files: VizFiles | null = content
471
- ? content.files
472
- : null;
229
+ const files = content ? content.files : null;
473
230
 
474
231
  useKeyboardShortcuts({
475
232
  closeTabs,
476
- // TODO verify that this makes sense
477
233
  activeFileId: activePane.activeFileId,
478
234
  activePaneId,
479
235
  handleOpenCreateFileModal,
@@ -488,12 +244,9 @@ export const VZCodeProvider = ({
488
244
  });
489
245
 
490
246
  // Track the currently hovered file id.
491
- const [hoveredItemId, setHoveredItemId] =
492
- useState<ItemId | null>(null);
247
+ const [hoveredItemId, setHoveredItemId] = useState(null);
493
248
 
494
249
  // Handle presence-based auto-following
495
- // This hook manages opening tabs when presence is received on files
496
- // that are not currently open, independent of CodeMirror extensions
497
250
  usePresenceAutoFollow({
498
251
  docPresence,
499
252
  enableAutoFollow,
@@ -502,7 +255,6 @@ export const VZCodeProvider = ({
502
255
  });
503
256
 
504
257
  // Livekit Voice Chat Modal
505
-
506
258
  const [voiceChatModalOpen, setVoiceChatModalOpen] =
507
259
  useState(false);
508
260
 
@@ -545,7 +297,6 @@ export const VZCodeProvider = ({
545
297
  setAIErrorMessage(null); // Clear any previous errors
546
298
 
547
299
  // Call backend endpoint for AI response
548
- // The server will handle all ShareDB operations including adding the user message
549
300
  try {
550
301
  const response = await fetch(aiChatEndpoint, {
551
302
  method: 'POST',
@@ -579,7 +330,7 @@ export const VZCodeProvider = ({
579
330
 
580
331
  // Check if this is the specific permission error that should trigger auto-fork
581
332
  if (
582
- aiErrorMessage ===
333
+ errorMessage ===
583
334
  'You do not have permission to use AI chat on this visualization. Only users with edit access can use this feature. Fork the viz to edit it.'
584
335
  ) {
585
336
  // Trigger auto-fork instead of showing error
@@ -600,7 +351,7 @@ export const VZCodeProvider = ({
600
351
  }
601
352
 
602
353
  // For other errors, show the error message
603
- setAIErrorMessage(aiErrorMessage);
354
+ setAIErrorMessage(errorMessage);
604
355
  return;
605
356
  }
606
357
 
@@ -625,8 +376,8 @@ export const VZCodeProvider = ({
625
376
  ],
626
377
  );
627
378
 
628
- // The value provided by this context.
629
- const value: VZCodeContextValue = {
379
+ // Return the context value
380
+ return {
630
381
  content,
631
382
  shareDBDoc,
632
383
  submitOperation,
@@ -750,10 +501,4 @@ export const VZCodeProvider = ({
750
501
  // Additional widgets that can be rendered in AI chat messages
751
502
  additionalWidgets,
752
503
  };
753
-
754
- return (
755
- <VZCodeContext.Provider value={value}>
756
- {children}
757
- </VZCodeContext.Provider>
758
- );
759
504
  };
@@ -6,7 +6,7 @@ import './styles.scss';
6
6
 
7
7
  const DEBUG = false;
8
8
 
9
- const showSuggestedRequests = true;
9
+ const showSuggestedRequests = false;
10
10
 
11
11
  export const AIChat = () => {
12
12
  const {
@@ -17,6 +17,8 @@
17
17
  overflow-y: auto;
18
18
  padding: 10px;
19
19
  padding-bottom: 0;
20
+ display: flex;
21
+ flex-direction: column;
20
22
  }
21
23
 
22
24
  .ai-chat-input-fixed {