1
This commit is contained in:
@@ -227,6 +227,200 @@ test('phase4 update_draft_card writes back draft profile and recompiles summarie
|
||||
);
|
||||
});
|
||||
|
||||
test('phase4 sync_result_profile writes result-page snapshot back into session draft chain', async () => {
|
||||
const runtimeRepository = createRuntimeRepositoryStub();
|
||||
const sessionStore = new CustomWorldAgentSessionStore(runtimeRepository);
|
||||
const orchestrator = new CustomWorldAgentOrchestrator(sessionStore, null, {
|
||||
singleTurnLlmClient: createTestCustomWorldAgentSingleTurnLlmClient(),
|
||||
});
|
||||
const userId = 'user-phase4-sync-result-profile';
|
||||
const session = await createObjectRefiningSession(orchestrator, userId);
|
||||
|
||||
const response = await orchestrator.executeAction(userId, session.sessionId, {
|
||||
action: 'sync_result_profile',
|
||||
profile: {
|
||||
id: `agent-draft-${session.sessionId}`,
|
||||
settingText: '被海雾吞没的旧航路群岛',
|
||||
name: '潮雾列岛·结果页精修版',
|
||||
subtitle: '旧灯塔与失控航路',
|
||||
summary: '结果页已经把世界概述继续往沉船夜暗线收紧。',
|
||||
tone: '压抑、潮湿、悬疑',
|
||||
playerGoal: '查清沉船夜与假航灯的真正操盘者。',
|
||||
templateWorldType: 'WUXIA',
|
||||
majorFactions: ['守灯会', '航运公会'],
|
||||
coreConflicts: ['守灯会与航运公会争夺旧航路控制权'],
|
||||
attributeSchema: {
|
||||
id: 'schema:test',
|
||||
worldId: 'CUSTOM',
|
||||
schemaVersion: 1,
|
||||
schemaName: '测试',
|
||||
generatedFrom: {
|
||||
worldType: 'CUSTOM',
|
||||
worldName: '潮雾列岛·结果页精修版',
|
||||
settingSummary: '测试',
|
||||
tone: '测试',
|
||||
conflictCore: '测试',
|
||||
},
|
||||
slots: [],
|
||||
},
|
||||
playableNpcs: [],
|
||||
storyNpcs: [],
|
||||
items: [],
|
||||
landmarks: [],
|
||||
generationMode: 'full',
|
||||
generationStatus: 'complete',
|
||||
},
|
||||
});
|
||||
const operation = await waitForOperation(
|
||||
orchestrator,
|
||||
userId,
|
||||
session.sessionId,
|
||||
response.operation.operationId,
|
||||
);
|
||||
const snapshot = await orchestrator.getSessionSnapshot(userId, session.sessionId);
|
||||
const profile = normalizeFoundationDraftProfile(snapshot?.draftProfile);
|
||||
const draftRecord = snapshot?.draftProfile as Record<string, unknown> | null;
|
||||
const legacyResultProfile = draftRecord?.legacyResultProfile as
|
||||
| Record<string, unknown>
|
||||
| undefined;
|
||||
|
||||
assert.equal(operation?.status, 'completed');
|
||||
assert.equal(profile?.name, '潮雾列岛·结果页精修版');
|
||||
assert.equal(
|
||||
profile?.summary,
|
||||
'结果页已经把世界概述继续往沉船夜暗线收紧。',
|
||||
);
|
||||
assert.equal(legacyResultProfile?.name, '潮雾列岛·结果页精修版');
|
||||
assert.equal(
|
||||
legacyResultProfile?.playerGoal,
|
||||
'查清沉船夜与假航灯的真正操盘者。',
|
||||
);
|
||||
assert.ok(
|
||||
snapshot?.messages.some(
|
||||
(message) =>
|
||||
message.kind === 'action_result' &&
|
||||
message.text.includes('结果页里的最新世界结构已经同步回当前草稿'),
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
test('phase4 sync_result_profile keeps existing foundation structure while updating summary snapshot', async () => {
|
||||
const runtimeRepository = createRuntimeRepositoryStub();
|
||||
const sessionStore = new CustomWorldAgentSessionStore(runtimeRepository);
|
||||
const orchestrator = new CustomWorldAgentOrchestrator(sessionStore, null, {
|
||||
singleTurnLlmClient: createTestCustomWorldAgentSingleTurnLlmClient(),
|
||||
});
|
||||
const userId = 'user-phase4-sync-result-profile-structure';
|
||||
const session = await createObjectRefiningSession(orchestrator, userId);
|
||||
const baselineProfile = normalizeFoundationDraftProfile(session.draftProfile);
|
||||
const baselinePlayableName = baselineProfile?.playableNpcs[0]?.name;
|
||||
const baselineStoryName = baselineProfile?.storyNpcs[0]?.name;
|
||||
const baselineLandmarkName = baselineProfile?.landmarks[0]?.name;
|
||||
|
||||
assert.ok(baselinePlayableName);
|
||||
assert.ok(baselineStoryName);
|
||||
assert.ok(baselineLandmarkName);
|
||||
|
||||
const response = await orchestrator.executeAction(userId, session.sessionId, {
|
||||
action: 'sync_result_profile',
|
||||
profile: {
|
||||
id: `agent-draft-${session.sessionId}`,
|
||||
settingText: '被海雾吞没的旧航路群岛',
|
||||
name: '潮雾列岛·结果页精修版',
|
||||
subtitle: '旧灯塔与失控航路',
|
||||
summary: '结果页已经把世界概述继续往沉船夜暗线收紧。',
|
||||
tone: '压抑、潮湿、悬疑',
|
||||
playerGoal: '查清沉船夜与假航灯的真正操盘者。',
|
||||
templateWorldType: 'WUXIA',
|
||||
majorFactions: ['守灯会', '航运公会'],
|
||||
coreConflicts: ['守灯会与航运公会争夺旧航路控制权'],
|
||||
attributeSchema: {
|
||||
id: 'schema:test',
|
||||
worldId: 'CUSTOM',
|
||||
schemaVersion: 1,
|
||||
schemaName: '测试',
|
||||
generatedFrom: {
|
||||
worldType: 'CUSTOM',
|
||||
worldName: '潮雾列岛·结果页精修版',
|
||||
settingSummary: '测试',
|
||||
tone: '测试',
|
||||
conflictCore: '测试',
|
||||
},
|
||||
slots: [],
|
||||
},
|
||||
playableNpcs: [
|
||||
{
|
||||
id: 'playable-runtime-only',
|
||||
name: '结果页临时角色',
|
||||
title: '运行时角色',
|
||||
role: '测试角色',
|
||||
description: '不应该直接覆盖 foundation draft。',
|
||||
backstory: '仅用于验证 sync 边界。',
|
||||
personality: '谨慎',
|
||||
motivation: '验证同步边界',
|
||||
combatStyle: '观察',
|
||||
initialAffinity: 0,
|
||||
relationshipHooks: [],
|
||||
tags: [],
|
||||
},
|
||||
],
|
||||
storyNpcs: [
|
||||
{
|
||||
id: 'story-runtime-only',
|
||||
name: '结果页临时场景角色',
|
||||
title: '运行时场景角色',
|
||||
role: '测试角色',
|
||||
description: '不应该直接覆盖 foundation draft。',
|
||||
backstory: '仅用于验证 sync 边界。',
|
||||
personality: '克制',
|
||||
motivation: '验证同步边界',
|
||||
combatStyle: '观察',
|
||||
initialAffinity: 0,
|
||||
relationshipHooks: [],
|
||||
tags: [],
|
||||
},
|
||||
],
|
||||
items: [],
|
||||
landmarks: [
|
||||
{
|
||||
id: 'landmark-runtime-only',
|
||||
name: '结果页临时地点',
|
||||
description: '不应该直接覆盖 foundation draft。',
|
||||
dangerLevel: '低',
|
||||
sceneNpcIds: [],
|
||||
connections: [],
|
||||
},
|
||||
],
|
||||
generationMode: 'full',
|
||||
generationStatus: 'complete',
|
||||
},
|
||||
});
|
||||
const operation = await waitForOperation(
|
||||
orchestrator,
|
||||
userId,
|
||||
session.sessionId,
|
||||
response.operation.operationId,
|
||||
);
|
||||
const snapshot = await orchestrator.getSessionSnapshot(userId, session.sessionId);
|
||||
const profile = normalizeFoundationDraftProfile(snapshot?.draftProfile);
|
||||
const draftRecord = snapshot?.draftProfile as Record<string, unknown> | null;
|
||||
const legacyResultProfile = draftRecord?.legacyResultProfile as
|
||||
| Record<string, unknown>
|
||||
| undefined;
|
||||
|
||||
assert.equal(operation?.status, 'completed');
|
||||
assert.equal(profile?.name, '潮雾列岛·结果页精修版');
|
||||
assert.equal(profile?.playableNpcs[0]?.name, baselinePlayableName);
|
||||
assert.equal(profile?.storyNpcs[0]?.name, baselineStoryName);
|
||||
assert.equal(profile?.landmarks[0]?.name, baselineLandmarkName);
|
||||
assert.equal(legacyResultProfile?.name, '潮雾列岛·结果页精修版');
|
||||
assert.equal(
|
||||
(legacyResultProfile?.playableNpcs as Array<{ name?: string }> | undefined)?.[0]
|
||||
?.name,
|
||||
'结果页临时角色',
|
||||
);
|
||||
});
|
||||
|
||||
test('phase4 generate_characters appends story npcs and updates work summary counts', async () => {
|
||||
const runtimeRepository = createRuntimeRepositoryStub();
|
||||
const sessionStore = new CustomWorldAgentSessionStore(runtimeRepository);
|
||||
@@ -323,3 +517,33 @@ test('phase4 generate_landmarks appends new landmark cards and checkpoints', asy
|
||||
);
|
||||
assert.ok((latestSessionRecord?.checkpoints.length ?? 0) >= 2);
|
||||
});
|
||||
|
||||
test('phase4 work summaries exclude library draft entries after phase3 downgrade', async () => {
|
||||
const runtimeRepository = createRuntimeRepositoryStub();
|
||||
const sessionStore = new CustomWorldAgentSessionStore(runtimeRepository);
|
||||
const orchestrator = new CustomWorldAgentOrchestrator(sessionStore, null, {
|
||||
singleTurnLlmClient: createTestCustomWorldAgentSingleTurnLlmClient(),
|
||||
});
|
||||
const userId = 'user-phase4-work-summary-phase3';
|
||||
const session = await createObjectRefiningSession(orchestrator, userId);
|
||||
|
||||
await runtimeRepository.upsertCustomWorldProfile(userId, 'library-draft-1', {
|
||||
id: 'library-draft-1',
|
||||
name: '旧兼容草稿',
|
||||
subtitle: '仍保留在作品库',
|
||||
summary: '不应该继续出现在创作中心 works 聚合里。',
|
||||
playableNpcs: [],
|
||||
landmarks: [],
|
||||
});
|
||||
|
||||
const workItems = await listCustomWorldWorkSummaries(userId, {
|
||||
runtimeRepository,
|
||||
customWorldAgentSessions: sessionStore,
|
||||
});
|
||||
|
||||
assert.ok(workItems.some((item) => item.sessionId === session.sessionId));
|
||||
assert.equal(
|
||||
workItems.some((item) => item.profileId === 'library-draft-1'),
|
||||
false,
|
||||
);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user