Rework story engine flow and reorganize project docs
Some checks failed
CI / verify (push) Has been cancelled

This commit is contained in:
2026-04-06 23:19:00 +08:00
parent d678929064
commit ddcb5d5c8c
241 changed files with 19805 additions and 2478 deletions

View File

@@ -30,7 +30,7 @@ vi.mock('./llmClient', () => ({
import type {
Character,
Encounter,
SceneMonster,
SceneHostileNpc,
StoryMoment,
StoryOption,
} from '../types';
@@ -365,7 +365,7 @@ describe('ai orchestration fallbacks', () => {
});
const context = createContext();
const targetStatus = createTargetStatus();
const monsters: SceneMonster[] = [];
const monsters: SceneHostileNpc[] = [];
const storyHistory: StoryMoment[] = [];
beforeEach(() => {
@@ -481,7 +481,7 @@ describe('ai orchestration fallbacks', () => {
await expect(
generateCustomWorldProfile('一个需要很多角色和场景的世界'),
).rejects.toThrow(
/requires at least 30 unique NPCs|requires at least 10 generated scenes|did not return enough non-playable NPCs|至少产出 30 名唯一角色|至少产出 10 个场景|至少需要 25 名场景角色/i,
/requires at least 10 generated scenes|至少产出 10 个场景|至少需要 10 个场景/i,
);
});
@@ -674,6 +674,52 @@ describe('ai orchestration fallbacks', () => {
);
});
it('attaches creator intent and anchor pack when generating from creator cards', async () => {
requestPlainTextCompletionMock.mockResolvedValue(
JSON.stringify(
createCustomWorldResponse({
name: '锚点世界',
}),
),
);
const profile = await generateCustomWorldProfile({
settingText: '世界一句话:一个被灵潮反复改写地形的边境世界。',
creatorIntent: {
sourceMode: 'card',
rawSettingText: '',
worldHook: '一个被灵潮反复改写地形的边境世界。',
themeKeywords: ['边境', '灵潮'],
toneDirectives: ['紧张', '潮湿'],
playerPremise: '玩家是前巡夜人。',
openingSituation: '刚进城就卷入旧案。',
coreConflicts: ['旧案名单再次出现'],
keyFactions: [],
keyCharacters: [
{
id: 'creator-character-1',
name: '沈砺',
role: '灰炬向导',
publicMask: '看起来只是个带路人',
hiddenHook: '一直在查旧撤离线',
relationToPlayer: '会先怀疑玩家身份',
notes: '',
locked: true,
},
],
keyLandmarks: [],
iconicElements: ['裂潮灯塔'],
forbiddenDirectives: ['不要出现现代枪械'],
},
});
expect(profile.name).toBe('锚点世界');
expect(profile.creatorIntent?.sourceMode).toBe('card');
expect(profile.creatorIntent?.keyCharacters[0]?.name).toBe('沈砺');
expect(profile.anchorPack?.keyCharacterAnchors[0]?.name).toBe('沈砺');
expect(profile.anchorPack?.lockedAnchorIds).toContain('creator-character-1');
});
it('generates a custom world scene image through the local proxy and returns the saved asset path', async () => {
fetchMock.mockResolvedValue({
ok: true,