feat(web): 前端收敛为「共享消息流 + 按消息 mode 渲染」,并补全 emoji→MD3 图标
架构变更(主人要求,design/07 §1/§2 已改定稿):把「9 个行为模式 = 9 个独立页面」改为 「一个共享页面 + 每条消息绑 mode,消息框按对应 mode 渲染」。 - ChatMessage 增 mode?(types.ts);useAppStore addUserMessage/beginAssistant 带 mode; useSendChat.send(text, mode) / chatStream body 带 mode(通知后端按 mode 回复)。 - MessageBubble 按 message.mode 分发到 components/messages/ 各形态渲染器 (chat 气泡 / code 等宽代码块 / home 设备卡 / docs 文档卡 / work 任务卡 / vision 视觉卡)。 - ChatInput 顶部加「行为模式」chip 切换下一条消息的 mode(默认 chat);输入框上方显示当前模式。 - ModeRouter 收敛为只渲染 ChatShell;删除 9 个旧独立 mode 页面;Nav/TopBar 的 mode 改为 「输入模式」语义;settings 归管理面板(design/10)。 同时补全上一轮 emoji→MD3 图标(约 23 文件):新增 Icon.tsx(MD3 SVG、IconName、零依赖、 离线优先),全部界面 emoji 替换为 <Icon name=... />;正文说明箭头保留。 npm run build 绿(tsc 0 错,79→71 模块,JS 284KB/gzip 86KB)。
This commit is contained in:
1 parent
265b207699
commit
4aab0f501a
28 files changed
+539
-950
No files matched your search
@@ -9,6 +9,7 @@ import type {
|
||||
ChatSyncResult,
|
||||
LoginResult,
|
||||
MemoryRecord,
|
||||
Mode,
|
||||
PersonaRecord,
|
||||
Role,
|
||||
SessionRecord,
|
||||
@@ -154,10 +155,10 @@ export function chatSync(
|
||||
}
|
||||
|
||||
/** POST /api/v1/chat with stream:true — triggers streaming over the WS channel. */
|
||||
export function chatStream(sessionId: string, text: string): Promise<{ stream: true }> {
|
||||
export function chatStream(sessionId: string, text: string, mode?: Mode): Promise<{ stream: true }> {
|
||||
return request<{ stream: true }>("/chat", {
|
||||
method: "POST",
|
||||
body: JSON.stringify({ sessionId, text, stream: true }),
|
||||
body: JSON.stringify({ sessionId, text, stream: true, mode }),
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -44,6 +44,9 @@ export interface ChatMessage {
|
||||
id: string;
|
||||
role: "user" | "assistant" | "system";
|
||||
content: string;
|
||||
/** Behavior mode this message was produced in — drives its bubble rendering.
|
||||
* Each message carries its own mode, so a single session can mix bubble shapes. */
|
||||
mode?: Mode;
|
||||
streaming?: boolean;
|
||||
thinking?: string;
|
||||
mood?: string;
|
||||
|
||||
@@ -2,14 +2,19 @@ import { useCallback, useState } from "react";
|
||||
import { chatStream } from "./api";
|
||||
import { connectWs, isWsOpen } from "./ws";
|
||||
import { useAppStore } from "../store/useAppStore";
|
||||
import { useModeStore } from "../store/useModeStore";
|
||||
import { now } from "./util";
|
||||
import type { Mode } from "./types";
|
||||
|
||||
/** Drives one user turn: push the user bubble, blanket a streaming assistant
|
||||
* bubble, trigger the backend loop over REST (`stream:true`), and let the WS
|
||||
* stream render into that bubble. Falls back to the WS `chat` channel when the
|
||||
* REST trigger fails so the demo still works without a wired loop. */
|
||||
* REST trigger fails so the demo still works without a wired loop.
|
||||
*
|
||||
* Each message carries the current input mode, so its bubble renders per that
|
||||
* mode (design/07 §1: shared message stream, per-message mode rendering). */
|
||||
export function useSendChat(): {
|
||||
send: (text: string) => Promise<void>;
|
||||
send: (text: string, mode?: Mode) => Promise<void>;
|
||||
sending: boolean;
|
||||
} {
|
||||
const [sending, setSending] = useState(false);
|
||||
@@ -22,17 +27,18 @@ export function useSendChat(): {
|
||||
const appendTaskLog = useAppStore((s) => s.appendTaskLog);
|
||||
|
||||
const send = useCallback(
|
||||
async (text: string) => {
|
||||
async (text: string, mode?: Mode) => {
|
||||
const trimmed = text.trim();
|
||||
if (!trimmed || sending) return;
|
||||
setSending(true);
|
||||
if (!isWsOpen()) connectWs();
|
||||
|
||||
addUserMessage(trimmed);
|
||||
beginAssistant();
|
||||
const m = mode ?? "chat";
|
||||
addUserMessage(trimmed, m);
|
||||
beginAssistant(m);
|
||||
|
||||
try {
|
||||
await chatStream(sessionId, trimmed);
|
||||
await chatStream(sessionId, trimmed, m);
|
||||
} catch (err: unknown) {
|
||||
// Backend loop not wired or gateway unreachable: show the failure inline
|
||||
// rather than leaving a permanently-streaming bubble.
|
||||
|
||||
Reference in new issue
Block a user