1
This commit is contained in:
@@ -5,8 +5,8 @@ import userEvent from '@testing-library/user-event';
|
||||
import { useState } from 'react';
|
||||
import { beforeEach, expect, test, vi } from 'vitest';
|
||||
|
||||
import type { CustomWorldAgentSessionSnapshot } from '../../../packages/shared/src/contracts/customWorldAgent';
|
||||
import type { BigFishWorkSummary } from '../../../packages/shared/src/contracts/bigFishWorkSummary';
|
||||
import type { CustomWorldAgentSessionSnapshot } from '../../../packages/shared/src/contracts/customWorldAgent';
|
||||
import type { PuzzleWorkSummary } from '../../../packages/shared/src/contracts/puzzleWorkSummary';
|
||||
import type { HydratedSavedGameSnapshot } from '../../persistence/runtimeSnapshotTypes';
|
||||
import { ApiClientError } from '../../services/apiClient';
|
||||
@@ -2526,6 +2526,10 @@ test('agent draft result test button enters current draft without publish gate',
|
||||
await waitFor(() => {
|
||||
expect(handleCustomWorldSelect).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ name: '潮雾列岛' }),
|
||||
expect.objectContaining({
|
||||
mode: 'test',
|
||||
returnStage: 'custom-world-result',
|
||||
}),
|
||||
);
|
||||
});
|
||||
expect(
|
||||
|
||||
@@ -4,7 +4,7 @@ import { act, render } from '@testing-library/react';
|
||||
import { describe, expect, it, vi } from 'vitest';
|
||||
|
||||
import type { CustomWorldAgentSessionSnapshot } from '../../../packages/shared/src/contracts/customWorldAgent';
|
||||
import { WorldType, type CustomWorldProfile } from '../../types';
|
||||
import { type CustomWorldProfile, WorldType } from '../../types';
|
||||
import { useRpgCreationEnterWorld } from './useRpgCreationEnterWorld';
|
||||
|
||||
function buildProfile(params: {
|
||||
@@ -88,7 +88,11 @@ function buildSession(): CustomWorldAgentSessionSnapshot {
|
||||
stage: 'ready_to_publish',
|
||||
focusCardId: null,
|
||||
creatorIntent: null,
|
||||
creatorIntentReadiness: { isReady: true, completedKeys: [], missingKeys: [] },
|
||||
creatorIntentReadiness: {
|
||||
isReady: true,
|
||||
completedKeys: [],
|
||||
missingKeys: [],
|
||||
},
|
||||
anchorPack: null,
|
||||
lockState: null,
|
||||
draftProfile: null,
|
||||
@@ -110,15 +114,15 @@ function buildSession(): CustomWorldAgentSessionSnapshot {
|
||||
}
|
||||
|
||||
describe('useRpgCreationEnterWorld', () => {
|
||||
it('Agent 草稿进入游戏时使用 session draft profile 的角色形象', async () => {
|
||||
it('Agent 草稿测试进入游戏时使用结果页当前 profile 的角色形象', async () => {
|
||||
const staleResultProfile = buildProfile({
|
||||
id: 'stale-result',
|
||||
name: '旧结果页快照',
|
||||
imageSrc: '/template/old-role.png',
|
||||
});
|
||||
const draftProfile = buildProfile({
|
||||
const resultProfile = buildProfile({
|
||||
id: 'draft-profile',
|
||||
name: '草稿真相源',
|
||||
name: '结果页真相源',
|
||||
imageSrc: '/generated-characters/draft-role/portrait.png',
|
||||
});
|
||||
const handleCustomWorldSelect = vi.fn();
|
||||
@@ -130,7 +134,7 @@ describe('useRpgCreationEnterWorld', () => {
|
||||
isAgentDraftResultView: true,
|
||||
activeAgentSessionId: 'session-1',
|
||||
generatedCustomWorldProfile: staleResultProfile,
|
||||
agentSessionProfile: draftProfile,
|
||||
agentSessionProfile: resultProfile,
|
||||
agentSession: buildSession(),
|
||||
handleCustomWorldSelect,
|
||||
executePublishWorld,
|
||||
@@ -138,7 +142,10 @@ describe('useRpgCreationEnterWorld', () => {
|
||||
});
|
||||
|
||||
return (
|
||||
<button type="button" onClick={() => void enterWorldForTestFromCurrentResult()}>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => void enterWorldForTestFromCurrentResult()}
|
||||
>
|
||||
进入
|
||||
</button>
|
||||
);
|
||||
@@ -150,9 +157,12 @@ describe('useRpgCreationEnterWorld', () => {
|
||||
});
|
||||
|
||||
expect(executePublishWorld).not.toHaveBeenCalled();
|
||||
expect(handleCustomWorldSelect).toHaveBeenCalledWith(draftProfile);
|
||||
expect(handleCustomWorldSelect.mock.calls[0]?.[0].playableNpcs[0]?.imageSrc).toBe(
|
||||
'/generated-characters/draft-role/portrait.png',
|
||||
);
|
||||
expect(handleCustomWorldSelect).toHaveBeenCalledWith(resultProfile, {
|
||||
mode: 'test',
|
||||
returnStage: 'custom-world-result',
|
||||
});
|
||||
expect(
|
||||
handleCustomWorldSelect.mock.calls[0]?.[0].playableNpcs[0]?.imageSrc,
|
||||
).toBe('/generated-characters/draft-role/portrait.png');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { useCallback } from 'react';
|
||||
|
||||
import type { CustomWorldAgentSessionSnapshot } from '../../../packages/shared/src/contracts/customWorldAgent';
|
||||
import type { CustomWorldRuntimeLaunchOptions } from '../platform-entry/platformEntryTypes';
|
||||
import { rpgCreationPreviewAdapter } from '../../services/rpg-creation/rpgCreationPreviewAdapter';
|
||||
import type { CustomWorldProfile } from '../../types';
|
||||
|
||||
@@ -10,14 +11,17 @@ type UseRpgCreationEnterWorldParams = {
|
||||
generatedCustomWorldProfile: CustomWorldProfile | null;
|
||||
agentSessionProfile: CustomWorldProfile | null;
|
||||
agentSession: CustomWorldAgentSessionSnapshot | null;
|
||||
handleCustomWorldSelect: (customWorldProfile: CustomWorldProfile) => void;
|
||||
handleCustomWorldSelect: (
|
||||
customWorldProfile: CustomWorldProfile,
|
||||
options?: CustomWorldRuntimeLaunchOptions,
|
||||
) => void;
|
||||
executePublishWorld: () => Promise<CustomWorldAgentSessionSnapshot | null>;
|
||||
setGeneratedCustomWorldProfile: (profile: CustomWorldProfile | null) => void;
|
||||
};
|
||||
|
||||
/**
|
||||
* 统一“进入世界”前的最终同步策略。
|
||||
* Agent 草稿结果进入游戏时只读 session.draftProfile,不再把结果页快照回写成新的运行时 profile。
|
||||
* Agent 草稿结果进入游戏时只读当前结果页 profile,不再静默回退到基础 draftProfile。
|
||||
*/
|
||||
export function useRpgCreationEnterWorld(
|
||||
params: UseRpgCreationEnterWorldParams,
|
||||
@@ -39,13 +43,22 @@ export function useRpgCreationEnterWorld(
|
||||
}
|
||||
|
||||
if (!isAgentDraftResultView || !activeAgentSessionId) {
|
||||
handleCustomWorldSelect(generatedCustomWorldProfile);
|
||||
handleCustomWorldSelect(generatedCustomWorldProfile, {
|
||||
mode: 'test',
|
||||
returnStage: 'custom-world-result',
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const latestProfile = agentSessionProfile ?? generatedCustomWorldProfile;
|
||||
setGeneratedCustomWorldProfile(latestProfile);
|
||||
handleCustomWorldSelect(latestProfile);
|
||||
if (!agentSessionProfile) {
|
||||
return;
|
||||
}
|
||||
|
||||
setGeneratedCustomWorldProfile(agentSessionProfile);
|
||||
handleCustomWorldSelect(agentSessionProfile, {
|
||||
mode: 'test',
|
||||
returnStage: 'custom-world-result',
|
||||
});
|
||||
}, [
|
||||
activeAgentSessionId,
|
||||
agentSessionProfile,
|
||||
@@ -64,8 +77,11 @@ export function useRpgCreationEnterWorld(
|
||||
return generatedCustomWorldProfile;
|
||||
}
|
||||
|
||||
const latestProfile = agentSessionProfile ?? generatedCustomWorldProfile;
|
||||
setGeneratedCustomWorldProfile(latestProfile);
|
||||
if (!agentSessionProfile) {
|
||||
return null;
|
||||
}
|
||||
|
||||
setGeneratedCustomWorldProfile(agentSessionProfile);
|
||||
|
||||
const latestSession = agentSession;
|
||||
const canEnterPublishedWorld =
|
||||
@@ -73,13 +89,13 @@ export function useRpgCreationEnterWorld(
|
||||
latestSession.resultPreview?.canEnterWorld;
|
||||
|
||||
if (canEnterPublishedWorld) {
|
||||
return latestProfile;
|
||||
return agentSessionProfile;
|
||||
}
|
||||
|
||||
const publishedSession = await executePublishWorld();
|
||||
const publishedProfile =
|
||||
rpgCreationPreviewAdapter.buildPreviewFromSession(publishedSession) ??
|
||||
latestProfile;
|
||||
agentSessionProfile;
|
||||
|
||||
setGeneratedCustomWorldProfile(publishedProfile);
|
||||
return publishedProfile;
|
||||
@@ -89,7 +105,6 @@ export function useRpgCreationEnterWorld(
|
||||
agentSessionProfile,
|
||||
executePublishWorld,
|
||||
generatedCustomWorldProfile,
|
||||
handleCustomWorldSelect,
|
||||
isAgentDraftResultView,
|
||||
setGeneratedCustomWorldProfile,
|
||||
]);
|
||||
|
||||
@@ -219,7 +219,7 @@ export function useRpgCreationResultAutosave(
|
||||
}
|
||||
|
||||
// Agent 结果页不再把前端 profile 回写到 session。
|
||||
// session.draftProfile 是真相源;这里只刷新后端最新快照,避免在采集/生成早期误触 sync_result_profile。
|
||||
// 这里只刷新后端结果页快照,避免在采集/生成早期误触 sync_result_profile。
|
||||
const latestSession = await syncAgentSessionSnapshot(activeAgentSessionId);
|
||||
const latestProfile = normalizeAgentBackedProfile(
|
||||
buildDraftResultProfile(latestSession) ?? profile,
|
||||
|
||||
Reference in New Issue
Block a user