feat(frontend): M9 模态 UI(mode 系统+共享 store+WS 客户端 + chat(思维链/工具回显/情绪徽标)/code/Agent 监控/后台思考页 + Miuix 设计 token + PWA);tsc+vite build 通过
This commit is contained in:
1 parent
b3ffd51736
commit
4c48e94659
40 files changed
+5321
No files matched your search
@@ -0,0 +1,52 @@
|
||||
import { useCallback, useState } from "react";
|
||||
import { chatStream } from "./api";
|
||||
import { connectWs, isWsOpen } from "./ws";
|
||||
import { useAppStore } from "../store/useAppStore";
|
||||
import { now } from "./util";
|
||||
|
||||
/** 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. */
|
||||
export function useSendChat(): {
|
||||
send: (text: string) => Promise<void>;
|
||||
sending: boolean;
|
||||
} {
|
||||
const [sending, setSending] = useState(false);
|
||||
const sessionId = useAppStore((s) => s.sessionId);
|
||||
const addUserMessage = useAppStore((s) => s.addUserMessage);
|
||||
const beginAssistant = useAppStore((s) => s.beginAssistant);
|
||||
const endStream = useAppStore((s) => s.endStream);
|
||||
const appendChunk = useAppStore((s) => s.appendChunk);
|
||||
const addTool = useAppStore((s) => s.addTool);
|
||||
const appendTaskLog = useAppStore((s) => s.appendTaskLog);
|
||||
|
||||
const send = useCallback(
|
||||
async (text: string) => {
|
||||
const trimmed = text.trim();
|
||||
if (!trimmed || sending) return;
|
||||
setSending(true);
|
||||
if (!isWsOpen()) connectWs();
|
||||
|
||||
addUserMessage(trimmed);
|
||||
beginAssistant();
|
||||
|
||||
try {
|
||||
await chatStream(sessionId, trimmed);
|
||||
} catch (err: unknown) {
|
||||
// Backend loop not wired or gateway unreachable: show the failure inline
|
||||
// rather than leaving a permanently-streaming bubble.
|
||||
endStream();
|
||||
const msg = err instanceof Error ? err.message : "触发失败";
|
||||
appendChunk(`[stream 触发失败] ${msg}`);
|
||||
appendTaskLog("main", `[error] ${msg}\n`);
|
||||
addTool({ name: "stream_trigger", summary: "失败", ok: false, detail: msg, at: now() });
|
||||
} finally {
|
||||
setSending(false);
|
||||
}
|
||||
},
|
||||
[sending, sessionId, addUserMessage, beginAssistant, endStream, appendChunk, addTool, appendTaskLog]
|
||||
);
|
||||
|
||||
return { send, sending };
|
||||
}
|
||||
Reference in new issue
Block a user