vzcode 2.21.0 → 2.25.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 +359 -0
- package/dist/assets/{buildWorker-Bi6wsfQk.js → buildWorker-DylWm2VX.js} +64 -72
- package/dist/assets/index-CkFweu5-.js +403 -0
- package/dist/assets/{index-fYq6iaqF.css → index-Dyt9tpmu.css} +1 -5
- package/dist/assets/{worker-BSzbM0Uo.js → worker-VPLhQVba.js} +230 -230
- package/dist/assets/worker-b9bkZkXK.js +116 -0
- package/dist/assets/{worker-Cm3I3tnR.js → worker-k7HZ3t-V.js} +3 -20
- package/dist/index.html +2 -2
- package/dist/{server/aiChatHandler → llm-streaming-server}/aiEditing.js +1 -1
- package/dist/{server/aiChatHandler → llm-streaming-server}/chatOperations.js +21 -2
- package/dist/{server/aiChatHandler → llm-streaming-server}/errorHandling.js +1 -1
- package/dist/llm-streaming-server/index.js +20 -0
- package/dist/{server/aiChatHandler → llm-streaming-server}/llmStreaming.js +19 -14
- package/dist/server/aiChatHandler/index.js +9 -7
- package/package.json +41 -40
- package/src/client/CodeEditor/getOrCreateEditor.tsx +20 -13
- package/src/client/CodeEditor/index.tsx +3 -3
- package/src/client/VZSidebar/FileTypeIcon.tsx +1 -0
- package/src/client/VZSidebar/index.tsx +1 -1
- package/src/llm-streaming-server/README.md +71 -0
- package/src/{server/aiChatHandler → llm-streaming-server}/aiEditing.ts +1 -1
- package/src/{server/aiChatHandler → llm-streaming-server}/chatOperations.ts +30 -3
- package/src/{server/aiChatHandler → llm-streaming-server}/errorHandling.ts +1 -1
- package/src/llm-streaming-server/index.ts +51 -0
- package/src/{server/aiChatHandler → llm-streaming-server}/llmStreaming.ts +26 -16
- package/src/llm-streaming-ui/README.md +103 -0
- package/src/{client/VZSidebar/AIChat → llm-streaming-ui/components}/ChatInput.tsx +3 -3
- package/src/{client/VZSidebar/AIChat → llm-streaming-ui/components}/DiffView.tsx +3 -3
- package/src/{client/VZSidebar/AIChat → llm-streaming-ui/components}/FileEditingIndicator.tsx +1 -1
- package/src/{client/VZSidebar/AIChat → llm-streaming-ui/components}/IndividualFileDiff.tsx +1 -1
- package/src/{client/VZSidebar/AIChat → llm-streaming-ui/components}/Message.tsx +12 -11
- package/src/{client/VZSidebar/AIChat → llm-streaming-ui/components}/MessageList.tsx +7 -2
- package/src/{client/VZSidebar/AIChat → llm-streaming-ui/components}/index.tsx +5 -5
- package/src/{client/VZSidebar/AIChat → llm-streaming-ui/components}/styles.scss +48 -0
- package/src/llm-streaming-ui/index.ts +34 -0
- package/src/server/aiChatHandler/index.ts +11 -5
- package/src/types.ts +1 -0
- package/dist/assets/index-D6-he0oi.js +0 -476
- package/dist/assets/worker-KiuLM-X4.js +0 -136
- /package/dist/{server/aiChatHandler → llm-streaming-server}/validation.js +0 -0
- /package/src/{server/aiChatHandler → llm-streaming-server}/validation.ts +0 -0
- /package/src/{client/VZSidebar/AIChat → llm-streaming-ui/components}/DiffView.scss +0 -0
- /package/src/{client/VZSidebar/AIChat → llm-streaming-ui/components}/JumpToLatestButton.tsx +0 -0
- /package/src/{client/VZSidebar/AIChat → llm-streaming-ui/components}/ThinkingScratchpad.tsx +0 -0
- /package/src/{client/VZSidebar/AIChat → llm-streaming-ui/components}/TypingIndicator.tsx +0 -0
- /package/src/{client/VZSidebar/AIChat → llm-streaming-ui/components}/useSpeechRecognition.ts +0 -0
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @vizhub/llm-streaming-server
|
|
3
|
+
*
|
|
4
|
+
* Server-side library for streaming LLM responses with ShareDB integration.
|
|
5
|
+
* This module provides functionality for:
|
|
6
|
+
* - Creating and managing LLM streaming functions
|
|
7
|
+
* - Performing AI-assisted code editing
|
|
8
|
+
* - Managing chat operations with ShareDB
|
|
9
|
+
* - Validating requests and handling errors
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
// Core LLM streaming functionality
|
|
13
|
+
export { createLLMFunction } from './llmStreaming.js';
|
|
14
|
+
|
|
15
|
+
// AI editing operations
|
|
16
|
+
export {
|
|
17
|
+
performAIChat,
|
|
18
|
+
performAIEditing,
|
|
19
|
+
} from './aiEditing.js';
|
|
20
|
+
|
|
21
|
+
// ShareDB chat operations
|
|
22
|
+
export {
|
|
23
|
+
ensureChatsExist,
|
|
24
|
+
ensureChatExists,
|
|
25
|
+
addUserMessage,
|
|
26
|
+
updateAIStatus,
|
|
27
|
+
updateAIScratchpad,
|
|
28
|
+
clearAIScratchpadAndStatus,
|
|
29
|
+
createAIMessage,
|
|
30
|
+
updateAIMessageContent,
|
|
31
|
+
setAIStatus,
|
|
32
|
+
finalizeAIMessage,
|
|
33
|
+
addDiffToAIMessage,
|
|
34
|
+
addAIMessage,
|
|
35
|
+
updateFiles,
|
|
36
|
+
resolveFileId,
|
|
37
|
+
createNewFile,
|
|
38
|
+
createStreamingAIMessage,
|
|
39
|
+
addStreamingEvent,
|
|
40
|
+
updateStreamingStatus,
|
|
41
|
+
finalizeStreamingMessage,
|
|
42
|
+
} from './chatOperations.js';
|
|
43
|
+
|
|
44
|
+
// Request validation
|
|
45
|
+
export { validateRequest } from './validation.js';
|
|
46
|
+
|
|
47
|
+
// Error handling
|
|
48
|
+
export {
|
|
49
|
+
handleError,
|
|
50
|
+
handleBackgroundError,
|
|
51
|
+
} from './errorHandling.js';
|
|
@@ -16,12 +16,13 @@ import {
|
|
|
16
16
|
addStreamingEvent,
|
|
17
17
|
updateStreamingStatus,
|
|
18
18
|
finalizeStreamingMessage,
|
|
19
|
+
setChatModel,
|
|
19
20
|
} from './chatOperations.js';
|
|
20
21
|
import {
|
|
21
22
|
ShareDBDoc,
|
|
22
23
|
ExtendedVizContent,
|
|
23
|
-
} from '
|
|
24
|
-
import { formatFiles } from '../prettier.js';
|
|
24
|
+
} from '../types.js';
|
|
25
|
+
import { formatFiles } from '../server/prettier.js';
|
|
25
26
|
|
|
26
27
|
// Verbose logs
|
|
27
28
|
const DEBUG = false;
|
|
@@ -56,8 +57,15 @@ export const createLLMFunction = ({
|
|
|
56
57
|
}) => {
|
|
57
58
|
return async (fullPrompt: string) => {
|
|
58
59
|
// Create OpenRouter client for reasoning token support
|
|
60
|
+
const apiKey = process.env.VZCODE_EDIT_WITH_AI_API_KEY;
|
|
61
|
+
if (!apiKey) {
|
|
62
|
+
console.warn(
|
|
63
|
+
'[LLMStreaming] OpenRouter API Key (VZCODE_EDIT_WITH_AI_API_KEY) not found',
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
|
|
59
67
|
const openRouterClient = new OpenAI({
|
|
60
|
-
apiKey:
|
|
68
|
+
apiKey: apiKey,
|
|
61
69
|
baseURL:
|
|
62
70
|
process.env.VZCODE_EDIT_WITH_AI_BASE_URL ||
|
|
63
71
|
'https://openrouter.ai/api/v1',
|
|
@@ -73,9 +81,18 @@ export const createLLMFunction = ({
|
|
|
73
81
|
let accumulatedTextChunk = '';
|
|
74
82
|
let currentFileContent = '';
|
|
75
83
|
|
|
84
|
+
// Stream the response with reasoning tokens
|
|
85
|
+
const modelName =
|
|
86
|
+
model ||
|
|
87
|
+
process.env.VZCODE_EDIT_WITH_AI_MODEL_NAME ||
|
|
88
|
+
'anthropic/claude-haiku-4.5';
|
|
89
|
+
|
|
76
90
|
// Create streaming AI message
|
|
77
91
|
createStreamingAIMessage(shareDBDoc, chatId);
|
|
78
92
|
|
|
93
|
+
// Set the model being used for this chat
|
|
94
|
+
setChatModel(shareDBDoc, chatId, modelName);
|
|
95
|
+
|
|
79
96
|
// Set initial content generation status
|
|
80
97
|
updateStreamingStatus(
|
|
81
98
|
shareDBDoc,
|
|
@@ -232,28 +249,21 @@ export const createLLMFunction = ({
|
|
|
232
249
|
const chunks = [];
|
|
233
250
|
let reasoningContent = '';
|
|
234
251
|
|
|
235
|
-
// Stream the response with reasoning tokens
|
|
236
|
-
const modelName =
|
|
237
|
-
model ||
|
|
238
|
-
process.env.VZCODE_EDIT_WITH_AI_MODEL_NAME ||
|
|
239
|
-
'anthropic/claude-3.5-sonnet';
|
|
240
|
-
|
|
241
252
|
// Configure reasoning tokens based on enableReasoningTokens flag
|
|
242
253
|
const requestConfig: any = {
|
|
243
254
|
model: modelName,
|
|
244
255
|
messages: [{ role: 'user', content: fullPrompt }],
|
|
245
|
-
usage: { include: true },
|
|
246
256
|
stream: true,
|
|
247
257
|
...aiRequestOptions,
|
|
248
258
|
};
|
|
249
259
|
|
|
250
260
|
// Only include reasoning configuration if reasoning tokens are enabled
|
|
251
|
-
if (enableReasoningTokens) {
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
}
|
|
261
|
+
// if (enableReasoningTokens) {
|
|
262
|
+
// requestConfig.reasoning = {
|
|
263
|
+
// effort: 'low',
|
|
264
|
+
// exclude: false,
|
|
265
|
+
// };
|
|
266
|
+
// }
|
|
257
267
|
|
|
258
268
|
const stream = await (
|
|
259
269
|
openRouterClient.chat.completions.create as any
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# LLM Streaming UI
|
|
2
|
+
|
|
3
|
+
Client-side React UI components for displaying streaming AI edits and chat.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
This module is being extracted from VZCode's AI chat interface to become a standalone, reusable React component library. It provides client-side UI functionality for:
|
|
8
|
+
|
|
9
|
+
- **AI Chat Interface**: Main chat container component
|
|
10
|
+
- **Message Display**: Rendering user and AI messages with streaming support
|
|
11
|
+
- **Diff Visualization**: Showing code changes with syntax highlighting
|
|
12
|
+
- **Status Indicators**: Displaying AI thinking/reasoning and file editing status
|
|
13
|
+
- **Voice Input**: Speech recognition for voice-based chat input
|
|
14
|
+
|
|
15
|
+
## Current Status
|
|
16
|
+
|
|
17
|
+
⚠️ **Work in Progress**: This is Phase 1 of the extraction plan. The files have been copied to this directory and imports have been updated, but the components are not yet decoupled from VZCode.
|
|
18
|
+
|
|
19
|
+
## Components
|
|
20
|
+
|
|
21
|
+
### Main Components
|
|
22
|
+
|
|
23
|
+
- `index.tsx` (AIChat) - Main chat container with message management
|
|
24
|
+
- `MessageList.tsx` - Scrollable message list with auto-scroll
|
|
25
|
+
- `Message.tsx` - Individual message rendering (user/assistant)
|
|
26
|
+
- `ChatInput.tsx` - Chat input field with voice support
|
|
27
|
+
|
|
28
|
+
### Diff/Code Display
|
|
29
|
+
|
|
30
|
+
- `DiffView.tsx` - Unified diff viewer for code changes
|
|
31
|
+
- `IndividualFileDiff.tsx` - Per-file diff display
|
|
32
|
+
- `FileEditingIndicator.tsx` - Status indicator for file editing
|
|
33
|
+
|
|
34
|
+
### Status/Loading
|
|
35
|
+
|
|
36
|
+
- `TypingIndicator.tsx` - Animated typing/loading indicator
|
|
37
|
+
- `ThinkingScratchpad.tsx` - AI reasoning/thinking display
|
|
38
|
+
- `JumpToLatestButton.tsx` - Button to scroll to latest message
|
|
39
|
+
|
|
40
|
+
### Hooks
|
|
41
|
+
|
|
42
|
+
- `useSpeechRecognition.ts` - Voice input functionality
|
|
43
|
+
|
|
44
|
+
### Styles
|
|
45
|
+
|
|
46
|
+
- `styles.scss` - Main component styles
|
|
47
|
+
- `DiffView.scss` - Diff viewer styles
|
|
48
|
+
|
|
49
|
+
## Dependencies
|
|
50
|
+
|
|
51
|
+
Currently depends on:
|
|
52
|
+
|
|
53
|
+
- React and React hooks
|
|
54
|
+
- VZCode context: `../../client/VZCodeContext`
|
|
55
|
+
- VZCode types: `../../types.js`
|
|
56
|
+
- VZCode utilities: `../../client/hooks/*`, `../../utils/*`
|
|
57
|
+
- Bootstrap components
|
|
58
|
+
- diff2html for diff rendering
|
|
59
|
+
- react-markdown for message rendering
|
|
60
|
+
|
|
61
|
+
## Future Plans
|
|
62
|
+
|
|
63
|
+
This module will eventually be:
|
|
64
|
+
|
|
65
|
+
1. Decoupled from VZCode-specific context and utilities
|
|
66
|
+
2. Published as `@vizhub/llm-streaming-ui` on npm
|
|
67
|
+
3. Made themeable and customizable
|
|
68
|
+
4. Provided with Storybook documentation
|
|
69
|
+
5. Fully typed with exported TypeScript interfaces
|
|
70
|
+
|
|
71
|
+
See the [main issue](https://github.com/vizhub-core/vzcode/issues/XXX) for the full extraction plan.
|
|
72
|
+
|
|
73
|
+
## Usage (Current)
|
|
74
|
+
|
|
75
|
+
Currently, this module is imported by `src/client/VZSidebar/index.tsx`:
|
|
76
|
+
|
|
77
|
+
```typescript
|
|
78
|
+
import { AIChat } from '../../llm-streaming-ui/components/index.js';
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
The AIChat component expects VZCode context to be available and receives props like:
|
|
82
|
+
|
|
83
|
+
- Chat state from VZCodeContext
|
|
84
|
+
- Message sending handlers
|
|
85
|
+
- Auto-scroll configuration
|
|
86
|
+
|
|
87
|
+
## Contributing
|
|
88
|
+
|
|
89
|
+
As this module is being extracted, please:
|
|
90
|
+
|
|
91
|
+
- Keep changes minimal and focused
|
|
92
|
+
- Maintain backward compatibility with VZCode
|
|
93
|
+
- Update component tests when modifying functionality
|
|
94
|
+
- Consider future consumers when adding new dependencies
|
|
95
|
+
- Document component props and behavior
|
|
96
|
+
|
|
97
|
+
## Theming
|
|
98
|
+
|
|
99
|
+
The components currently use VZCode's theming system via SCSS variables. Future versions will provide:
|
|
100
|
+
|
|
101
|
+
- CSS custom properties for theming
|
|
102
|
+
- Light/dark theme presets
|
|
103
|
+
- Customizable component styling
|
|
@@ -9,10 +9,10 @@ import {
|
|
|
9
9
|
Button,
|
|
10
10
|
ButtonGroup,
|
|
11
11
|
ToggleButton,
|
|
12
|
-
} from '../../bootstrap';
|
|
13
|
-
import { enableAskMode } from '../../featureFlags';
|
|
12
|
+
} from '../../client/bootstrap';
|
|
13
|
+
import { enableAskMode } from '../../client/featureFlags';
|
|
14
14
|
import { useSpeechRecognition } from './useSpeechRecognition';
|
|
15
|
-
import { MicSVG, MicOffSVG } from '../../Icons';
|
|
15
|
+
import { MicSVG, MicOffSVG } from '../../client/Icons';
|
|
16
16
|
|
|
17
17
|
interface ChatInputProps {
|
|
18
18
|
aiChatMessage: string;
|
|
@@ -11,16 +11,16 @@ import {
|
|
|
11
11
|
combineUnifiedDiffs,
|
|
12
12
|
isFileDeletion,
|
|
13
13
|
getDeletedFileName,
|
|
14
|
-
} from '
|
|
14
|
+
} from '../../utils/fileDiff';
|
|
15
15
|
import * as Diff2Html from 'diff2html';
|
|
16
16
|
import 'diff2html/bundles/css/diff2html.min.css';
|
|
17
17
|
import './DiffView.scss';
|
|
18
|
-
import { VZCodeContext } from '../../VZCodeContext';
|
|
18
|
+
import { VZCodeContext } from '../../client/VZCodeContext';
|
|
19
19
|
import {
|
|
20
20
|
scrollToFirstDiff,
|
|
21
21
|
getHeaderOffset,
|
|
22
22
|
announceDiffSummary,
|
|
23
|
-
} from '../../utils/scrollUtils';
|
|
23
|
+
} from '../../client/utils/scrollUtils';
|
|
24
24
|
import { getFileId } from '@vizhub/viz-utils';
|
|
25
25
|
|
|
26
26
|
interface DiffViewProps {
|
|
@@ -2,7 +2,7 @@ import React, { useMemo } from 'react';
|
|
|
2
2
|
import * as Diff2Html from 'diff2html';
|
|
3
3
|
import 'diff2html/bundles/css/diff2html.min.css';
|
|
4
4
|
import './DiffView.scss';
|
|
5
|
-
import { generateFileUnifiedDiff } from '
|
|
5
|
+
import { generateFileUnifiedDiff } from '../../utils/fileDiff';
|
|
6
6
|
|
|
7
7
|
interface IndividualFileDiffProps {
|
|
8
8
|
fileName: string;
|
|
@@ -6,14 +6,14 @@ import React, {
|
|
|
6
6
|
import { timestampToDate } from '@vizhub/viz-utils';
|
|
7
7
|
import Markdown from 'react-markdown';
|
|
8
8
|
import remarkGfm from 'remark-gfm';
|
|
9
|
-
import { StreamingEvent } from '
|
|
9
|
+
import { StreamingEvent } from '../../types.js';
|
|
10
10
|
import { IndividualFileDiff } from './IndividualFileDiff';
|
|
11
|
-
import { VZCodeContext } from '../../VZCodeContext';
|
|
11
|
+
import { VZCodeContext } from '../../client/VZCodeContext';
|
|
12
12
|
import { DiffView, DiffViewRef } from './DiffView';
|
|
13
|
-
import { UnifiedFilesDiff } from '
|
|
14
|
-
import { enableDiffView } from '../../featureFlags';
|
|
13
|
+
import { UnifiedFilesDiff } from '../../utils/fileDiff';
|
|
14
|
+
import { enableDiffView } from '../../client/featureFlags';
|
|
15
15
|
|
|
16
|
-
const DEBUG =
|
|
16
|
+
const DEBUG = true;
|
|
17
17
|
|
|
18
18
|
interface MessageProps {
|
|
19
19
|
id: string;
|
|
@@ -26,6 +26,7 @@ interface MessageProps {
|
|
|
26
26
|
showAdditionalWidgets?: boolean;
|
|
27
27
|
isStreaming?: boolean;
|
|
28
28
|
diffData?: UnifiedFilesDiff;
|
|
29
|
+
model?: string; // The LLM model used for this message (assistant only)
|
|
29
30
|
}
|
|
30
31
|
|
|
31
32
|
export const Message = forwardRef<
|
|
@@ -45,18 +46,13 @@ export const Message = forwardRef<
|
|
|
45
46
|
showAdditionalWidgets = false,
|
|
46
47
|
isStreaming = false,
|
|
47
48
|
diffData,
|
|
49
|
+
model,
|
|
48
50
|
},
|
|
49
51
|
ref,
|
|
50
52
|
) => {
|
|
51
53
|
const { additionalWidgets, handleSendMessage } =
|
|
52
54
|
useContext(VZCodeContext);
|
|
53
55
|
|
|
54
|
-
DEBUG &&
|
|
55
|
-
console.log(
|
|
56
|
-
'StreamingMessage: Rendered with events:',
|
|
57
|
-
events,
|
|
58
|
-
);
|
|
59
|
-
|
|
60
56
|
// Memoize date formatting to avoid repeated computation
|
|
61
57
|
const formattedTime = useMemo(() => {
|
|
62
58
|
return timestampToDate(timestamp).toLocaleTimeString(
|
|
@@ -76,6 +72,11 @@ export const Message = forwardRef<
|
|
|
76
72
|
return (
|
|
77
73
|
<div className={messageClassName}>
|
|
78
74
|
<div className="ai-chat-message-content">
|
|
75
|
+
{/* Model indicator for assistant messages */}
|
|
76
|
+
{role === 'assistant' && model && (
|
|
77
|
+
<div className="model-indicator">{model}</div>
|
|
78
|
+
)}
|
|
79
|
+
|
|
79
80
|
{/* Render regular content for non-streaming messages */}
|
|
80
81
|
{content && (
|
|
81
82
|
<Markdown remarkPlugins={[remarkGfm]}>
|
|
@@ -10,9 +10,9 @@ import { TypingIndicator } from './TypingIndicator';
|
|
|
10
10
|
import { ThinkingScratchpad } from './ThinkingScratchpad';
|
|
11
11
|
import { AIEditingStatusIndicator } from './FileEditingIndicator';
|
|
12
12
|
import { VizChatMessage } from '@vizhub/viz-types';
|
|
13
|
-
import { ExtendedVizChatMessage } from '
|
|
13
|
+
import { ExtendedVizChatMessage } from '../../types.js';
|
|
14
14
|
import { DiffViewRef } from './DiffView.js';
|
|
15
|
-
import { VZCodeContext } from '../../VZCodeContext';
|
|
15
|
+
import { VZCodeContext } from '../../client/VZCodeContext';
|
|
16
16
|
|
|
17
17
|
const MessageListComponent = ({
|
|
18
18
|
messages,
|
|
@@ -20,6 +20,7 @@ const MessageListComponent = ({
|
|
|
20
20
|
chatId, // Add chatId prop
|
|
21
21
|
aiScratchpad, // Add aiScratchpad prop
|
|
22
22
|
currentStatus, // Add current status prop
|
|
23
|
+
model, // Add model prop
|
|
23
24
|
onNewEvent,
|
|
24
25
|
onJumpToLatest,
|
|
25
26
|
beforeRender,
|
|
@@ -30,6 +31,7 @@ const MessageListComponent = ({
|
|
|
30
31
|
chatId?: string; // Add chatId to the type
|
|
31
32
|
aiScratchpad?: string; // Add aiScratchpad to the type
|
|
32
33
|
currentStatus?: string; // Add current status to the type
|
|
34
|
+
model?: string; // Add model to the type
|
|
33
35
|
onNewEvent: (targetElement?: HTMLElement) => void;
|
|
34
36
|
onJumpToLatest: (targetElement?: HTMLElement) => void;
|
|
35
37
|
beforeRender: () => number;
|
|
@@ -192,6 +194,9 @@ const MessageListComponent = ({
|
|
|
192
194
|
showAdditionalWidgets={showAdditionalWidgets}
|
|
193
195
|
isStreaming={isStreamingMessage}
|
|
194
196
|
diffData={(msg as any).diffData}
|
|
197
|
+
model={
|
|
198
|
+
msg.role === 'assistant' ? model : undefined
|
|
199
|
+
}
|
|
195
200
|
ref={
|
|
196
201
|
isLastMessage && (msg as any).diffData
|
|
197
202
|
? diffViewRef
|
|
@@ -4,11 +4,11 @@ import {
|
|
|
4
4
|
useEffect,
|
|
5
5
|
useCallback,
|
|
6
6
|
} from 'react';
|
|
7
|
-
import { VZCodeContext } from '../../VZCodeContext';
|
|
7
|
+
import { VZCodeContext } from '../../client/VZCodeContext';
|
|
8
8
|
import { MessageList } from './MessageList';
|
|
9
9
|
import { ChatInput } from './ChatInput';
|
|
10
|
-
import { ExtendedVizChat } from '
|
|
11
|
-
import { useAutoScroll } from '../../hooks/useAutoScroll';
|
|
10
|
+
import { ExtendedVizChat } from '../../types.js';
|
|
11
|
+
import { useAutoScroll } from '../../client/hooks/useAutoScroll';
|
|
12
12
|
import { JumpToLatestButton } from './JumpToLatestButton';
|
|
13
13
|
import './styles.scss';
|
|
14
14
|
|
|
@@ -92,9 +92,8 @@ export const AIChat = () => {
|
|
|
92
92
|
const aiScratchpad = currentChat?.aiScratchpad;
|
|
93
93
|
const currentStatus = (currentChat as ExtendedVizChat)
|
|
94
94
|
?.currentStatus;
|
|
95
|
+
const model = (currentChat as ExtendedVizChat)?.model;
|
|
95
96
|
|
|
96
|
-
// Debug logging for AI status
|
|
97
|
-
DEBUG && console.log('AIChat: currentChat:', currentChat);
|
|
98
97
|
DEBUG && console.log('AIChat: aiStatus:', aiStatus);
|
|
99
98
|
DEBUG &&
|
|
100
99
|
console.log(
|
|
@@ -332,6 +331,7 @@ export const AIChat = () => {
|
|
|
332
331
|
chatId={selectedChatId || currentChatId}
|
|
333
332
|
aiScratchpad={aiScratchpad}
|
|
334
333
|
currentStatus={currentStatus}
|
|
334
|
+
model={model}
|
|
335
335
|
onNewEvent={onNewEvent}
|
|
336
336
|
onJumpToLatest={onJumpToLatest}
|
|
337
337
|
beforeRender={beforeRender}
|
|
@@ -314,6 +314,16 @@
|
|
|
314
314
|
padding: 0 1em;
|
|
315
315
|
}
|
|
316
316
|
|
|
317
|
+
.model-indicator {
|
|
318
|
+
opacity: 0.6;
|
|
319
|
+
font-size: 0.7rem;
|
|
320
|
+
color: var(--vscode-descriptionForeground);
|
|
321
|
+
padding: 0.25rem 0.5rem;
|
|
322
|
+
font-family: var(--vscode-editor-font-family);
|
|
323
|
+
letter-spacing: 0.3px;
|
|
324
|
+
margin-bottom: 0.5rem;
|
|
325
|
+
}
|
|
326
|
+
|
|
317
327
|
padding: 10px 12px;
|
|
318
328
|
font-size: 14px;
|
|
319
329
|
line-height: 1.4;
|
|
@@ -362,6 +372,25 @@
|
|
|
362
372
|
margin-top: 1rem;
|
|
363
373
|
margin-bottom: 0.5rem;
|
|
364
374
|
color: inherit;
|
|
375
|
+
font-weight: 600;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
h1 {
|
|
379
|
+
font-size: 1.25rem; // 20px at 16px base
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
h2 {
|
|
383
|
+
font-size: 1.125rem; // 18px at 16px base
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
h3 {
|
|
387
|
+
font-size: 1rem; // 16px at 16px base
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
h4,
|
|
391
|
+
h5,
|
|
392
|
+
h6 {
|
|
393
|
+
font-size: 0.875rem; // 14px at 16px base
|
|
365
394
|
}
|
|
366
395
|
|
|
367
396
|
ul,
|
|
@@ -784,10 +813,29 @@
|
|
|
784
813
|
h6 {
|
|
785
814
|
margin: 8px 0 6px 0;
|
|
786
815
|
color: var(--vh-color-neutral-04);
|
|
816
|
+
font-weight: 600;
|
|
787
817
|
|
|
788
818
|
&:first-child {
|
|
789
819
|
margin-top: 0;
|
|
790
820
|
}
|
|
791
821
|
}
|
|
822
|
+
|
|
823
|
+
h1 {
|
|
824
|
+
font-size: 1.125rem; // 18px at 16px base
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
h2 {
|
|
828
|
+
font-size: 1rem; // 16px at 16px base
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
h3 {
|
|
832
|
+
font-size: 0.9375rem; // 15px at 16px base
|
|
833
|
+
}
|
|
834
|
+
|
|
835
|
+
h4,
|
|
836
|
+
h5,
|
|
837
|
+
h6 {
|
|
838
|
+
font-size: 0.8125rem; // 13px at 16px base
|
|
839
|
+
}
|
|
792
840
|
}
|
|
793
841
|
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @vizhub/llm-streaming-ui
|
|
3
|
+
*
|
|
4
|
+
* Client-side React UI components for displaying streaming AI edits and chat.
|
|
5
|
+
* This module provides functionality for:
|
|
6
|
+
* - Displaying AI chat messages with streaming support
|
|
7
|
+
* - Showing real-time diffs and code changes
|
|
8
|
+
* - Rendering thinking/reasoning scratchpads
|
|
9
|
+
* - Managing file editing indicators
|
|
10
|
+
* - Voice input support
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
// Main AI Chat component
|
|
14
|
+
export { AIChat } from './components/index.js';
|
|
15
|
+
|
|
16
|
+
// Message display components
|
|
17
|
+
export { MessageList } from './components/MessageList.js';
|
|
18
|
+
export { Message } from './components/Message.js';
|
|
19
|
+
|
|
20
|
+
// Diff visualization components
|
|
21
|
+
export { DiffView } from './components/DiffView.js';
|
|
22
|
+
export { IndividualFileDiff } from './components/IndividualFileDiff.js';
|
|
23
|
+
|
|
24
|
+
// Status and indicator components
|
|
25
|
+
export { TypingIndicator } from './components/TypingIndicator.js';
|
|
26
|
+
export { ThinkingScratchpad } from './components/ThinkingScratchpad.js';
|
|
27
|
+
export { AIEditingStatusIndicator as FileEditingIndicator } from './components/FileEditingIndicator';
|
|
28
|
+
export { JumpToLatestButton } from './components/JumpToLatestButton.js';
|
|
29
|
+
|
|
30
|
+
// Input components
|
|
31
|
+
export { ChatInput } from './components/ChatInput.js';
|
|
32
|
+
|
|
33
|
+
// Custom hooks
|
|
34
|
+
export { useSpeechRecognition } from './components/useSpeechRecognition.js';
|
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import { validateRequest } from '
|
|
1
|
+
import { validateRequest } from '../../llm-streaming-server/validation.js';
|
|
2
2
|
import {
|
|
3
3
|
ensureChatsExist,
|
|
4
4
|
ensureChatExists,
|
|
5
5
|
addUserMessage,
|
|
6
6
|
setAIStatus,
|
|
7
|
-
} from '
|
|
8
|
-
import { createLLMFunction } from '
|
|
9
|
-
import { performAIEditing } from '
|
|
7
|
+
} from '../../llm-streaming-server/chatOperations.js';
|
|
8
|
+
import { createLLMFunction } from '../../llm-streaming-server/llmStreaming.js';
|
|
9
|
+
import { performAIEditing } from '../../llm-streaming-server/aiEditing.js';
|
|
10
10
|
import {
|
|
11
11
|
handleError,
|
|
12
12
|
handleBackgroundError,
|
|
13
|
-
} from '
|
|
13
|
+
} from '../../llm-streaming-server/errorHandling.js';
|
|
14
14
|
import { createRunCodeFunction } from '../../runCode.js';
|
|
15
15
|
import { ShareDBDoc } from '../../types.js';
|
|
16
16
|
import { VizContent } from '@vizhub/viz-types';
|
|
@@ -25,11 +25,13 @@ export const handleAIChatMessage =
|
|
|
25
25
|
onCreditDeduction,
|
|
26
26
|
model,
|
|
27
27
|
aiRequestOptions,
|
|
28
|
+
enableReasoningTokens,
|
|
28
29
|
}: {
|
|
29
30
|
shareDBDoc: ShareDBDoc<VizContent>;
|
|
30
31
|
onCreditDeduction?: any;
|
|
31
32
|
model?: string;
|
|
32
33
|
aiRequestOptions?: any;
|
|
34
|
+
enableReasoningTokens?: boolean;
|
|
33
35
|
}) =>
|
|
34
36
|
async (req: any, res: any) => {
|
|
35
37
|
const { content, chatId } = req.body;
|
|
@@ -68,6 +70,7 @@ export const handleAIChatMessage =
|
|
|
68
70
|
content,
|
|
69
71
|
model,
|
|
70
72
|
aiRequestOptions,
|
|
73
|
+
enableReasoningTokens,
|
|
71
74
|
onCreditDeduction,
|
|
72
75
|
}).catch((error) => {
|
|
73
76
|
console.error(
|
|
@@ -91,6 +94,7 @@ const processAIRequestAsync = async ({
|
|
|
91
94
|
content,
|
|
92
95
|
model,
|
|
93
96
|
aiRequestOptions,
|
|
97
|
+
enableReasoningTokens,
|
|
94
98
|
onCreditDeduction,
|
|
95
99
|
}: {
|
|
96
100
|
shareDBDoc: ShareDBDoc<VizContent>;
|
|
@@ -98,6 +102,7 @@ const processAIRequestAsync = async ({
|
|
|
98
102
|
content: string;
|
|
99
103
|
model?: string;
|
|
100
104
|
aiRequestOptions?: any;
|
|
105
|
+
enableReasoningTokens?: boolean;
|
|
101
106
|
onCreditDeduction?: any;
|
|
102
107
|
}) => {
|
|
103
108
|
try {
|
|
@@ -105,6 +110,7 @@ const processAIRequestAsync = async ({
|
|
|
105
110
|
const llmFunction = createLLMFunction({
|
|
106
111
|
shareDBDoc,
|
|
107
112
|
chatId,
|
|
113
|
+
enableReasoningTokens: enableReasoningTokens ?? true,
|
|
108
114
|
model,
|
|
109
115
|
aiRequestOptions,
|
|
110
116
|
});
|
package/src/types.ts
CHANGED
|
@@ -261,6 +261,7 @@ export interface ExtendedVizChat extends VizChat {
|
|
|
261
261
|
streamingEvents?: StreamingEvent[];
|
|
262
262
|
currentStatus?: string;
|
|
263
263
|
isStreaming?: boolean;
|
|
264
|
+
model?: string; // The LLM model used for this chat
|
|
264
265
|
}
|
|
265
266
|
|
|
266
267
|
// Extended VizChatMessage with progressive rendering support
|