1f3980d461
Split `chatInitActor` into `loadQuotaActor` (guest quota fetch) and `loadHistoryActor` (local → network → save sync), and add `quotaLoaded` / `historyLoaded` state flags so the UI can display loading status during the new local-first history hydration flow. Also drop the now-unused `ChatInit` event and pipe Next.js stdout/stderr to a persistent log file in the post-receive hook for easier troubleshooting.
67 lines
2.7 KiB
TypeScript
67 lines
2.7 KiB
TypeScript
/**
|
||
* 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;
|
||
/** 游客剩余配额(次/天)—— **仅**游客业务展示用
|
||
* - default 0 = "未初始化" / "已耗尽"(同码,靠 `isGuest` 区分)
|
||
* - 非游客:永不被赋值(业务事实"无消息限制")
|
||
*/
|
||
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,
|
||
};
|