feat(chat): handle daily message paywall

This commit is contained in:
2026-06-22 10:46:17 +08:00
parent df7f673855
commit 61fd4ca916
10 changed files with 162 additions and 44 deletions
+48 -1
View File
@@ -13,7 +13,7 @@
* 设计目标:
* - helpers 无 XState 依赖(可独立 import / 测试)
* - actors 依赖 helpersimport
* - machine 依赖 actors(import)—— 不直接依赖 helpers
* - machine 依赖 actors,并复用 helpers 里的纯状态转换函数
*
* 历史:
* - `readInitData` + `InitResult` 已删(被 2 个独立 helper 替换)
@@ -27,6 +27,8 @@ import { ChatStorage } from "@/data/storage/chat/chat_storage";
import { ChatSendResponse } from "@/data/dto/chat/chat_send_response";
import { formatDate, Result, Logger } from "@/utils";
import type { ChatState } from "./chat-state";
const log = new Logger("StoresChatChatMachineHelpers");
// ============================================================
@@ -76,6 +78,51 @@ export function sendResponseToUiMessage(response: ChatSendResponse): UiMessage {
};
}
export type HttpSendOutput = {
response: ChatSendResponse;
reply: UiMessage | null;
};
export function applyHttpSendOutput(
context: ChatState,
output: HttpSendOutput,
): Partial<ChatState> {
const { response, reply } = output;
if (response.blocked === true && response.blockReason === "daily_limit") {
const detail = response.blockDetail;
const lastMessage = context.messages[context.messages.length - 1];
const messages =
lastMessage && !lastMessage.isFromAI
? context.messages.slice(0, -1)
: context.messages;
return {
messages,
isReplyingAI: false,
paywallTriggered: true,
paywallReason: "daily_limit",
paywallDetail: detail
? { usedToday: detail.usedToday, limit: detail.limit }
: null,
};
}
if (!reply) {
return {
isReplyingAI: false,
};
}
return {
messages: [...context.messages, reply],
isReplyingAI: false,
paywallTriggered: false,
paywallReason: null,
paywallDetail: null,
};
}
// ============================================================
// Result → number 映射
// ============================================================