feat(web): 聊天请求携带行为模式 mode(A3) — useChat 读当前 mode 经 REST 发送
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled

- api.ts chatStream 新增可选 mode,空则不写键(后端回落chat)
- useChat.ts 发送时带上 useModeStore 当前 mode,使非chat模式消息在Web端真正落库
- 修正 docblock(移除虚构的WS chat回退描述)
This commit is contained in:
AskaEth committed 2026-09-08 21:07:59 +08:00
1 parent b686d5fec8
commit 747b9ad414
2 files changed
+19 -10

No files matched your search

+12 -3
View File
@@ -248,15 +248,24 @@ export function chatSync(
* `image` (a base64 data: URI or URL) is attached for the vision path; the
* gateway's chat body currently has no image field, so an unconfigured backend
* simply ignores it. `deviceId` mirrors the client's per-browser id onto the
* persisted message (design/16 §4.5). */
* persisted message (design/16 §4.5). `mode` is the behavior mode this turn is
* sent in (design/01 §3); omitted when empty so the backend falls back to chat. */
export function chatStream(
sessionId: string,
text: string,
image?: string
image?: string,
mode?: Mode
): Promise<{ stream: true }> {
return request<{ stream: true }>("/chat", {
method: "POST",
body: JSON.stringify({ sessionId, text, image, stream: true, deviceId: getClientId() }),
body: JSON.stringify({
sessionId,
text,
image,
stream: true,
deviceId: getClientId(),
...(mode ? { mode } : {}),
}),
});
}
+7 -7
View File
@@ -8,13 +8,13 @@ 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.
* stream render into that bubble. If the REST trigger fails, the failure is
* surfaced inline on the bubble rather than left streaming forever.
*
* The behavior mode is NOT chosen by the user at send time — the agent / backend
* hot-switches it (design/01 §3), and each message carries its own mode, so the
* bubble renders per that message's mode. Until the backend advertises a
* per-message mode, a new assistant bubble defaults to the current UI mode. */
* The behavior mode is chosen by the agent / backend hot-switch (design/01 §3);
* each message carries the mode in effect when the turn is sent, and the bubble
* renders per that message's mode. We read the current UI mode here and pass it
* on the turn so the backend persists it alongside the message (A3). */
export function useSendChat(): {
send: (text: string, image?: string) => Promise<void>;
sending: boolean;
@@ -46,7 +46,7 @@ export function useSendChat(): {
beginAssistant(mode, clientId);
try {
await chatStream(sessionId, prompt, image);
await chatStream(sessionId, prompt, image, mode);
} catch (err: unknown) {
// Backend loop not wired or gateway unreachable: show the failure inline
// rather than leaving a permanently-streaming bubble.