vzcode 2.3.0 → 2.4.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/package.json +3 -2
- package/src/cli.ts +208 -0
- package/src/client/AIAssist/AIAssistCodeMirrorKeyMap.ts +42 -0
- package/src/client/AIAssist/AIAssistWidget/index.tsx +135 -0
- package/src/client/AIAssist/AIAssistWidget/style.scss +47 -0
- package/src/client/AIAssist/Spinner.jsx +76 -0
- package/src/client/AIAssist/formatFile.ts +27 -0
- package/src/client/AIAssist/generateFilesContext.ts +25 -0
- package/src/client/AIAssist/index.ts +2 -0
- package/src/client/AIAssist/startAIAssist.ts +95 -0
- package/src/client/App/index.tsx +152 -0
- package/src/client/App/style.scss +82 -0
- package/src/client/App/usePending.ts +51 -0
- package/src/client/App/useShareDB.ts +161 -0
- package/src/client/CodeEditor/Copilot/index.ts +74 -0
- package/src/client/CodeEditor/InteractiveWidgets/boolToggler.ts +12 -0
- package/src/client/CodeEditor/InteractiveWidgets/colorPicker.ts +68 -0
- package/src/client/CodeEditor/InteractiveWidgets/colorsInTextPlugin.ts +174 -0
- package/src/client/CodeEditor/InteractiveWidgets/highlightWidgets.ts +79 -0
- package/src/client/CodeEditor/InteractiveWidgets/index.ts +44 -0
- package/src/client/CodeEditor/InteractiveWidgets/markdownCheckboxToggler.ts +12 -0
- package/src/client/CodeEditor/InteractiveWidgets/numberDragger.ts +20 -0
- package/src/client/CodeEditor/InteractiveWidgets/rotateWidget.ts +143 -0
- package/src/client/CodeEditor/InteractiveWidgets/urlClicker.test.ts +48 -0
- package/src/client/CodeEditor/InteractiveWidgets/urlClicker.ts +12 -0
- package/src/client/CodeEditor/InteractiveWidgets/vec2Slider.ts +25 -0
- package/src/client/CodeEditor/basicSetup.ts +73 -0
- package/src/client/CodeEditor/getOrCreateEditor.tsx +615 -0
- package/src/client/CodeEditor/index.tsx +202 -0
- package/src/client/CodeEditor/json1PresenceBroadcast.ts +41 -0
- package/src/client/CodeEditor/json1PresenceDisplay.ts +350 -0
- package/src/client/CodeEditor/rainbowBrackets.ts +122 -0
- package/src/client/CodeEditor/style.scss +156 -0
- package/src/client/CodeEditor/typescriptExtension/worker.ts +32 -0
- package/src/client/CodeErrorOverlay/index.tsx +77 -0
- package/src/client/CodeErrorOverlay/style.scss +33 -0
- package/src/client/Fonts/fonts.ts +8 -0
- package/src/client/Icons/AdjustmentSVG.tsx +19 -0
- package/src/client/Icons/BugSVG.tsx +20 -0
- package/src/client/Icons/CloseSVG.tsx +19 -0
- package/src/client/Icons/CssSVG.tsx +16 -0
- package/src/client/Icons/DirectoryArrowSVG.tsx +19 -0
- package/src/client/Icons/EditSVG.tsx +19 -0
- package/src/client/Icons/FileSVG.tsx +19 -0
- package/src/client/Icons/FolderSVG.tsx +20 -0
- package/src/client/Icons/GearSVG.tsx +16 -0
- package/src/client/Icons/HtmlSVG.tsx +16 -0
- package/src/client/Icons/JavaScriptSVG.tsx +16 -0
- package/src/client/Icons/JsonSVG.tsx +16 -0
- package/src/client/Icons/MarkdownSVG.tsx +16 -0
- package/src/client/Icons/MicOffSVG.tsx +35 -0
- package/src/client/Icons/MicSVG.tsx +25 -0
- package/src/client/Icons/NewSVG.tsx +19 -0
- package/src/client/Icons/PinSVG.tsx +14 -0
- package/src/client/Icons/PlaySVG.tsx +16 -0
- package/src/client/Icons/QuestionMarkSVG.tsx +18 -0
- package/src/client/Icons/ReactSVG.tsx +16 -0
- package/src/client/Icons/SearchSVG.tsx +20 -0
- package/src/client/Icons/SparklesSVG.tsx +23 -0
- package/src/client/Icons/SplitEditorSVG.tsx +34 -0
- package/src/client/Icons/StopSVG.tsx +15 -0
- package/src/client/Icons/SvelteSVG.tsx +16 -0
- package/src/client/Icons/TrashSVG.tsx +19 -0
- package/src/client/Icons/TypeScriptSVG.tsx +16 -0
- package/src/client/Icons/index.tsx +26 -0
- package/src/client/ImageViewer/index.tsx +91 -0
- package/src/client/ImageViewer/style.scss +41 -0
- package/src/client/PresenceNotifications/PresenceNotifications.test.ts +134 -0
- package/src/client/PresenceNotifications/index.tsx +158 -0
- package/src/client/PresenceNotifications/style.scss +17 -0
- package/src/client/RunCodeWidget/index.tsx +117 -0
- package/src/client/RunCodeWidget/style.scss +24 -0
- package/src/client/SplitPaneResizeContext.tsx +159 -0
- package/src/client/TabList/Tab.tsx +73 -0
- package/src/client/TabList/index.tsx +35 -0
- package/src/client/TabList/style.scss +51 -0
- package/src/client/VZCodeContext/index.tsx +29 -0
- package/src/client/VZCodeContext/types.ts +248 -0
- package/src/client/VZCodeContext/useVZCodeState.ts +602 -0
- package/src/client/VZKeyboardShortcutsDoc.tsx +148 -0
- package/src/client/VZLeft.tsx +28 -0
- package/src/client/VZMiddle.tsx +172 -0
- package/src/client/VZResizer/index.tsx +128 -0
- package/src/client/VZResizer/styles.scss +33 -0
- package/src/client/VZRight.tsx +113 -0
- package/src/client/VZSettings.tsx +275 -0
- package/src/client/VZSidebar/AIChat/ChatInput.tsx +243 -0
- package/src/client/VZSidebar/AIChat/DiffView.scss +136 -0
- package/src/client/VZSidebar/AIChat/DiffView.tsx +176 -0
- package/src/client/VZSidebar/AIChat/Message.tsx +79 -0
- package/src/client/VZSidebar/AIChat/MessageList.tsx +190 -0
- package/src/client/VZSidebar/AIChat/StreamingMessage.tsx +35 -0
- package/src/client/VZSidebar/AIChat/ThinkingScratchpad.tsx +156 -0
- package/src/client/VZSidebar/AIChat/TypingIndicator.tsx +19 -0
- package/src/client/VZSidebar/AIChat/index.tsx +357 -0
- package/src/client/VZSidebar/AIChat/styles.scss +646 -0
- package/src/client/VZSidebar/AIChat/useSpeechRecognition.ts +117 -0
- package/src/client/VZSidebar/CreateDirModal.tsx +111 -0
- package/src/client/VZSidebar/CreateFileModal.tsx +111 -0
- package/src/client/VZSidebar/DeleteConfirmationModal.tsx +76 -0
- package/src/client/VZSidebar/DirectoryListing.tsx +89 -0
- package/src/client/VZSidebar/EmptyState.tsx +11 -0
- package/src/client/VZSidebar/FileListing.tsx +91 -0
- package/src/client/VZSidebar/FileTypeIcon.tsx +49 -0
- package/src/client/VZSidebar/Item.tsx +237 -0
- package/src/client/VZSidebar/Listing.tsx +47 -0
- package/src/client/VZSidebar/Search.tsx +527 -0
- package/src/client/VZSidebar/VisualEditor.tsx +282 -0
- package/src/client/VZSidebar/VoiceChatModal.tsx +121 -0
- package/src/client/VZSidebar/aiCopyPaste.ts +199 -0
- package/src/client/VZSidebar/index.tsx +728 -0
- package/src/client/VZSidebar/styles.scss +612 -0
- package/src/client/VZSidebar/useDragAndDrop.tsx +408 -0
- package/src/client/bootstrap.ts +26 -0
- package/src/client/buildWorker.ts +3 -0
- package/src/client/featureFlags.ts +8 -0
- package/src/client/generateRequestId.ts +6 -0
- package/src/client/getFileTree.ts +53 -0
- package/src/client/index.ts +19 -0
- package/src/client/main.jsx +10 -0
- package/src/client/presenceColor.ts +8 -0
- package/src/client/shouldTriggerRun.ts +31 -0
- package/src/client/sortFileTree.ts +21 -0
- package/src/client/tabsSearchParameters.test.ts +79 -0
- package/src/client/tabsSearchParameters.ts +137 -0
- package/src/client/themes/index.ts +7 -0
- package/src/client/themes/themes.ts +77 -0
- package/src/client/themes/uiwImports.ts +32 -0
- package/src/client/themes/useDynamicTheme.ts +29 -0
- package/src/client/themes/vizhubTheme/colors.ts +80 -0
- package/src/client/themes/vizhubTheme/index.ts +193 -0
- package/src/client/useActions.ts +288 -0
- package/src/client/useESLint/index.ts +72 -0
- package/src/client/useESLint/worker.ts +113 -0
- package/src/client/useEditorCache.ts +35 -0
- package/src/client/useFileCRUD.ts +228 -0
- package/src/client/useKeyboardShortcuts.ts +451 -0
- package/src/client/useOpenDirectories.ts +99 -0
- package/src/client/usePresenceAutoFollow.ts +85 -0
- package/src/client/usePrettier/index.ts +178 -0
- package/src/client/usePrettier/worker.ts +109 -0
- package/src/client/useRunCode.tsx +15 -0
- package/src/client/useRuntimeError.ts +32 -0
- package/src/client/useSubmitOperation.ts +15 -0
- package/src/client/useURLSync.ts +137 -0
- package/src/client/usernameLocalStorage.ts +43 -0
- package/src/client/utils/fileExtension.ts +10 -0
- package/src/client/utils/isImageFile.ts +12 -0
- package/src/client/vzReducer/aiChatReducer.ts +44 -0
- package/src/client/vzReducer/closeTabReducer.test.ts +205 -0
- package/src/client/vzReducer/closeTabsReducer.ts +96 -0
- package/src/client/vzReducer/createInitialState.ts +38 -0
- package/src/client/vzReducer/editorNoLongerWantsFocusReducer.ts +9 -0
- package/src/client/vzReducer/findPane.ts +19 -0
- package/src/client/vzReducer/index.ts +250 -0
- package/src/client/vzReducer/openTabReducer.test.ts +127 -0
- package/src/client/vzReducer/openTabReducer.ts +74 -0
- package/src/client/vzReducer/searchReducer.test.ts +292 -0
- package/src/client/vzReducer/searchReducer.ts +181 -0
- package/src/client/vzReducer/setActiveFileIdReducer.ts +28 -0
- package/src/client/vzReducer/setActiveFileLeftRightReducer.ts +76 -0
- package/src/client/vzReducer/setIsDocOpenReducer.ts +9 -0
- package/src/client/vzReducer/setIsSettingsOpenReducer.ts +9 -0
- package/src/client/vzReducer/setThemeReducer.ts +9 -0
- package/src/client/vzReducer/setUsernameReducer.ts +9 -0
- package/src/client/vzReducer/splitCurrentPaneReducer.ts +66 -0
- package/src/client/vzReducer/toggleAutoFollowReducer.ts +12 -0
- package/src/client/vzReducer/updatePane.ts +40 -0
- package/src/client/vzReducer/updatePresenceIndicatorReducer.ts +30 -0
- package/src/client/vzReducer/visualEditorReducer.ts +9 -0
- package/src/ot.ts +24 -0
- package/src/randomId.ts +15 -0
- package/src/reactRouterExports.ts +15 -0
- package/src/runCode.ts +27 -0
- package/src/server/aiChatHandler/aiEditing.ts +151 -0
- package/src/server/aiChatHandler/chatOperations.ts +476 -0
- package/src/server/aiChatHandler/errorHandling.ts +66 -0
- package/src/server/aiChatHandler/index.ts +199 -0
- package/src/server/aiChatHandler/llmStreaming.ts +419 -0
- package/src/server/aiChatHandler/validation.ts +24 -0
- package/src/server/computeInitialDocument.ts +220 -0
- package/src/server/config.ts +24 -0
- package/src/server/featureFlags.ts +8 -0
- package/src/server/generateAIResponse.ts +188 -0
- package/src/server/handleAIAssist.ts +53 -0
- package/src/server/handleAIChatMessage.ts +2 -0
- package/src/server/handleAICopilot.ts +97 -0
- package/src/server/index.ts +379 -0
- package/src/server/isDirectory.ts +1 -0
- package/src/server/livekit.ts +24 -0
- package/src/server/prettier.ts +115 -0
- package/src/server/setupEnv.ts +8 -0
- package/src/submitOperation.ts +25 -0
- package/src/types.ts +205 -0
- package/src/utils/fileDiff.ts +117 -0
- package/src/vite-env.d.ts +10 -0
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
import {
|
|
2
|
+
useContext,
|
|
3
|
+
useMemo,
|
|
4
|
+
useEffect,
|
|
5
|
+
useCallback,
|
|
6
|
+
} from 'react';
|
|
7
|
+
import { VZCodeContext } from '../../VZCodeContext';
|
|
8
|
+
import { MessageList } from './MessageList';
|
|
9
|
+
import { ChatInput } from './ChatInput';
|
|
10
|
+
import './styles.scss';
|
|
11
|
+
|
|
12
|
+
const DEBUG = false;
|
|
13
|
+
|
|
14
|
+
const showSuggestedRequests = false;
|
|
15
|
+
|
|
16
|
+
// Component for displaying the list of existing chats
|
|
17
|
+
const ChatList = ({
|
|
18
|
+
chats,
|
|
19
|
+
selectedChatId,
|
|
20
|
+
onSelectChat,
|
|
21
|
+
getChatTitle,
|
|
22
|
+
}) => {
|
|
23
|
+
return (
|
|
24
|
+
<div className="ai-chat-list">
|
|
25
|
+
<div className="ai-chat-list-header">
|
|
26
|
+
<h4>Previous Chats</h4>
|
|
27
|
+
</div>
|
|
28
|
+
<div className="ai-chat-suggested-prompts">
|
|
29
|
+
{chats.map((chat) => (
|
|
30
|
+
<button
|
|
31
|
+
key={chat.id}
|
|
32
|
+
className={`ai-chat-suggested-prompt ${
|
|
33
|
+
selectedChatId === chat.id ? 'selected' : ''
|
|
34
|
+
}`}
|
|
35
|
+
onClick={() => onSelectChat(chat.id)}
|
|
36
|
+
>
|
|
37
|
+
{getChatTitle(chat)}
|
|
38
|
+
</button>
|
|
39
|
+
))}
|
|
40
|
+
</div>
|
|
41
|
+
</div>
|
|
42
|
+
);
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export const AIChat = () => {
|
|
46
|
+
const {
|
|
47
|
+
aiChatFocused,
|
|
48
|
+
content,
|
|
49
|
+
aiChatMode,
|
|
50
|
+
aiChatMessage,
|
|
51
|
+
isLoading,
|
|
52
|
+
currentChatId,
|
|
53
|
+
selectedChatId,
|
|
54
|
+
setSelectedChatId,
|
|
55
|
+
aiErrorMessage,
|
|
56
|
+
setAIChatMode,
|
|
57
|
+
clearStoredAIPrompt,
|
|
58
|
+
getStoredAIPrompt,
|
|
59
|
+
setAIChatMessage,
|
|
60
|
+
handleSendMessage,
|
|
61
|
+
setAIErrorMessage,
|
|
62
|
+
navigateMessageHistoryUp,
|
|
63
|
+
navigateMessageHistoryDown,
|
|
64
|
+
resetMessageHistoryNavigation,
|
|
65
|
+
} = useContext(VZCodeContext);
|
|
66
|
+
|
|
67
|
+
// Get the active chat ID and chat data
|
|
68
|
+
// If selectedChatId is set, use it; otherwise, if no chat selected, don't default to currentChatId
|
|
69
|
+
const activeChatId = selectedChatId;
|
|
70
|
+
const currentChat = activeChatId
|
|
71
|
+
? content?.chats?.[activeChatId]
|
|
72
|
+
: null;
|
|
73
|
+
const rawMessages = currentChat?.messages || [];
|
|
74
|
+
const aiStatus = currentChat?.aiStatus;
|
|
75
|
+
const aiScratchpad = currentChat?.aiScratchpad;
|
|
76
|
+
|
|
77
|
+
// Transform messages to ensure they have required id field - memoized to avoid recreation
|
|
78
|
+
const messages = useMemo(
|
|
79
|
+
() =>
|
|
80
|
+
rawMessages.map((msg, index) => ({
|
|
81
|
+
...msg,
|
|
82
|
+
id: msg.id || `msg-${index}`,
|
|
83
|
+
})),
|
|
84
|
+
[rawMessages],
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
// Check if this is the first time opening the chat (no messages) or no chat selected
|
|
88
|
+
const isEmptyState =
|
|
89
|
+
!selectedChatId || rawMessages.length === 0;
|
|
90
|
+
|
|
91
|
+
// Get all existing chats
|
|
92
|
+
const allChats = content?.chats || {};
|
|
93
|
+
const existingChats = Object.values(allChats).filter(
|
|
94
|
+
(chat) => chat.messages.length > 0,
|
|
95
|
+
);
|
|
96
|
+
const hasExistingChats = existingChats.length > 0;
|
|
97
|
+
|
|
98
|
+
// Generate title for a chat (first 50 characters of first user message)
|
|
99
|
+
const getChatTitle = (chat) => {
|
|
100
|
+
const firstUserMessage = chat.messages.find(
|
|
101
|
+
(msg) => msg.role === 'user',
|
|
102
|
+
);
|
|
103
|
+
if (!firstUserMessage) return 'New Chat';
|
|
104
|
+
return (
|
|
105
|
+
firstUserMessage.content.slice(0, 50) +
|
|
106
|
+
(firstUserMessage.content.length > 50 ? '...' : '')
|
|
107
|
+
);
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
// Wrapper for handleSendMessage to automatically select the chat when sending
|
|
111
|
+
const handleSendMessageWithSelection = useCallback(() => {
|
|
112
|
+
// If no chat is selected, select the currentChatId when sending a message
|
|
113
|
+
if (!selectedChatId) {
|
|
114
|
+
setSelectedChatId(currentChatId);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Call the original handleSendMessage without parameters
|
|
118
|
+
return handleSendMessage();
|
|
119
|
+
}, [
|
|
120
|
+
selectedChatId,
|
|
121
|
+
setSelectedChatId,
|
|
122
|
+
currentChatId,
|
|
123
|
+
handleSendMessage,
|
|
124
|
+
]);
|
|
125
|
+
|
|
126
|
+
// Check for stored AI prompt on component mount (post-fork restoration)
|
|
127
|
+
useEffect(() => {
|
|
128
|
+
DEBUG &&
|
|
129
|
+
console.log('AIChat: Checking for stored AI prompt');
|
|
130
|
+
if (getStoredAIPrompt) {
|
|
131
|
+
const storedPrompt = getStoredAIPrompt();
|
|
132
|
+
DEBUG &&
|
|
133
|
+
console.log(
|
|
134
|
+
'AIChat: Stored prompt result:',
|
|
135
|
+
storedPrompt,
|
|
136
|
+
);
|
|
137
|
+
if (storedPrompt) {
|
|
138
|
+
// Restore the prompt and mode
|
|
139
|
+
DEBUG &&
|
|
140
|
+
console.log('AIChat: Restoring prompt and mode');
|
|
141
|
+
setAIChatMessage(storedPrompt.prompt);
|
|
142
|
+
setAIChatMode(
|
|
143
|
+
storedPrompt.modelName === 'ask' ? 'ask' : 'edit',
|
|
144
|
+
);
|
|
145
|
+
|
|
146
|
+
// Clear the stored prompt
|
|
147
|
+
DEBUG &&
|
|
148
|
+
console.log('AIChat: Clearing stored prompt');
|
|
149
|
+
clearStoredAIPrompt();
|
|
150
|
+
|
|
151
|
+
// Auto-submit the restored prompt after a short delay
|
|
152
|
+
DEBUG &&
|
|
153
|
+
console.log('AIChat: Scheduling auto-submit');
|
|
154
|
+
setTimeout(() => {
|
|
155
|
+
DEBUG &&
|
|
156
|
+
console.log(
|
|
157
|
+
'AIChat: Auto-submitting restored prompt',
|
|
158
|
+
);
|
|
159
|
+
handleSendMessage(storedPrompt.prompt);
|
|
160
|
+
}, 100);
|
|
161
|
+
} else {
|
|
162
|
+
DEBUG &&
|
|
163
|
+
console.log('AIChat: No stored prompt found');
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}, [
|
|
167
|
+
getStoredAIPrompt,
|
|
168
|
+
clearStoredAIPrompt,
|
|
169
|
+
setAIChatMessage,
|
|
170
|
+
setAIChatMode,
|
|
171
|
+
handleSendMessage,
|
|
172
|
+
]);
|
|
173
|
+
|
|
174
|
+
return (
|
|
175
|
+
<div className="ai-chat-container">
|
|
176
|
+
<div className="ai-chat-content">
|
|
177
|
+
<div className="ai-chat-messages-container">
|
|
178
|
+
{isEmptyState ? (
|
|
179
|
+
<div className="ai-chat-empty">
|
|
180
|
+
<div className="ai-chat-empty-icon">✨</div>
|
|
181
|
+
<h3 className="ai-chat-empty-title">
|
|
182
|
+
Edit with AI
|
|
183
|
+
</h3>
|
|
184
|
+
<div className="ai-chat-empty-text">
|
|
185
|
+
How can I help you?
|
|
186
|
+
</div>
|
|
187
|
+
{hasExistingChats && (
|
|
188
|
+
<ChatList
|
|
189
|
+
chats={existingChats}
|
|
190
|
+
selectedChatId={selectedChatId}
|
|
191
|
+
onSelectChat={setSelectedChatId}
|
|
192
|
+
getChatTitle={getChatTitle}
|
|
193
|
+
/>
|
|
194
|
+
)}
|
|
195
|
+
{showSuggestedRequests && (
|
|
196
|
+
<div className="ai-chat-empty-examples">
|
|
197
|
+
{aiChatMode === 'ask' ? (
|
|
198
|
+
<>
|
|
199
|
+
<h4>Try asking questions like:</h4>
|
|
200
|
+
<div className="ai-chat-suggested-prompts">
|
|
201
|
+
<button
|
|
202
|
+
className="ai-chat-suggested-prompt"
|
|
203
|
+
onClick={() =>
|
|
204
|
+
handleSendMessage(
|
|
205
|
+
'Explain how this works',
|
|
206
|
+
)
|
|
207
|
+
}
|
|
208
|
+
>
|
|
209
|
+
"Explain how this works"
|
|
210
|
+
</button>
|
|
211
|
+
<button
|
|
212
|
+
className="ai-chat-suggested-prompt"
|
|
213
|
+
onClick={() =>
|
|
214
|
+
handleSendMessage(
|
|
215
|
+
'How could I change it so that the circles are bigger?',
|
|
216
|
+
)
|
|
217
|
+
}
|
|
218
|
+
>
|
|
219
|
+
"How could I change it so that the
|
|
220
|
+
circles are bigger?"
|
|
221
|
+
</button>
|
|
222
|
+
<button
|
|
223
|
+
className="ai-chat-suggested-prompt"
|
|
224
|
+
onClick={() =>
|
|
225
|
+
handleSendMessage(
|
|
226
|
+
'What does this function do?',
|
|
227
|
+
)
|
|
228
|
+
}
|
|
229
|
+
>
|
|
230
|
+
"What does this function do?"
|
|
231
|
+
</button>
|
|
232
|
+
<button
|
|
233
|
+
className="ai-chat-suggested-prompt"
|
|
234
|
+
onClick={() =>
|
|
235
|
+
handleSendMessage(
|
|
236
|
+
'How can I make this more accessible?',
|
|
237
|
+
)
|
|
238
|
+
}
|
|
239
|
+
>
|
|
240
|
+
"How can I make this more
|
|
241
|
+
accessible?"
|
|
242
|
+
</button>
|
|
243
|
+
</div>
|
|
244
|
+
</>
|
|
245
|
+
) : (
|
|
246
|
+
<>
|
|
247
|
+
<h4>Try edit requests like these:</h4>
|
|
248
|
+
<div className="ai-chat-suggested-prompts">
|
|
249
|
+
<button
|
|
250
|
+
className="ai-chat-suggested-prompt"
|
|
251
|
+
onClick={() =>
|
|
252
|
+
handleSendMessage(
|
|
253
|
+
'Change the circles to squares',
|
|
254
|
+
)
|
|
255
|
+
}
|
|
256
|
+
>
|
|
257
|
+
"Change the circles to squares"
|
|
258
|
+
</button>
|
|
259
|
+
<button
|
|
260
|
+
className="ai-chat-suggested-prompt"
|
|
261
|
+
onClick={() =>
|
|
262
|
+
handleSendMessage(
|
|
263
|
+
'Add a button that toggles the animation',
|
|
264
|
+
)
|
|
265
|
+
}
|
|
266
|
+
>
|
|
267
|
+
"Add a button that toggles the
|
|
268
|
+
animation"
|
|
269
|
+
</button>
|
|
270
|
+
<button
|
|
271
|
+
className="ai-chat-suggested-prompt"
|
|
272
|
+
onClick={() =>
|
|
273
|
+
handleSendMessage(
|
|
274
|
+
'Fix the CSS so the layout is responsive',
|
|
275
|
+
)
|
|
276
|
+
}
|
|
277
|
+
>
|
|
278
|
+
"Fix the CSS so the layout is
|
|
279
|
+
responsive"
|
|
280
|
+
</button>
|
|
281
|
+
<button
|
|
282
|
+
className="ai-chat-suggested-prompt"
|
|
283
|
+
onClick={() =>
|
|
284
|
+
handleSendMessage(
|
|
285
|
+
'Refactor this function to use async/await',
|
|
286
|
+
)
|
|
287
|
+
}
|
|
288
|
+
>
|
|
289
|
+
"Refactor this function to use
|
|
290
|
+
async/await"
|
|
291
|
+
</button>
|
|
292
|
+
</div>
|
|
293
|
+
</>
|
|
294
|
+
)}
|
|
295
|
+
</div>
|
|
296
|
+
)}
|
|
297
|
+
{showSuggestedRequests && (
|
|
298
|
+
<div className="ai-chat-empty-text">
|
|
299
|
+
{aiChatMode === 'ask'
|
|
300
|
+
? 'Type your question below to get started!'
|
|
301
|
+
: 'Type your edit request below to get started!'}
|
|
302
|
+
</div>
|
|
303
|
+
)}
|
|
304
|
+
</div>
|
|
305
|
+
) : (
|
|
306
|
+
<MessageList
|
|
307
|
+
messages={messages}
|
|
308
|
+
aiStatus={aiStatus}
|
|
309
|
+
isLoading={isLoading}
|
|
310
|
+
chatId={selectedChatId || currentChatId}
|
|
311
|
+
aiScratchpad={aiScratchpad}
|
|
312
|
+
/>
|
|
313
|
+
)}
|
|
314
|
+
{aiErrorMessage && (
|
|
315
|
+
<div className="ai-chat-error">
|
|
316
|
+
<div className="ai-chat-error-content">
|
|
317
|
+
<span className="ai-chat-error-icon">
|
|
318
|
+
⚠️
|
|
319
|
+
</span>
|
|
320
|
+
<span className="ai-chat-error-message">
|
|
321
|
+
{aiErrorMessage}
|
|
322
|
+
</span>
|
|
323
|
+
<button
|
|
324
|
+
className="ai-chat-error-dismiss"
|
|
325
|
+
onClick={() => setAIErrorMessage(null)}
|
|
326
|
+
aria-label="Dismiss error"
|
|
327
|
+
>
|
|
328
|
+
×
|
|
329
|
+
</button>
|
|
330
|
+
</div>
|
|
331
|
+
</div>
|
|
332
|
+
)}
|
|
333
|
+
</div>
|
|
334
|
+
</div>
|
|
335
|
+
<div className="ai-chat-input-fixed">
|
|
336
|
+
<ChatInput
|
|
337
|
+
aiChatMessage={aiChatMessage}
|
|
338
|
+
setAIChatMessage={setAIChatMessage}
|
|
339
|
+
onSendMessage={handleSendMessageWithSelection}
|
|
340
|
+
isLoading={isLoading}
|
|
341
|
+
focused={aiChatFocused}
|
|
342
|
+
aiChatMode={aiChatMode}
|
|
343
|
+
setAIChatMode={setAIChatMode}
|
|
344
|
+
navigateMessageHistoryUp={
|
|
345
|
+
navigateMessageHistoryUp
|
|
346
|
+
}
|
|
347
|
+
navigateMessageHistoryDown={
|
|
348
|
+
navigateMessageHistoryDown
|
|
349
|
+
}
|
|
350
|
+
resetMessageHistoryNavigation={
|
|
351
|
+
resetMessageHistoryNavigation
|
|
352
|
+
}
|
|
353
|
+
/>
|
|
354
|
+
</div>
|
|
355
|
+
</div>
|
|
356
|
+
);
|
|
357
|
+
};
|