Merge branch 'codex/backend-rewrite-spacetimedb' of http://82.157.175.59:3000/GenarrativeAI/Genarrative into codex/backend-rewrite-spacetimedb

# Conflicts:
#	docs/technical/RUST_LOCAL_AND_REMOTE_DEPLOYMENT_SCRIPTS_2026-04-22.md   resolved by origin/codex/backend-rewrite-spacetimedb(远端) version
This commit is contained in:
2026-04-25 17:06:57 +08:00
393 changed files with 2902 additions and 91859 deletions

View File

@@ -339,7 +339,6 @@ function createLandmark(
return {
name: `场景${index + 1}`,
description: `场景描述${index + 1}`,
dangerLevel: 'high',
sceneNpcNames: options?.storyNpcNames ?? [
`世界NPC${index + 1}`,
`世界NPC${index + 2}`,
@@ -931,7 +930,6 @@ describe('ai orchestration fallbacks', () => {
id: 'landmark-1',
name: '雾潮码头',
description: '被潮雾与旧升降机包围的码头。',
dangerLevel: 'high',
},
userPrompt: '雨夜的栈桥横跨黑色海沟,塔楼灯火被潮雾吞没。',
size: '1280*720',
@@ -1002,7 +1000,6 @@ describe('ai orchestration fallbacks', () => {
id: 'landmark-1',
name: '雾潮码头',
description: '被潮雾与旧升降机包围的码头。',
dangerLevel: 'high',
},
}),
).rejects.toThrow('DashScope API key 无效。');

View File

@@ -1987,7 +1987,6 @@ export async function generateCustomWorldSceneImage({
id: landmark.id,
name: landmark.name,
description: landmark.description,
dangerLevel: landmark.dangerLevel,
},
...(referenceImageSrc?.trim()
? { referenceImageSrc: referenceImageSrc.trim() }

View File

@@ -69,7 +69,6 @@ export interface CustomWorldSceneImageRequest {
id: string;
name: string;
description: string;
dangerLevel: string;
};
userPrompt?: string;
prompt?: string;

View File

@@ -86,7 +86,6 @@ describe('normalizeCustomWorldProfile', () => {
{
name: '北侧塌桥',
description: '横跨裂谷的旧桥只剩半截石拱。',
dangerLevel: 'high',
},
],
};
@@ -191,7 +190,6 @@ describe('normalizeCustomWorldProfile', () => {
{
name: '北侧塌桥',
description: '断桥上方还残留着旧索道。',
dangerLevel: 'high',
sceneNpcNames: ['梁砺'],
connections: [
{
@@ -204,7 +202,6 @@ describe('normalizeCustomWorldProfile', () => {
{
name: '雾潮码头',
description: '潮雾会把来路和去路都遮住一半。',
dangerLevel: 'medium',
sceneNpcNames: ['苏雾', '顾岚'],
connections: [],
},

View File

@@ -115,7 +115,6 @@ export interface CustomWorldGenerationLandmarkOutline {
name: string;
description: string;
visualDescription?: string;
dangerLevel: string;
sceneNpcNames: string[];
connections: CustomWorldGenerationLandmarkConnectionOutline[];
}
@@ -125,7 +124,6 @@ export interface CustomWorldGenerationCampOutline {
name: string;
description: string;
visualDescription?: string;
dangerLevel: string;
imageSrc?: string;
sceneNpcIds?: string[];
sceneNpcNames?: string[];
@@ -714,7 +712,6 @@ export function normalizeCustomWorldGenerationFramework(
camp: {
name: fallback.camp?.name ?? '归舍',
description: fallback.camp?.description ?? '',
dangerLevel: fallback.camp?.dangerLevel ?? 'low',
},
playableNpcs: [],
storyNpcs: [],
@@ -786,7 +783,6 @@ export function buildCustomWorldRawProfileFromFramework(
camp: {
name: framework.camp.name,
description: framework.camp.description,
dangerLevel: framework.camp.dangerLevel,
},
playableNpcs: framework.playableNpcs.map((npc) => ({
name: npc.name,
@@ -816,7 +812,6 @@ export function buildCustomWorldRawProfileFromFramework(
name: landmark.name,
description: landmark.description,
visualDescription: landmark.visualDescription,
dangerLevel: landmark.dangerLevel,
sceneNpcNames: [...landmark.sceneNpcNames],
connections: landmark.connections.map((connection) => ({
targetLandmarkName: connection.targetLandmarkName,
@@ -1071,7 +1066,6 @@ function normalizeCampOutline(
name: toText(item.name) || fallback.name,
description: toText(item.description) || fallback.description,
visualDescription: toText(item.visualDescription) || undefined,
dangerLevel: toText(item.dangerLevel) || fallback.dangerLevel,
imageSrc: toText(item.imageSrc) || undefined,
sceneNpcIds: toStringArray(item.sceneNpcIds),
sceneNpcNames: [
@@ -1107,7 +1101,6 @@ function normalizeLandmarkOutlineList(value: unknown) {
toText(item.description) ||
truncateText(`${name}暗藏新的局势变化。`, 40),
visualDescription: toText(item.visualDescription) || undefined,
dangerLevel: toText(item.dangerLevel) || 'medium',
sceneNpcNames: [
...toStringArray(item.sceneNpcNames),
...toStringArray(item.npcs, 'name'),
@@ -1168,7 +1161,6 @@ function normalizeLandmarkDraftList(value: unknown) {
name,
description: toText(item.description),
visualDescription: toText(item.visualDescription) || undefined,
dangerLevel: toText(item.dangerLevel),
imageSrc: toText(item.imageSrc) || undefined,
sceneNpcIds: toStringArray(item.sceneNpcIds),
sceneNpcNames: [
@@ -1215,7 +1207,6 @@ function normalizeCampScene(
name: toText(item.name) || fallback.name,
description: toText(item.description) || fallback.description,
visualDescription: toText(item.visualDescription) || undefined,
dangerLevel: toText(item.dangerLevel) || fallback.dangerLevel,
imageSrc: toText(item.imageSrc) || undefined,
sceneNpcIds: toStringArray(item.sceneNpcIds),
connections: toRecordArray(item.connections)
@@ -1439,7 +1430,7 @@ export function buildCustomWorldReferenceText(
.slice(0, 10)
.map(
(landmark) =>
`- ${landmark.name}${landmark.description}危险度:${landmark.dangerLevel}场景角色:${
`- ${landmark.name}${landmark.description};场景角色:${
landmark.sceneNpcIds
.map((npcId) => storyNpcById.get(npcId)?.name)
.filter(Boolean)

View File

@@ -75,7 +75,6 @@ describe('buildExpandedCustomWorldProfile', () => {
id: 'landmark-1',
name: '断桥旧哨',
description: '旧哨火和断桥一起守着边城北口。',
dangerLevel: 'high',
sceneNpcIds: ['story-1'],
connections: [],
},

View File

@@ -158,11 +158,6 @@ export function buildExpandedCustomWorldProfile(
...landmark,
id: landmark.id || createEntryId('landmark', landmark.name, index),
description: clampText(landmark.description, 96),
dangerLevel:
landmark.dangerLevel ||
(resolveCustomWorldCompatibilityTemplateWorldType(profile) === WorldType.XIANXIA
? 'high'
: 'medium'),
}));
const landmarkIdByReference = new Map<string, string>();
landmarkDrafts.forEach((landmark) => {

View File

@@ -14,7 +14,6 @@ type CampProfileSeed = Pick<
| 'name'
| 'description'
| 'visualDescription'
| 'dangerLevel'
| 'imageSrc'
| 'sceneNpcIds'
| 'connections'
@@ -92,7 +91,6 @@ export function buildFallbackCustomWorldCampScene(
id: 'custom-scene-camp',
name: fallbackName,
description: buildFallbackCampDescription(profile, fallbackName),
dangerLevel: 'low',
sceneNpcIds: [],
connections: [],
narrativeResidues: null,
@@ -110,7 +108,6 @@ export function resolveCustomWorldCampScene(
name: camp?.name?.trim() || fallback.name,
description: camp?.description?.trim() || fallback.description,
visualDescription: camp?.visualDescription?.trim() || undefined,
dangerLevel: camp?.dangerLevel?.trim() || fallback.dangerLevel,
imageSrc: camp?.imageSrc?.trim() || undefined,
sceneNpcIds: Array.isArray(camp?.sceneNpcIds)
? [...new Set(camp.sceneNpcIds.map((entry) => entry.trim()).filter(Boolean))]

View File

@@ -59,7 +59,6 @@ function createBaseProfile(): CustomWorldProfile {
id: 'camp-1',
name: '守夜营地',
description: '潮线后的临时据点。',
dangerLevel: 'medium',
imageSrc: '/images/camp/camp.webp',
sceneNpcIds: [],
connections: [],
@@ -69,7 +68,6 @@ function createBaseProfile(): CustomWorldProfile {
id: 'landmark-1',
name: '潮汐码头',
description: '涨潮时会吞掉半截栈桥。',
dangerLevel: 'high',
imageSrc: '/images/landmark/docks.webp',
sceneNpcIds: [],
connections: [],

View File

@@ -353,7 +353,7 @@ function inferRoleArchetypeLabel(
}
function inferSceneBucketLabel(
landmark: Pick<CustomWorldProfile['landmarks'][number], 'name' | 'description' | 'dangerLevel'>,
landmark: Pick<CustomWorldProfile['landmarks'][number], 'name' | 'description'>,
) {
const source = `${landmark.name} ${landmark.description}`;
@@ -365,9 +365,7 @@ function inferSceneBucketLabel(
if (/[||||]/u.test(source)) return '';
if (/[||||]/u.test(source)) return '';
return landmark.dangerLevel === 'high' || landmark.dangerLevel === 'extreme'
? '高压交汇区'
: '叙事缓冲区';
return '叙事缓冲区';
}
function buildRoleArchetypes(profile: CustomWorldProfile) {
@@ -388,7 +386,7 @@ function buildSceneBuckets(profile: CustomWorldProfile) {
id: `scene-bucket-${index + 1}`,
label: inferSceneBucketLabel(landmark),
moodTags: dedupeStrings(
[landmark.dangerLevel, ...splitToneTags(profile.tone)],
splitToneTags(profile.tone),
4,
),
keywords: dedupeStrings([landmark.name, landmark.description], 4),

View File

@@ -112,7 +112,6 @@ describe('buildUserPrompt', () => {
id: 'landmark-1',
name: '断桥旧哨',
description: '旧哨火和断桥一起守着边城北口。',
dangerLevel: 'high',
sceneNpcIds: ['story-1'],
connections: [],
},