feat(characters): support character-scoped conversations

This commit is contained in:
2026-07-17 11:42:31 +08:00
parent 93efcb6604
commit 2796010971
85 changed files with 1645 additions and 251 deletions
@@ -5,12 +5,14 @@ import {
UnlockPrivateResponse,
type UiMessage,
} from "@/data/dto/chat";
import { DEFAULT_CHARACTER_ID } from "@/data/constants/character";
import { chatMachine } from "@/stores/chat/chat-machine";
import type { ChatEvent } from "@/stores/chat/chat-events";
import type {
UnlockMessageOutput as MachineUnlockMessageOutput,
UnlockMessageRequest,
} from "@/stores/chat/helper/unlock";
import type { ChatHistoryActorInput } from "@/stores/chat/machine/actors/history";
export interface SendMessageHttpOutput {
response: ChatSendResponse;
@@ -29,6 +31,10 @@ export interface TestUnlockMessageOutput {
response: UnlockPrivateResponse;
}
export const TEST_CHAT_MACHINE_INPUT = {
characterId: DEFAULT_CHARACTER_ID,
};
export function makeChatSendResponse(): ChatSendResponse {
return ChatSendResponse.from({
reply: "",
@@ -74,7 +80,7 @@ export function createTestChatMachine(
loadHistory: createLoadHistoryCallback(options.historyMessages ?? []),
sendMessageHttp: fromPromise<
SendMessageHttpOutput,
{ content: string }
{ characterId: string; content: string }
>(async () => {
if (options.sendMessageHttpError) {
throw options.sendMessageHttpError;
@@ -84,21 +90,26 @@ export function createTestChatMachine(
reply: null,
};
}),
httpMessageQueue: fromCallback<ChatEvent>(({ receive, sendBack }) => {
receive((event) => {
if (event.type !== "ChatSendMessage") return;
sendBack({ type: "ChatQueuedSendStarted" });
sendBack({
type: "ChatQueuedHttpDone",
output: {
response: makeChatSendResponse(),
reply: null,
},
httpMessageQueue: fromCallback<ChatEvent, { characterId: string }>(
({ receive, sendBack }) => {
receive((event) => {
if (event.type !== "ChatSendMessage") return;
sendBack({ type: "ChatQueuedSendStarted" });
sendBack({
type: "ChatQueuedHttpDone",
output: {
response: makeChatSendResponse(),
reply: null,
},
});
});
});
return () => undefined;
}),
unlockHistory: fromPromise<UnlockHistoryOutput>(async () => {
return () => undefined;
},
),
unlockHistory: fromPromise<
UnlockHistoryOutput,
{ characterId: string }
>(async () => {
if (options.unlockHistoryError) {
throw options.unlockHistoryError;
}
@@ -112,7 +123,7 @@ export function createTestChatMachine(
}),
unlockMessage: fromPromise<
MachineUnlockMessageOutput,
UnlockMessageRequest
UnlockMessageRequest & { characterId: string }
>(async ({ input }) => {
const output = options.unlockMessageOutput ?? {
messageId: input.messageId ?? input.displayMessageId,
@@ -136,7 +147,7 @@ export function createLoadHistoryCallback(
limit: 50,
},
) {
return fromCallback<ChatEvent>(({ sendBack }) => {
return fromCallback<ChatEvent, ChatHistoryActorInput>(({ sendBack }) => {
sendBack({
type: "ChatLocalHistoryLoaded",
output: {