feat(desktop): DeerFlow visual redesign + stream hang fix + intelligence client
Some checks failed
CI / Lint & TypeCheck (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Build Frontend (push) Has been cancelled
CI / Rust Check (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled

DeerFlow frontend visual overhaul:
- Card-style input box (white rounded card, textarea top, actions bottom)
- Dropdown mode selector (闪速/思考/Pro/Ultra with icons+descriptions)
- Colored quick-action chips (小惊喜/写作/研究/收集/学习)
- Minimal top bar (title + token count + export)
- Warm gray color system (#faf9f6 bg, #f5f4f1 sidebar, #e8e6e1 border)
- DeerFlow-style sidebar (新对话/对话/智能体 nav)
- Reasoning block, tool call chain, task progress visualization
- Streaming text, model selector, suggestion chips components
- Resizable artifact panel with drag handle
- Virtualized message list for 100+ messages

Bug fixes:
- Stream hang: GatewayClient onclose code 1000 now calls onComplete
- WebView2 textarea border: CSS !important override for UA styles
- Gateway stream event handling (response/phase/tool_call types)

Intelligence client:
- Unified client with fallback drivers (compactor/heartbeat/identity/memory/reflection)
- Gateway API types and type conversions
This commit is contained in:
iven
2026-04-01 22:03:07 +08:00
parent e3b93ff96d
commit 73ff5e8c5e
43 changed files with 4817 additions and 905 deletions

View File

@@ -56,6 +56,9 @@ export function installChatMethods(ClientClass: { prototype: KernelClient }): vo
opts?: {
sessionKey?: string;
agentId?: string;
thinking_enabled?: boolean;
reasoning_effort?: string;
plan_mode?: boolean;
}
): Promise<{ runId: string }> {
const runId = crypto.randomUUID();
@@ -68,6 +71,20 @@ export function installChatMethods(ClientClass: { prototype: KernelClient }): vo
}
let unlisten: UnlistenFn | null = null;
let completed = false;
// Stream timeout — prevent hanging forever if backend never sends complete/error
const STREAM_TIMEOUT_MS = 5 * 60 * 1000; // 5 minutes
const timeoutId = setTimeout(() => {
if (!completed) {
completed = true;
log.warn('Stream timeout — no complete/error event received');
callbacks.onError('响应超时,请重试');
if (unlisten) {
unlisten();
unlisten = null;
}
}
}, STREAM_TIMEOUT_MS);
try {
// Set up event listener for stream chunks
@@ -129,6 +146,8 @@ export function installChatMethods(ClientClass: { prototype: KernelClient }): vo
case 'complete':
log.debug('Stream complete:', streamEvent.inputTokens, streamEvent.outputTokens);
completed = true;
clearTimeout(timeoutId);
callbacks.onComplete(streamEvent.inputTokens, streamEvent.outputTokens);
// Clean up listener
if (unlisten) {
@@ -139,6 +158,8 @@ export function installChatMethods(ClientClass: { prototype: KernelClient }): vo
case 'error':
log.error('Stream error:', streamEvent.message);
completed = true;
clearTimeout(timeoutId);
callbacks.onError(streamEvent.message);
// Clean up listener
if (unlisten) {
@@ -155,6 +176,9 @@ export function installChatMethods(ClientClass: { prototype: KernelClient }): vo
agentId,
sessionId,
message,
thinkingEnabled: opts?.thinking_enabled,
reasoningEffort: opts?.reasoning_effort,
planMode: opts?.plan_mode,
},
});
} catch (err: unknown) {