vzcode 2.16.0 → 2.17.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/{bindings_wasm_bg-9w8E-TmY.wasm → bindings_wasm_bg-D9vNLG9F.wasm} +0 -0
- package/dist/assets/buildWorker-DL4wXpRr.js +695 -0
- package/dist/assets/{index-C2BLPyQP.js → index-BiPmUreW.js} +147 -147
- package/dist/assets/{index-DVR90LwF.css → index-BvGPtSrr.css} +1 -1
- package/dist/assets/worker-RJ-cjbld.js +327 -0
- package/dist/index.html +2 -2
- package/package.json +1 -1
- package/src/client/VZSidebar/AIChat/FileEditingIndicator.tsx +12 -4
- package/src/client/VZSidebar/AIChat/Message.tsx +71 -18
- package/src/client/VZSidebar/AIChat/MessageList.tsx +57 -37
- package/src/client/VZSidebar/AIChat/index.tsx +0 -3
- package/src/client/VZSidebar/AIChat/styles.scss +33 -29
- package/src/client/hooks/useAutoScroll.ts +0 -1
- package/dist/assets/buildWorker-Bi6wsfQk.js +0 -695
- package/dist/assets/worker-BSzbM0Uo.js +0 -330
- package/src/client/VZSidebar/AIChat/StreamingMessage.tsx +0 -77
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-BiPmUreW.js"></script>
|
|
24
|
+
<link rel="stylesheet" crossorigin href="/assets/index-BvGPtSrr.css">
|
|
25
25
|
</head>
|
|
26
26
|
<body>
|
|
27
27
|
<div id="root"></div>
|
package/package.json
CHANGED
|
@@ -3,11 +3,12 @@ import { Spinner } from '../../AIAssist/Spinner';
|
|
|
3
3
|
interface AIEditingStatusIndicatorProps {
|
|
4
4
|
status: string;
|
|
5
5
|
fileName?: string;
|
|
6
|
+
additionalWidgets?: React.ReactNode;
|
|
6
7
|
}
|
|
7
8
|
|
|
8
9
|
export const AIEditingStatusIndicator: React.FC<
|
|
9
10
|
AIEditingStatusIndicatorProps
|
|
10
|
-
> = ({ status, fileName }) => {
|
|
11
|
+
> = ({ status, fileName, additionalWidgets }) => {
|
|
11
12
|
const getStatusDisplay = (status: string) => {
|
|
12
13
|
switch (status) {
|
|
13
14
|
case 'Analyzing request...':
|
|
@@ -36,9 +37,16 @@ export const AIEditingStatusIndicator: React.FC<
|
|
|
36
37
|
);
|
|
37
38
|
case 'Done':
|
|
38
39
|
return (
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
40
|
+
<div className="file-editing-done-container">
|
|
41
|
+
<div className="file-editing-done-status">
|
|
42
|
+
✅ <span>Done</span>
|
|
43
|
+
</div>
|
|
44
|
+
{additionalWidgets && (
|
|
45
|
+
<div className="file-editing-done-widgets">
|
|
46
|
+
{additionalWidgets}
|
|
47
|
+
</div>
|
|
48
|
+
)}
|
|
49
|
+
</div>
|
|
42
50
|
);
|
|
43
51
|
default:
|
|
44
52
|
// Handle file editing status (e.g., "Editing filename.js...")
|
|
@@ -1,31 +1,36 @@
|
|
|
1
|
-
import { timestampToDate } from '@vizhub/viz-utils';
|
|
2
|
-
import Markdown from 'react-markdown';
|
|
3
|
-
import remarkGfm from 'remark-gfm';
|
|
4
1
|
import React, {
|
|
5
2
|
useMemo,
|
|
6
|
-
memo,
|
|
7
3
|
useContext,
|
|
8
4
|
forwardRef,
|
|
9
5
|
} from 'react';
|
|
6
|
+
import { timestampToDate } from '@vizhub/viz-utils';
|
|
7
|
+
import Markdown from 'react-markdown';
|
|
8
|
+
import remarkGfm from 'remark-gfm';
|
|
9
|
+
import { StreamingEvent } from '../../../types.js';
|
|
10
|
+
import { IndividualFileDiff } from './IndividualFileDiff';
|
|
11
|
+
import { VZCodeContext } from '../../VZCodeContext';
|
|
10
12
|
import { DiffView, DiffViewRef } from './DiffView';
|
|
11
13
|
import { UnifiedFilesDiff } from '../../../utils/fileDiff';
|
|
12
14
|
import { enableDiffView } from '../../featureFlags';
|
|
13
|
-
|
|
15
|
+
|
|
16
|
+
const DEBUG = false;
|
|
14
17
|
|
|
15
18
|
interface MessageProps {
|
|
16
19
|
id: string;
|
|
17
20
|
role: 'user' | 'assistant';
|
|
18
|
-
content
|
|
21
|
+
content?: string; // For non-streaming messages
|
|
19
22
|
timestamp: number;
|
|
20
|
-
|
|
21
|
-
|
|
23
|
+
events?: StreamingEvent[]; // For streaming messages
|
|
24
|
+
isActive?: boolean; // Is this the currently streaming message?
|
|
22
25
|
chatId?: string;
|
|
23
26
|
showAdditionalWidgets?: boolean;
|
|
27
|
+
isStreaming?: boolean;
|
|
28
|
+
diffData?: UnifiedFilesDiff;
|
|
24
29
|
}
|
|
25
30
|
|
|
26
|
-
const
|
|
31
|
+
export const Message = forwardRef<
|
|
27
32
|
DiffViewRef,
|
|
28
|
-
MessageProps
|
|
33
|
+
React.PropsWithChildren<MessageProps>
|
|
29
34
|
>(
|
|
30
35
|
(
|
|
31
36
|
{
|
|
@@ -33,16 +38,25 @@ const MessageComponent = forwardRef<
|
|
|
33
38
|
role,
|
|
34
39
|
content,
|
|
35
40
|
timestamp,
|
|
36
|
-
|
|
37
|
-
|
|
41
|
+
events = [],
|
|
42
|
+
isActive,
|
|
43
|
+
children,
|
|
38
44
|
chatId,
|
|
39
45
|
showAdditionalWidgets = false,
|
|
46
|
+
isStreaming = false,
|
|
47
|
+
diffData,
|
|
40
48
|
},
|
|
41
49
|
ref,
|
|
42
50
|
) => {
|
|
43
51
|
const { additionalWidgets, handleSendMessage } =
|
|
44
52
|
useContext(VZCodeContext);
|
|
45
53
|
|
|
54
|
+
DEBUG &&
|
|
55
|
+
console.log(
|
|
56
|
+
'StreamingMessage: Rendered with events:',
|
|
57
|
+
events,
|
|
58
|
+
);
|
|
59
|
+
|
|
46
60
|
// Memoize date formatting to avoid repeated computation
|
|
47
61
|
const formattedTime = useMemo(() => {
|
|
48
62
|
return timestampToDate(timestamp).toLocaleTimeString(
|
|
@@ -62,22 +76,63 @@ const MessageComponent = forwardRef<
|
|
|
62
76
|
return (
|
|
63
77
|
<div className={messageClassName}>
|
|
64
78
|
<div className="ai-chat-message-content">
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
79
|
+
{/* Render regular content for non-streaming messages */}
|
|
80
|
+
{content && (
|
|
81
|
+
<Markdown remarkPlugins={[remarkGfm]}>
|
|
82
|
+
{content}
|
|
83
|
+
</Markdown>
|
|
84
|
+
)}
|
|
85
|
+
|
|
86
|
+
{/* Render diff view if present */}
|
|
68
87
|
{enableDiffView &&
|
|
69
88
|
diffData &&
|
|
70
89
|
Object.keys(diffData).length > 0 && (
|
|
71
90
|
<DiffView diffData={diffData} ref={ref} />
|
|
72
91
|
)}
|
|
92
|
+
|
|
93
|
+
{/* Render events in order for streaming messages */}
|
|
94
|
+
{events.map((event, index) => {
|
|
95
|
+
switch (event.type) {
|
|
96
|
+
case 'text_chunk':
|
|
97
|
+
return (
|
|
98
|
+
<div
|
|
99
|
+
key={`text-${index}`}
|
|
100
|
+
className="text-chunk"
|
|
101
|
+
>
|
|
102
|
+
<Markdown remarkPlugins={[remarkGfm]}>
|
|
103
|
+
{event.content}
|
|
104
|
+
</Markdown>
|
|
105
|
+
</div>
|
|
106
|
+
);
|
|
107
|
+
case 'file_complete':
|
|
108
|
+
return (
|
|
109
|
+
<IndividualFileDiff
|
|
110
|
+
key={`file-${event.fileName}-${index}`}
|
|
111
|
+
fileName={event.fileName}
|
|
112
|
+
beforeContent={
|
|
113
|
+
event.beforeContent || ''
|
|
114
|
+
}
|
|
115
|
+
afterContent={event.afterContent || ''}
|
|
116
|
+
/>
|
|
117
|
+
);
|
|
118
|
+
case 'file_start':
|
|
119
|
+
// File start events are now handled by centralized status logic in MessageList
|
|
120
|
+
return null;
|
|
121
|
+
default:
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
124
|
+
})}
|
|
125
|
+
{/* Additional widgets are now shown within the "Done" status indicator */}
|
|
73
126
|
{showAdditionalWidgets &&
|
|
74
127
|
additionalWidgets &&
|
|
75
128
|
chatId &&
|
|
129
|
+
!isStreaming && // Only show here for non-streaming messages (completed messages)
|
|
76
130
|
additionalWidgets({
|
|
77
131
|
messageId: id,
|
|
78
132
|
chatId: chatId,
|
|
79
133
|
handleSendMessage,
|
|
80
134
|
})}
|
|
135
|
+
{isActive && children}
|
|
81
136
|
</div>
|
|
82
137
|
<div className="ai-chat-message-time">
|
|
83
138
|
{formattedTime}
|
|
@@ -87,6 +142,4 @@ const MessageComponent = forwardRef<
|
|
|
87
142
|
},
|
|
88
143
|
);
|
|
89
144
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
export const Message = memo(MessageComponent);
|
|
145
|
+
Message.displayName = 'Message';
|
|
@@ -1,12 +1,18 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
useRef,
|
|
3
|
+
useEffect,
|
|
4
|
+
memo,
|
|
5
|
+
useState,
|
|
6
|
+
useContext,
|
|
7
|
+
} from 'react';
|
|
2
8
|
import { Message } from './Message';
|
|
3
|
-
import { StreamingMessage } from './StreamingMessage';
|
|
4
9
|
import { TypingIndicator } from './TypingIndicator';
|
|
5
10
|
import { ThinkingScratchpad } from './ThinkingScratchpad';
|
|
6
11
|
import { AIEditingStatusIndicator } from './FileEditingIndicator';
|
|
7
12
|
import { VizChatMessage } from '@vizhub/viz-types';
|
|
8
13
|
import { ExtendedVizChatMessage } from '../../../types.js';
|
|
9
14
|
import { DiffViewRef } from './DiffView.js';
|
|
15
|
+
import { VZCodeContext } from '../../VZCodeContext';
|
|
10
16
|
|
|
11
17
|
const MessageListComponent = ({
|
|
12
18
|
messages,
|
|
@@ -32,6 +38,10 @@ const MessageListComponent = ({
|
|
|
32
38
|
const messagesEndRef = useRef<HTMLDivElement>(null);
|
|
33
39
|
const diffViewRef = useRef<DiffViewRef>(null);
|
|
34
40
|
|
|
41
|
+
// Get additional widgets from context
|
|
42
|
+
const { additionalWidgets, handleSendMessage } =
|
|
43
|
+
useContext(VZCodeContext);
|
|
44
|
+
|
|
35
45
|
// Track previous loading state to detect when AI generation completes
|
|
36
46
|
const [prevIsLoading, setPrevIsLoading] =
|
|
37
47
|
useState(isLoading);
|
|
@@ -162,54 +172,64 @@ const MessageListComponent = ({
|
|
|
162
172
|
msg.role === 'assistant' &&
|
|
163
173
|
index === lastAssistantMessageIndex;
|
|
164
174
|
|
|
165
|
-
// Use
|
|
166
|
-
if (
|
|
167
|
-
msg.role === 'assistant' &&
|
|
168
|
-
isStreamingMessage
|
|
169
|
-
) {
|
|
170
|
-
return (
|
|
171
|
-
<StreamingMessage
|
|
172
|
-
key={msg.id}
|
|
173
|
-
timestamp={msg.timestamp}
|
|
174
|
-
events={extendedMsg.streamingEvents || []}
|
|
175
|
-
isActive={index === lastAssistantMessageIndex}
|
|
176
|
-
>
|
|
177
|
-
{showThinkingScratchpad && (
|
|
178
|
-
<ThinkingScratchpad
|
|
179
|
-
content={aiScratchpad || ''}
|
|
180
|
-
isVisible={showThinkingScratchpad}
|
|
181
|
-
/>
|
|
182
|
-
)}
|
|
183
|
-
|
|
184
|
-
{showConsolidatedStatusIndicator && (
|
|
185
|
-
<AIEditingStatusIndicator
|
|
186
|
-
status={consolidatedStatus?.status || ''}
|
|
187
|
-
fileName={consolidatedStatus?.fileName}
|
|
188
|
-
/>
|
|
189
|
-
)}
|
|
190
|
-
|
|
191
|
-
{showTypingIndicator && <TypingIndicator />}
|
|
192
|
-
</StreamingMessage>
|
|
193
|
-
);
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
// Use regular Message component for user messages and non-streaming assistant messages
|
|
175
|
+
// Use Message for all messages now
|
|
197
176
|
return (
|
|
198
177
|
<Message
|
|
199
178
|
key={msg.id}
|
|
200
179
|
id={msg.id}
|
|
201
180
|
role={msg.role}
|
|
202
|
-
content={
|
|
181
|
+
content={
|
|
182
|
+
isStreamingMessage ? undefined : msg.content
|
|
183
|
+
}
|
|
203
184
|
timestamp={msg.timestamp}
|
|
204
|
-
|
|
185
|
+
events={
|
|
186
|
+
isStreamingMessage
|
|
187
|
+
? extendedMsg.streamingEvents || []
|
|
188
|
+
: []
|
|
189
|
+
}
|
|
190
|
+
isActive={index === lastAssistantMessageIndex}
|
|
205
191
|
chatId={chatId}
|
|
206
192
|
showAdditionalWidgets={showAdditionalWidgets}
|
|
193
|
+
isStreaming={isStreamingMessage}
|
|
194
|
+
diffData={(msg as any).diffData}
|
|
207
195
|
ref={
|
|
208
196
|
isLastMessage && (msg as any).diffData
|
|
209
197
|
? diffViewRef
|
|
210
198
|
: null
|
|
211
199
|
}
|
|
212
|
-
|
|
200
|
+
>
|
|
201
|
+
{isStreamingMessage &&
|
|
202
|
+
showThinkingScratchpad && (
|
|
203
|
+
<ThinkingScratchpad
|
|
204
|
+
content={aiScratchpad || ''}
|
|
205
|
+
isVisible={showThinkingScratchpad}
|
|
206
|
+
/>
|
|
207
|
+
)}
|
|
208
|
+
|
|
209
|
+
{isStreamingMessage &&
|
|
210
|
+
showConsolidatedStatusIndicator && (
|
|
211
|
+
<AIEditingStatusIndicator
|
|
212
|
+
status={consolidatedStatus?.status || ''}
|
|
213
|
+
fileName={consolidatedStatus?.fileName}
|
|
214
|
+
additionalWidgets={
|
|
215
|
+
consolidatedStatus?.status === 'Done' &&
|
|
216
|
+
showAdditionalWidgets &&
|
|
217
|
+
additionalWidgets &&
|
|
218
|
+
chatId
|
|
219
|
+
? additionalWidgets({
|
|
220
|
+
messageId: msg.id,
|
|
221
|
+
chatId: chatId,
|
|
222
|
+
handleSendMessage,
|
|
223
|
+
})
|
|
224
|
+
: undefined
|
|
225
|
+
}
|
|
226
|
+
/>
|
|
227
|
+
)}
|
|
228
|
+
|
|
229
|
+
{isStreamingMessage && showTypingIndicator && (
|
|
230
|
+
<TypingIndicator />
|
|
231
|
+
)}
|
|
232
|
+
</Message>
|
|
213
233
|
);
|
|
214
234
|
})}
|
|
215
235
|
|
|
@@ -78,9 +78,6 @@ export const AIChat = () => {
|
|
|
78
78
|
afterRender,
|
|
79
79
|
} = useAutoScroll({ threshold: 24 });
|
|
80
80
|
|
|
81
|
-
// TODO fix this - currently always false
|
|
82
|
-
console.log('showJumpButton:', showJumpButton);
|
|
83
|
-
|
|
84
81
|
// Get the active chat ID and chat data
|
|
85
82
|
// If selectedChatId is set, use it; otherwise, if no chat selected, don't default to currentChatId
|
|
86
83
|
const activeChatId = selectedChatId;
|
|
@@ -140,8 +140,7 @@
|
|
|
140
140
|
.file-editing-indicator {
|
|
141
141
|
display: flex;
|
|
142
142
|
align-items: center;
|
|
143
|
-
|
|
144
|
-
margin: 0.5rem 0;
|
|
143
|
+
margin: 0.25rem 0;
|
|
145
144
|
background-color: var(--vscode-editor-background);
|
|
146
145
|
border: 1px solid var(--vscode-panel-border);
|
|
147
146
|
border-radius: 4px;
|
|
@@ -150,6 +149,7 @@
|
|
|
150
149
|
display: flex;
|
|
151
150
|
align-items: center;
|
|
152
151
|
gap: 0.5rem;
|
|
152
|
+
width: 100%;
|
|
153
153
|
}
|
|
154
154
|
|
|
155
155
|
.file-editing-icon {
|
|
@@ -161,6 +161,7 @@
|
|
|
161
161
|
.file-editing-text {
|
|
162
162
|
color: var(--vscode-foreground);
|
|
163
163
|
font-size: 0.9rem;
|
|
164
|
+
flex: 1;
|
|
164
165
|
|
|
165
166
|
code {
|
|
166
167
|
background-color: var(
|
|
@@ -170,6 +171,36 @@
|
|
|
170
171
|
border-radius: 3px;
|
|
171
172
|
font-family: var(--vscode-editor-font-family);
|
|
172
173
|
}
|
|
174
|
+
|
|
175
|
+
.file-editing-done-container {
|
|
176
|
+
display: flex;
|
|
177
|
+
align-items: center;
|
|
178
|
+
justify-content: space-between;
|
|
179
|
+
width: 100%;
|
|
180
|
+
gap: 0.5rem;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
.file-editing-done-status {
|
|
184
|
+
display: flex;
|
|
185
|
+
align-items: center;
|
|
186
|
+
gap: 8px;
|
|
187
|
+
font-size: 16px;
|
|
188
|
+
font-weight: 500;
|
|
189
|
+
margin-left: 4px;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
.file-editing-done-widgets {
|
|
193
|
+
display: flex;
|
|
194
|
+
align-items: center;
|
|
195
|
+
gap: 0.5rem;
|
|
196
|
+
flex-shrink: 0;
|
|
197
|
+
|
|
198
|
+
// // Override the margin-top for undo-button-container when inside file editing indicator
|
|
199
|
+
// .undo-button-container {
|
|
200
|
+
// margin-top: 0;
|
|
201
|
+
// margin-bottom: 0;
|
|
202
|
+
// }
|
|
203
|
+
}
|
|
173
204
|
}
|
|
174
205
|
}
|
|
175
206
|
|
|
@@ -288,33 +319,6 @@
|
|
|
288
319
|
line-height: 1.4;
|
|
289
320
|
word-wrap: break-word;
|
|
290
321
|
|
|
291
|
-
.undo-button-container {
|
|
292
|
-
display: flex;
|
|
293
|
-
justify-content: flex-end;
|
|
294
|
-
gap: 8px;
|
|
295
|
-
margin-top: 16px;
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
.undo-button {
|
|
299
|
-
background-color: #dc3545;
|
|
300
|
-
color: white;
|
|
301
|
-
border: none;
|
|
302
|
-
border-radius: 4px;
|
|
303
|
-
padding: 4px 8px;
|
|
304
|
-
font-size: 12px;
|
|
305
|
-
cursor: pointer;
|
|
306
|
-
transition: background-color 0.2s;
|
|
307
|
-
|
|
308
|
-
&:hover:not(:disabled) {
|
|
309
|
-
background-color: #c82333;
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
&:disabled {
|
|
313
|
-
background-color: #6c757d;
|
|
314
|
-
cursor: not-allowed;
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
|
|
318
322
|
// Markdown styling for dark backgrounds
|
|
319
323
|
pre {
|
|
320
324
|
background-color: rgba(0, 0, 0, 0.3);
|
|
@@ -148,7 +148,6 @@ export const useAutoScroll = (
|
|
|
148
148
|
// Ignore scroll events during programmatic scrolling
|
|
149
149
|
if (isProgrammaticScrollRef.current) return;
|
|
150
150
|
|
|
151
|
-
console.log('handleScroll called');
|
|
152
151
|
const container = containerRef.current;
|
|
153
152
|
if (!container) return;
|
|
154
153
|
|