refactor(chat): remove guest history synchronization
This commit is contained in:
@@ -1,15 +0,0 @@
|
||||
{
|
||||
"characterId": "elio",
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Hi Elio.",
|
||||
"timestamp": "2026-06-23T02:10:00.000Z"
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "Hi, I am right here with you.",
|
||||
"timestamp": "2026-06-23T02:10:04.000Z"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -6,8 +6,6 @@ import type {
|
||||
import {
|
||||
ChatHistoryResponse,
|
||||
ChatPreviewsResponse,
|
||||
ChatSyncRequest,
|
||||
ChatSyncRequestSchema,
|
||||
ChatSendResponse,
|
||||
SendMessageRequestSchema,
|
||||
UnlockHistoryRequestSchema,
|
||||
@@ -58,15 +56,6 @@ export class ChatRemoteDataSource {
|
||||
return Result.wrap(() => this.api.getPreviews(options));
|
||||
}
|
||||
|
||||
async syncGuestHistory(
|
||||
request: ChatSyncRequest,
|
||||
options?: ChatRequestOptions,
|
||||
): Promise<Result<void>> {
|
||||
return Result.wrap(() =>
|
||||
this.api.syncGuestHistory(ChatSyncRequestSchema.parse(request), options),
|
||||
);
|
||||
}
|
||||
|
||||
async getHistory(
|
||||
characterId: string,
|
||||
limit = 50,
|
||||
|
||||
@@ -10,7 +10,6 @@ import type {
|
||||
import type {
|
||||
ChatHistoryResponse,
|
||||
ChatPreviewsResponse,
|
||||
ChatSyncRequest,
|
||||
ChatMessage,
|
||||
ChatSendResponse,
|
||||
UnlockHistoryResponse,
|
||||
@@ -63,13 +62,6 @@ export class ChatRepository implements IChatRepository {
|
||||
return this.remote.getPreviews(options);
|
||||
}
|
||||
|
||||
async syncGuestHistory(
|
||||
request: ChatSyncRequest,
|
||||
options?: ChatRequestOptions,
|
||||
): Promise<Result<void>> {
|
||||
return this.remote.syncGuestHistory(request, options);
|
||||
}
|
||||
|
||||
/** 解锁单条历史付费 / 私密消息。 */
|
||||
async unlockPrivateMessage(
|
||||
input: UnlockPrivateMessageInput,
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
import type {
|
||||
ChatHistoryResponse,
|
||||
ChatPreviewsResponse,
|
||||
ChatSyncRequest,
|
||||
ChatImageData,
|
||||
ChatLockDetailData,
|
||||
ChatLockType,
|
||||
@@ -79,12 +78,6 @@ export interface IChatRepository {
|
||||
options?: ChatRequestOptions,
|
||||
): Promise<Result<ChatPreviewsResponse>>;
|
||||
|
||||
/** 把一个角色的游客历史同步到正式账号。 */
|
||||
syncGuestHistory(
|
||||
request: ChatSyncRequest,
|
||||
options?: ChatRequestOptions,
|
||||
): Promise<Result<void>>;
|
||||
|
||||
/** 解锁单条历史付费 / 私密消息。 */
|
||||
unlockPrivateMessage(
|
||||
input: UnlockPrivateMessageInput,
|
||||
|
||||
@@ -2,7 +2,6 @@ import { describe, expect, it } from "vitest";
|
||||
|
||||
import {
|
||||
ChatPreviewsResponseSchema,
|
||||
ChatSyncRequestSchema,
|
||||
SendMessageRequestSchema,
|
||||
} from "@/data/schemas/chat";
|
||||
|
||||
@@ -26,23 +25,12 @@ describe("multi-role chat schemas", () => {
|
||||
).toThrow();
|
||||
});
|
||||
|
||||
it("parses nullable previews and immutable sync messages", () => {
|
||||
it("parses nullable immutable previews", () => {
|
||||
const previews = ChatPreviewsResponseSchema.parse({
|
||||
items: [{ characterId: "elio", message: null }],
|
||||
});
|
||||
const sync = ChatSyncRequestSchema.parse({
|
||||
characterId: "elio",
|
||||
messages: [
|
||||
{
|
||||
role: "assistant",
|
||||
content: "Welcome back",
|
||||
timestamp: "2026-07-20T00:00:00.000Z",
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
expect(previews.items[0]?.message).toBeNull();
|
||||
expect(Object.isFrozen(previews.items)).toBe(true);
|
||||
expect(Object.isFrozen(sync.messages)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -7,7 +7,6 @@ export * from "./chat_media";
|
||||
export * from "./chat_message";
|
||||
export * from "./chat_payloads";
|
||||
export * from "./request/send_message_request";
|
||||
export * from "./request/chat_sync_request";
|
||||
export * from "./request/unlock_history_request";
|
||||
export * from "./request/unlock_private_request";
|
||||
export * from "./response/chat_history_response";
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
import { z } from "zod";
|
||||
|
||||
export const ChatSyncMessageSchema = z
|
||||
.object({
|
||||
role: z.enum(["user", "assistant"]),
|
||||
content: z.string(),
|
||||
timestamp: z.string().min(1),
|
||||
})
|
||||
.readonly();
|
||||
|
||||
export const ChatSyncRequestSchema = z
|
||||
.object({
|
||||
characterId: z.string().min(1),
|
||||
messages: z.array(ChatSyncMessageSchema).min(1).readonly(),
|
||||
})
|
||||
.readonly();
|
||||
|
||||
export type ChatSyncRequestInput = z.input<typeof ChatSyncRequestSchema>;
|
||||
export type ChatSyncRequest = z.output<typeof ChatSyncRequestSchema>;
|
||||
@@ -3,6 +3,5 @@
|
||||
*/
|
||||
|
||||
export * from "./send_message_request";
|
||||
export * from "./chat_sync_request";
|
||||
export * from "./unlock_private_request";
|
||||
export * from "./unlock_history_request";
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
import {
|
||||
ChatSyncRequestSchema,
|
||||
SendMessageRequestSchema,
|
||||
UnlockHistoryRequestSchema,
|
||||
UnlockPrivateRequestSchema,
|
||||
@@ -74,30 +73,16 @@ describe("multi-character API contract", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("loads previews and syncs guest history", async () => {
|
||||
it("loads chat previews", async () => {
|
||||
const api = new ChatApi();
|
||||
httpClientMock
|
||||
.mockResolvedValueOnce({ success: true, data: { items: [] } })
|
||||
.mockResolvedValueOnce({ success: true, data: {} });
|
||||
httpClientMock.mockResolvedValueOnce({
|
||||
success: true,
|
||||
data: { items: [] },
|
||||
});
|
||||
|
||||
await api.getPreviews();
|
||||
const request = ChatSyncRequestSchema.parse({
|
||||
characterId: CHARACTER_ID,
|
||||
messages: [
|
||||
{
|
||||
role: "user",
|
||||
content: "Hello",
|
||||
timestamp: "2026-07-20T00:00:00.000Z",
|
||||
},
|
||||
],
|
||||
});
|
||||
await api.syncGuestHistory(request);
|
||||
|
||||
expect(httpClientMock).toHaveBeenNthCalledWith(1, "/api/chat/previews", {});
|
||||
expect(httpClientMock).toHaveBeenNthCalledWith(2, "/api/chat/sync", {
|
||||
method: "POST",
|
||||
body: request,
|
||||
});
|
||||
expect(httpClientMock).toHaveBeenCalledWith("/api/chat/previews", {});
|
||||
});
|
||||
|
||||
it("forwards request cancellation to the HTTP client", async () => {
|
||||
|
||||
@@ -26,6 +26,5 @@
|
||||
"reportUserInfo": { "method": "post", "path": "/api/data/report-user-info" },
|
||||
"feedback": { "method": "post", "path": "/api/feedback" },
|
||||
"characters": { "method": "get", "path": "/api/characters" },
|
||||
"chatPreviews": { "method": "get", "path": "/api/chat/previews" },
|
||||
"chatSync": { "method": "post", "path": "/api/chat/sync" }
|
||||
"chatPreviews": { "method": "get", "path": "/api/chat/previews" }
|
||||
}
|
||||
|
||||
@@ -104,6 +104,4 @@ export class ApiPath {
|
||||
|
||||
static readonly chatPreviews = apiContract.chatPreviews.path;
|
||||
|
||||
static readonly chatSync = apiContract.chatSync.path;
|
||||
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@ import {
|
||||
ChatPreviewsResponseSchema,
|
||||
ChatSendResponse,
|
||||
ChatSendResponseSchema,
|
||||
ChatSyncRequest,
|
||||
SendMessageRequest,
|
||||
UnlockHistoryRequest,
|
||||
UnlockHistoryResponse,
|
||||
@@ -67,17 +66,6 @@ export class ChatApi {
|
||||
return ChatPreviewsResponseSchema.parse(unwrap(env));
|
||||
}
|
||||
|
||||
async syncGuestHistory(
|
||||
body: ChatSyncRequest,
|
||||
options?: { signal?: AbortSignal },
|
||||
): Promise<void> {
|
||||
await httpClient<ApiEnvelope<unknown>>(ApiPath.chatSync, {
|
||||
method: "POST",
|
||||
body,
|
||||
...(options?.signal ? { signal: options.signal } : {}),
|
||||
}).then(unwrap);
|
||||
}
|
||||
|
||||
/**
|
||||
* 解锁单条历史付费 / 私密消息
|
||||
*/
|
||||
|
||||
@@ -259,22 +259,6 @@ export class NavigationStorage {
|
||||
await SessionAsyncUtil.remove(StorageKeys.pendingChatImageReturn);
|
||||
}
|
||||
|
||||
static async saveGuestChatOwnerKey(ownerKey: string): Promise<void> {
|
||||
await SessionAsyncUtil.setJson(
|
||||
StorageKeys.guestChatOwnerKey,
|
||||
ownerKey,
|
||||
z.string().min(1),
|
||||
);
|
||||
}
|
||||
|
||||
static async getGuestChatOwnerKey(): Promise<string | null> {
|
||||
const result = await SessionAsyncUtil.getJson(
|
||||
StorageKeys.guestChatOwnerKey,
|
||||
z.string().min(1),
|
||||
);
|
||||
return Result.isOk(result) ? result.data : null;
|
||||
}
|
||||
|
||||
private static parsePendingChatUnlock(
|
||||
value: PendingChatUnlock | null,
|
||||
): PendingChatUnlock | null {
|
||||
|
||||
@@ -28,7 +28,6 @@ export const StorageKeys = {
|
||||
pendingChatImageReturn: "pending_chat_image_return",
|
||||
pendingChatUnlock: "pending_chat_unlock",
|
||||
pendingChatPromotion: "pending_chat_promotion",
|
||||
guestChatOwnerKey: "guest_chat_owner_key",
|
||||
|
||||
// pwa / app info
|
||||
pwaDialogShown: "pwa_dialog_shown",
|
||||
|
||||
Reference in New Issue
Block a user