/** * Chat 状态机:State 形状 + 初始值 * * 注:GuestChatQuota 仍位于 chat-machine.ts(属于业务常量,与上下文配对紧密)。 * * 历史: * - `isGuest: boolean` 字段已删(由 chat-screen 派生自 `auth.loginStatus === "guest"`) * - `guestRemainingQuota` / `guestTotalQuota` default 改 0: * - 游客:chat-screen 派 `ChatInit` → readInitData 调 ChatStorage → onDone 条件赋 * - 非游客:永不被赋值(业务事实"非游客无消息限制")—— 0 - 1 = max(0, -1) = 0 天然 no-op * - 0 同时表示"未初始化"和"已耗尽" —— UI 用 `if (isGuest && ...)` 天然过滤 * * 新增 `wsConnected: boolean`(仅 userSession 期间 true): * - WS 已连 → 消息发送走 WS,不消耗次数 * - WS 未连 → 消息发送走 HTTP,消耗次数 * - `ChatWebSocketConnected` 事件 → true * - `userSession.exit` → false(WS actor cleanup 时也会跑 exit) */ import type { UiMessage } from "@/models/chat/ui-message"; export interface ChatState { messages: UiMessage[]; isReplyingAI: boolean; /** * WebSocket 连接状态(仅 userSession 期间 true) * - 决定消息发送路径(WS / HTTP)和是否消耗次数 * - true:走 WS,不消耗次数 * - false:走 HTTP,消耗次数 */ wsConnected: boolean; /** 游客剩余配额(次/天)—— 仅游客业务展示用 */ guestRemainingQuota: number; /** 游客总配额(仅游客展示用) */ guestTotalQuota: number; quotaExceededTrigger: number; isLoadingMore: boolean; hasMore: boolean; historyOffset: number; /** 游客配额加载完成标志(仅 guestSession 期间) —— default false * - guestSession.initializing 走 always barrier:`quotaLoaded && historyLoaded` 才进 ready * - userSession 永不为 true(不调 loadQuota)—— OK,不影响 barrier */ quotaLoaded: boolean; /** history 加载完成标志(initial load —— local → network → save 跑完) * - guestSession.initializing / userSession.initializing 走 always barrier * - 不被 `loadMoreHistoryActor` 设置(翻页是另一码事) */ historyLoaded: boolean; } export const initialState: ChatState = { messages: [], isReplyingAI: false, wsConnected: false, guestRemainingQuota: 0, guestTotalQuota: 0, quotaExceededTrigger: 0, isLoadingMore: false, hasMore: true, historyOffset: 0, quotaLoaded: false, historyLoaded: false, };