feat(web): add markdown syntax highlighting, slash commands, stop button, quote/reply
- PromptEditor with Prism.js syntax highlighting - Slash commands (/run, /status, /images, /list, /help) in chat input - Stop button to cancel ongoing generation - Quote/reply and regenerate/continue actions in chat - MiddlePanel with conversation timestamps and preview - Pipeline progress in chat view - Fix all remaining dark theme classes Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -2,12 +2,12 @@ import { useState, useEffect, useCallback, useRef } from 'react';
|
||||
import { chatSocket } from '@/lib/websocket';
|
||||
import type { Message } from '@/types';
|
||||
|
||||
interface StreamingMessage {
|
||||
id: string;
|
||||
role: 'assistant';
|
||||
content: string;
|
||||
created_at: string;
|
||||
streaming: boolean;
|
||||
interface PipelineState {
|
||||
phase: string;
|
||||
progress: number;
|
||||
currentItem?: number;
|
||||
totalItems?: number;
|
||||
status?: string;
|
||||
}
|
||||
|
||||
export function useChat(conversationId: string | null) {
|
||||
@@ -15,6 +15,7 @@ export function useChat(conversationId: string | null) {
|
||||
const [connected, setConnected] = useState(false);
|
||||
const [thinking, setThinking] = useState(false);
|
||||
const [toolStatus, setToolStatus] = useState<string | null>(null);
|
||||
const [pipeline, setPipeline] = useState<PipelineState | null>(null);
|
||||
const pendingRef = useRef(false);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -30,14 +31,14 @@ export function useChat(conversationId: string | null) {
|
||||
setMessages((prev) => [...prev, data as unknown as Message]);
|
||||
});
|
||||
|
||||
// Streaming handlers
|
||||
// Streaming
|
||||
chatSocket.on('status', (data) => {
|
||||
if (data.status === 'thinking') setThinking(true);
|
||||
if (data.status === 'done') { setThinking(false); setToolStatus(null); }
|
||||
});
|
||||
|
||||
chatSocket.on('message_start', (data) => {
|
||||
setThinking(false);
|
||||
// Add placeholder for streaming
|
||||
setMessages((prev) => [...prev, {
|
||||
id: data.id as string,
|
||||
role: 'assistant',
|
||||
@@ -57,23 +58,41 @@ export function useChat(conversationId: string | null) {
|
||||
setThinking(false);
|
||||
});
|
||||
|
||||
// Tools
|
||||
chatSocket.on('tool_start', (data) => {
|
||||
setToolStatus(`正在执行: ${data.tool}...`);
|
||||
setToolStatus(`执行: ${data.tool}...`);
|
||||
});
|
||||
|
||||
chatSocket.on('tool_result', () => {
|
||||
chatSocket.on('tool_result', (data) => {
|
||||
setToolStatus(null);
|
||||
setThinking(true);
|
||||
// Save tool result as a tool-type message for inline display
|
||||
setMessages((prev) => [...prev, {
|
||||
id: `tool-${Date.now()}`,
|
||||
role: 'tool' as const,
|
||||
content: JSON.stringify({ tool: data.tool, result: data.result }),
|
||||
created_at: new Date().toISOString(),
|
||||
conversation_id: '',
|
||||
}]);
|
||||
});
|
||||
|
||||
chatSocket.on('tool_error', (data) => {
|
||||
setToolStatus(`工具执行失败: ${data.tool}`);
|
||||
setTimeout(() => setToolStatus(null), 3000);
|
||||
setToolStatus(`失败: ${data.tool}`);
|
||||
setTimeout(() => setToolStatus(null), 4000);
|
||||
});
|
||||
|
||||
return () => {
|
||||
chatSocket.disconnect();
|
||||
};
|
||||
// Pipeline progress
|
||||
chatSocket.on('pipeline_progress', (data) => {
|
||||
setPipeline({
|
||||
phase: data.phase as string,
|
||||
progress: data.progress as number,
|
||||
currentItem: data.currentItem as number,
|
||||
totalItems: data.totalItems as number,
|
||||
status: data.status as string,
|
||||
});
|
||||
});
|
||||
|
||||
return () => { chatSocket.disconnect(); };
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -91,9 +110,13 @@ export function useChat(conversationId: string | null) {
|
||||
chatSocket.send('chat', { content });
|
||||
}, []);
|
||||
|
||||
const stop = useCallback(() => {
|
||||
chatSocket.stop();
|
||||
}, []);
|
||||
|
||||
const createConversation = useCallback((title: string, accountId?: string) => {
|
||||
chatSocket.send('create_conversation', { title, accountId });
|
||||
}, []);
|
||||
|
||||
return { messages, connected, thinking, toolStatus, send, createConversation };
|
||||
return { messages, connected, thinking, toolStatus, pipeline, send, stop, createConversation };
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user