Extend square-hole creation flow with visual asset timeout guard
This commit is contained in:
@@ -32,22 +32,6 @@ import type {
|
||||
Match3DWorkProfile,
|
||||
Match3DWorkSummary,
|
||||
} from '../../../packages/shared/src/contracts/match3dWorks';
|
||||
import type {
|
||||
CreateSquareHoleSessionRequest,
|
||||
ExecuteSquareHoleActionRequest,
|
||||
SendSquareHoleMessageRequest,
|
||||
SquareHoleActionResponse,
|
||||
SquareHoleSessionResponse,
|
||||
SquareHoleSessionSnapshot,
|
||||
} from '../../../packages/shared/src/contracts/squareHoleAgent';
|
||||
import type {
|
||||
DropSquareHoleShapeRequest,
|
||||
SquareHoleRunSnapshot,
|
||||
} from '../../../packages/shared/src/contracts/squareHoleRuntime';
|
||||
import type {
|
||||
SquareHoleWorkProfile,
|
||||
SquareHoleWorkSummary,
|
||||
} from '../../../packages/shared/src/contracts/squareHoleWorks';
|
||||
import type {
|
||||
PuzzleAgentActionRequest,
|
||||
PuzzleAgentOperationRecord,
|
||||
@@ -72,6 +56,21 @@ import type {
|
||||
ProfileSaveArchiveResumeResponse,
|
||||
ProfileSaveArchiveSummary,
|
||||
} from '../../../packages/shared/src/contracts/runtime';
|
||||
import type {
|
||||
CreateSquareHoleSessionRequest,
|
||||
ExecuteSquareHoleActionRequest,
|
||||
SendSquareHoleMessageRequest,
|
||||
SquareHoleActionResponse,
|
||||
SquareHoleSessionResponse,
|
||||
SquareHoleSessionSnapshot,
|
||||
} from '../../../packages/shared/src/contracts/squareHoleAgent';
|
||||
import type {
|
||||
SquareHoleRunSnapshot,
|
||||
} from '../../../packages/shared/src/contracts/squareHoleRuntime';
|
||||
import type {
|
||||
SquareHoleWorkProfile,
|
||||
SquareHoleWorkSummary,
|
||||
} from '../../../packages/shared/src/contracts/squareHoleWorks';
|
||||
import { buildCustomWorldPlayableCharacters } from '../../data/characterPresets';
|
||||
import {
|
||||
buildPublicWorkStagePath,
|
||||
@@ -123,6 +122,7 @@ import {
|
||||
buildBigFishGenerationAnchorEntries,
|
||||
buildMiniGameDraftGenerationProgress,
|
||||
buildPuzzleGenerationAnchorEntries,
|
||||
buildSquareHoleGenerationAnchorEntries,
|
||||
createMiniGameDraftGenerationState,
|
||||
type MiniGameDraftGenerationState,
|
||||
} from '../../services/miniGameDraftGenerationProgress';
|
||||
@@ -552,8 +552,12 @@ function mapPublicWorkDetailToSquareHoleWork(
|
||||
summary: entry.summaryText,
|
||||
tags: entry.themeTags,
|
||||
coverImageSrc: entry.coverImageSrc,
|
||||
shapeCount: 8,
|
||||
difficulty: 4,
|
||||
backgroundPrompt: entry.backgroundPrompt ?? '方洞挑战运行背景',
|
||||
backgroundImageSrc: entry.backgroundImageSrc ?? null,
|
||||
shapeOptions: entry.shapeOptions ?? [],
|
||||
holeOptions: entry.holeOptions ?? [],
|
||||
shapeCount: entry.shapeCount ?? 8,
|
||||
difficulty: entry.difficulty ?? 4,
|
||||
publicationStatus: 'published',
|
||||
playCount: entry.playCount ?? 0,
|
||||
updatedAt: entry.updatedAt,
|
||||
@@ -581,7 +585,11 @@ function buildSquareHoleProfileFromSession(
|
||||
twistRule: draft.twistRule,
|
||||
summary: draft.summary,
|
||||
tags: draft.tags,
|
||||
coverImageSrc: null,
|
||||
coverImageSrc: draft.coverImageSrc ?? null,
|
||||
backgroundPrompt: draft.backgroundPrompt,
|
||||
backgroundImageSrc: draft.backgroundImageSrc ?? null,
|
||||
shapeOptions: draft.shapeOptions,
|
||||
holeOptions: draft.holeOptions,
|
||||
shapeCount: draft.shapeCount,
|
||||
difficulty: draft.difficulty,
|
||||
publicationStatus: 'draft',
|
||||
@@ -608,13 +616,6 @@ function mergeBigFishWorkSummary(
|
||||
: current;
|
||||
}
|
||||
|
||||
function mergeSquareHoleWorkSummary(
|
||||
current: SquareHoleWorkSummary,
|
||||
updated: SquareHoleWorkSummary,
|
||||
): SquareHoleWorkSummary {
|
||||
return current.profileId === updated.profileId ? updated : current;
|
||||
}
|
||||
|
||||
async function resolvePublicWorkAuthorSummary(
|
||||
entry: PlatformPublicGalleryCard,
|
||||
): Promise<PublicUserSummary | null> {
|
||||
@@ -1086,6 +1087,8 @@ export function PlatformEntryFlowShellImpl({
|
||||
useState<SquareHoleRuntimeReturnStage>('square-hole-result');
|
||||
const [isSquareHoleLoadingLibrary, setIsSquareHoleLoadingLibrary] =
|
||||
useState(false);
|
||||
const [squareHoleGenerationState, setSquareHoleGenerationState] =
|
||||
useState<MiniGameDraftGenerationState | null>(null);
|
||||
const [bigFishRun, setBigFishRun] =
|
||||
useState<BigFishRuntimeSnapshotResponse | null>(null);
|
||||
const [bigFishRuntimeShare, setBigFishRuntimeShare] = useState<{
|
||||
@@ -1817,7 +1820,7 @@ export function PlatformEntryFlowShellImpl({
|
||||
workspaceStage: 'square-hole-agent-workspace',
|
||||
resultStage: 'square-hole-result',
|
||||
platformStage: 'platform',
|
||||
isCompileAction: (payload) => payload.action === 'square_hole_compile_draft',
|
||||
isCompileAction: () => false,
|
||||
resolveErrorMessage: resolveSquareHoleErrorMessage,
|
||||
errorMessages: {
|
||||
open: '开启方洞挑战共创工作台失败。',
|
||||
@@ -1831,9 +1834,30 @@ export function PlatformEntryFlowShellImpl({
|
||||
onSessionOpened: () => {
|
||||
setShowCreationTypeModal(false);
|
||||
},
|
||||
beforeExecuteAction: ({ payload }) => {
|
||||
if (payload.action === 'square_hole_compile_draft') {
|
||||
setSquareHoleGenerationState(
|
||||
createMiniGameDraftGenerationState('square-hole'),
|
||||
);
|
||||
setSelectionStage('square-hole-generating');
|
||||
}
|
||||
if (payload.action === 'square_hole_generate_visual_assets') {
|
||||
setSquareHoleGenerationState((current) => ({
|
||||
...(current ?? createMiniGameDraftGenerationState('square-hole')),
|
||||
phase: 'square-hole-cover',
|
||||
completedAssetCount: 0,
|
||||
totalAssetCount: 0,
|
||||
error: null,
|
||||
}));
|
||||
setSelectionStage('square-hole-generating');
|
||||
}
|
||||
},
|
||||
onActionComplete: async ({ payload, response, setSession }) => {
|
||||
setSession(response.session);
|
||||
if (payload.action !== 'square_hole_compile_draft') {
|
||||
if (
|
||||
payload.action !== 'square_hole_compile_draft' &&
|
||||
payload.action !== 'square_hole_generate_visual_assets'
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1843,12 +1867,79 @@ export function PlatformEntryFlowShellImpl({
|
||||
return;
|
||||
}
|
||||
|
||||
if (payload.action === 'square_hole_compile_draft') {
|
||||
try {
|
||||
const assetResponse = await squareHoleCreationClient.executeAction(
|
||||
response.session.sessionId,
|
||||
{
|
||||
action: 'square_hole_generate_visual_assets',
|
||||
},
|
||||
);
|
||||
setSession(assetResponse.session);
|
||||
const assetProfileId = assetResponse.session.draft?.profileId;
|
||||
if (!assetProfileId) {
|
||||
setSquareHoleProfile(
|
||||
buildSquareHoleProfileFromSession(assetResponse.session),
|
||||
);
|
||||
setSelectionStage('square-hole-result');
|
||||
return;
|
||||
}
|
||||
const { item } = await getSquareHoleWorkDetail(assetProfileId);
|
||||
setSquareHoleProfile(item);
|
||||
setSquareHoleGenerationState((current) => ({
|
||||
...(current ?? createMiniGameDraftGenerationState('square-hole')),
|
||||
phase: 'ready',
|
||||
completedAssetCount: item.shapeOptions.length + 2,
|
||||
totalAssetCount: item.shapeOptions.length + 2,
|
||||
error: null,
|
||||
}));
|
||||
await refreshSquareHoleShelf().catch(() => undefined);
|
||||
setSelectionStage('square-hole-result');
|
||||
} catch (error) {
|
||||
const errorMessage = resolveSquareHoleErrorMessage(
|
||||
error,
|
||||
'生成方洞挑战图片失败。',
|
||||
);
|
||||
setSquareHoleError(errorMessage);
|
||||
setSquareHoleGenerationState((current) => ({
|
||||
...(current ?? createMiniGameDraftGenerationState('square-hole')),
|
||||
phase: 'failed',
|
||||
error: errorMessage,
|
||||
}));
|
||||
setSquareHoleProfile(buildSquareHoleProfileFromSession(response.session));
|
||||
setSelectionStage('square-hole-generating');
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const { item } = await getSquareHoleWorkDetail(profileId);
|
||||
setSquareHoleProfile(item);
|
||||
setSquareHoleGenerationState((current) => ({
|
||||
...(current ?? createMiniGameDraftGenerationState('square-hole')),
|
||||
phase: 'ready',
|
||||
completedAssetCount: item.shapeOptions.length + 2,
|
||||
totalAssetCount: item.shapeOptions.length + 2,
|
||||
error: null,
|
||||
}));
|
||||
await refreshSquareHoleShelf().catch(() => undefined);
|
||||
setSelectionStage('square-hole-result');
|
||||
} catch {
|
||||
setSquareHoleProfile(buildSquareHoleProfileFromSession(response.session));
|
||||
setSelectionStage('square-hole-result');
|
||||
}
|
||||
},
|
||||
onActionError: ({ payload, errorMessage }) => {
|
||||
if (
|
||||
payload.action === 'square_hole_compile_draft' ||
|
||||
payload.action === 'square_hole_generate_visual_assets'
|
||||
) {
|
||||
setSquareHoleGenerationState((current) => ({
|
||||
...(current ?? createMiniGameDraftGenerationState('square-hole')),
|
||||
phase: 'failed',
|
||||
error: errorMessage,
|
||||
}));
|
||||
setSelectionStage('square-hole-generating');
|
||||
}
|
||||
},
|
||||
});
|
||||
@@ -2047,6 +2138,7 @@ export function PlatformEntryFlowShellImpl({
|
||||
setSquareHoleProfile(null);
|
||||
setSquareHoleRun(null);
|
||||
setSquareHoleError(null);
|
||||
setSquareHoleGenerationState(null);
|
||||
setSquareHoleRuntimeReturnStage('square-hole-result');
|
||||
setStreamingSquareHoleReplyText('');
|
||||
setIsStreamingSquareHoleReply(false);
|
||||
@@ -2162,6 +2254,7 @@ export function PlatformEntryFlowShellImpl({
|
||||
setSquareHoleGalleryEntries([]);
|
||||
setSquareHoleRun(null);
|
||||
setSquareHoleRuntimeReturnStage('square-hole-result');
|
||||
setSquareHoleGenerationState(null);
|
||||
setSquareHoleError(null);
|
||||
setStreamingSquareHoleReplyText('');
|
||||
setIsStreamingSquareHoleReply(false);
|
||||
@@ -2291,6 +2384,7 @@ export function PlatformEntryFlowShellImpl({
|
||||
const leaveSquareHoleFlow = useCallback(() => {
|
||||
setSquareHoleRun(null);
|
||||
setSquareHoleRuntimeReturnStage('square-hole-result');
|
||||
setSquareHoleGenerationState(null);
|
||||
squareHoleFlow.leaveFlow();
|
||||
}, [squareHoleFlow]);
|
||||
|
||||
@@ -2316,6 +2410,20 @@ export function PlatformEntryFlowShellImpl({
|
||||
|
||||
const executeSquareHoleAction = squareHoleFlow.executeAction;
|
||||
|
||||
const retrySquareHoleAssetGeneration = useCallback(() => {
|
||||
const session = squareHoleSession;
|
||||
if (!session?.draft?.profileId) {
|
||||
void executeSquareHoleAction({
|
||||
action: 'square_hole_compile_draft',
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
void executeSquareHoleAction({
|
||||
action: 'square_hole_generate_visual_assets',
|
||||
});
|
||||
}, [executeSquareHoleAction, squareHoleSession]);
|
||||
|
||||
const executePuzzleAction = puzzleFlow.executeAction;
|
||||
|
||||
const retryPuzzleDraftGeneration = useCallback(() => {
|
||||
@@ -4013,6 +4121,7 @@ export function PlatformEntryFlowShellImpl({
|
||||
return;
|
||||
}
|
||||
|
||||
setSquareHoleGenerationState(null);
|
||||
const restoredSession = await squareHoleFlow.restoreDraft(
|
||||
item.sourceSessionId,
|
||||
);
|
||||
@@ -5583,6 +5692,50 @@ export function PlatformEntryFlowShellImpl({
|
||||
</motion.div>
|
||||
)}
|
||||
|
||||
{selectionStage === 'square-hole-generating' && (
|
||||
<motion.div
|
||||
key="square-hole-generating"
|
||||
initial={{ opacity: 0, y: 12 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
exit={{ opacity: 0, y: -12 }}
|
||||
className="flex h-full min-h-0 flex-col"
|
||||
>
|
||||
<Suspense
|
||||
fallback={<LazyPanelFallback label="正在加载方洞挑战生成面板..." />}
|
||||
>
|
||||
<CustomWorldGenerationView
|
||||
settingText={
|
||||
squareHoleSession?.lastAssistantReply ??
|
||||
'正在整理当前方洞挑战草稿。'
|
||||
}
|
||||
anchorEntries={buildSquareHoleGenerationAnchorEntries(
|
||||
squareHoleSession,
|
||||
)}
|
||||
progress={buildMiniGameDraftGenerationProgress(
|
||||
squareHoleGenerationState,
|
||||
)}
|
||||
isGenerating={isSquareHoleBusy}
|
||||
error={squareHoleError}
|
||||
onBack={leaveSquareHoleFlow}
|
||||
onEditSetting={() => {
|
||||
setSelectionStage('square-hole-agent-workspace');
|
||||
}}
|
||||
onRetry={retrySquareHoleAssetGeneration}
|
||||
onInterrupt={undefined}
|
||||
backLabel="返回创作中心"
|
||||
settingActionLabel={null}
|
||||
retryLabel="重新生成图片"
|
||||
settingTitle="当前方洞挑战"
|
||||
settingDescription={null}
|
||||
progressTitle="方洞挑战图片生成进度"
|
||||
activeBadgeLabel="图片生成中"
|
||||
pausedBadgeLabel="图片生成已暂停"
|
||||
idleBadgeLabel="等待返回结果页"
|
||||
/>
|
||||
</Suspense>
|
||||
</motion.div>
|
||||
)}
|
||||
|
||||
{selectionStage === 'square-hole-result' && squareHoleSession?.draft && (
|
||||
<motion.div
|
||||
key="square-hole-result"
|
||||
|
||||
Reference in New Issue
Block a user