feat(chat): sync multi-role backend APIs

This commit is contained in:
2026-07-20 11:29:54 +08:00
parent 16b5c16e76
commit b6fdc912ae
84 changed files with 1488 additions and 439 deletions
+39 -3
View File
@@ -34,6 +34,11 @@ export interface CharacterCatalog {
getBySlug(characterSlug: string | null | undefined): CharacterProfile | null;
}
export interface CharacterCatalogSnapshot {
readonly catalog: CharacterCatalog;
readonly defaultCharacter: CharacterProfile;
}
function defineCharacter(profile: CharacterProfile): CharacterProfile {
return Object.freeze({
...profile,
@@ -45,7 +50,7 @@ function defineCharacter(profile: CharacterProfile): CharacterProfile {
const CHARACTER_PROFILES: readonly CharacterProfile[] = Object.freeze([
defineCharacter({
id: "character_elio",
id: "elio",
slug: "elio",
displayName: "Elio Silvestri",
shortName: "Elio",
@@ -75,7 +80,7 @@ const CHARACTER_PROFILES: readonly CharacterProfile[] = Object.freeze([
},
}),
defineCharacter({
id: "character_maya",
id: "maya-tan",
slug: "maya",
displayName: "Maya Tan",
shortName: "Maya",
@@ -104,7 +109,7 @@ const CHARACTER_PROFILES: readonly CharacterProfile[] = Object.freeze([
},
}),
defineCharacter({
id: "character_nayeli",
id: "nayeli-cervantes",
slug: "nayeli",
displayName: "Nayeli Cervantes",
shortName: "Nayeli",
@@ -166,6 +171,37 @@ export function createCharacterCatalog(
});
}
export function mergeRemoteCharacterCatalog(
remote: import("@/data/schemas/character").CharacterListResponse,
localProfiles: readonly CharacterProfile[] = CHARACTERS,
): CharacterCatalogSnapshot {
const localById = new Map(localProfiles.map((profile) => [profile.id, profile]));
const profiles = remote.items.flatMap((item) => {
const local = localById.get(item.id);
if (!local || !item.isActive || !item.capabilities.chat) return [];
return [
defineCharacter({
...local,
displayName: item.displayName,
sortOrder: item.sortOrder,
capabilities: {
chat: item.capabilities.chat,
privateRoom:
local.capabilities.privateRoom && item.capabilities.privateContent,
tip: local.capabilities.tip,
},
}),
];
});
const catalog = createCharacterCatalog(profiles);
const defaultCharacter =
catalog.getById(remote.defaultCharacterId) ??
catalog.getById(DEFAULT_CHARACTER_ID) ??
catalog.characters[0] ??
DEFAULT_CHARACTER;
return Object.freeze({ catalog, defaultCharacter });
}
export const LOCAL_CHARACTER_CATALOG = createCharacterCatalog(
CHARACTER_PROFILES,
);