合并 master 到图片画布素材分支

保留图片画布素材元数据迁移记录

合入 Pingora 网关与生产运维更新

解决外部生成 worker 测试夹具时间戳冲突
This commit is contained in:
2026-06-19 17:01:31 +08:00
92 changed files with 59009 additions and 501 deletions
@@ -167,6 +167,7 @@ import {
fetchCreationEntryConfig,
} from '../../services/creationEntryConfigService';
import {
type CreationUrlState,
clearCreationUrlState,
readCreationUrlState,
writeCreationUrlState,
@@ -501,6 +502,7 @@ import {
type PendingDraftShelfKind,
type PendingDraftShelfMap,
type PendingDraftShelfMetadata,
buildPuzzleDraftOpenNoticeKeys,
resolveBigFishDraftOpenIntent,
resolveJumpHopDraftOpenIntent,
resolveMatch3DDraftOpenIntent,
@@ -912,6 +914,29 @@ function pushPuzzleResultHistoryEntry(
writeCreationUrlState(buildPuzzleCreationUrlState(session));
}
function pushPuzzleGeneratingHistoryEntry(
session: PuzzleAgentSessionSnapshot | null,
fallbackState?: CreationUrlState,
) {
pushAppHistoryPath('/creation/puzzle/generating');
writeCreationUrlState(
session ? buildPuzzleCreationUrlState(session) : (fallbackState ?? {}),
);
}
function buildPuzzleCreationUrlStateFromWork(
item: PuzzleWorkSummary,
): CreationUrlState {
const sourceSessionId = item.sourceSessionId?.trim() || null;
return {
sessionId: sourceSessionId,
profileId:
item.profileId?.trim() || buildPuzzleResultProfileId(sourceSessionId),
workId: item.workId?.trim() || buildPuzzleResultWorkId(sourceSessionId),
};
}
const PUZZLE_DRAFT_GENERATION_POINT_COST = 2;
const PUZZLE_BACKGROUND_ACTION_POLL_INTERVAL_MS = 3000;
const PUZZLE_BACKGROUND_ACTION_MAX_POLL_ATTEMPTS = 160;
@@ -4291,6 +4316,7 @@ export function PlatformEntryFlowShellImpl({
);
activePuzzleGenerationSessionIdRef.current =
response.session.sessionId;
pushPuzzleGeneratingHistoryEntry(response.session);
setSelectionStage('puzzle-generating');
markDraftGenerating('puzzle', [
response.session.sessionId,
@@ -4435,6 +4461,7 @@ export function PlatformEntryFlowShellImpl({
);
selectionStageRef.current = 'puzzle-generating';
activePuzzleGenerationSessionIdRef.current = session.sessionId;
pushPuzzleGeneratingHistoryEntry(session);
setSelectionStage('puzzle-generating');
const nextGenerationState = createPuzzleDraftGenerationStateFromPayload(
formPayload ?? buildPuzzleFormPayloadFromSession(session),
@@ -5707,6 +5734,7 @@ export function PlatformEntryFlowShellImpl({
}
selectionStageRef.current = 'puzzle-generating';
activePuzzleGenerationSessionIdRef.current = nextSession.sessionId;
pushPuzzleGeneratingHistoryEntry(nextSession);
setSelectionStage('puzzle-generating');
try {
@@ -12110,6 +12138,66 @@ export function PlatformEntryFlowShellImpl({
setPuzzleRun(null);
setPuzzleRuntimeAuthMode('default');
setSelectedPuzzleDetail(null);
const restorePuzzleGeneratingSession = (
latestSession: PuzzleAgentSessionSnapshot,
) => {
const payload = buildPuzzleFormPayloadFromSession(latestSession);
const startedAtMs = resolveMiniGameDraftGenerationStartedAtMs(
latestSession.updatedAt,
);
const baseGenerationState =
createMiniGameDraftGenerationStateForRestoredDraft(
'puzzle',
{
puzzleAiRedraw: payload.aiRedraw ?? true,
puzzleProgressPercent:
latestSession.draft && !latestSession.draft.formDraft
? latestSession.progressPercent
: undefined,
},
startedAtMs,
);
const generationState = mergePuzzleSessionProgressIntoGenerationState(
baseGenerationState,
latestSession,
);
puzzleFlow.setSession(latestSession);
setPuzzleFormDraftPayload(payload);
setPuzzleGenerationState(generationState);
setPuzzleBackgroundCompileTasks((current) => ({
...current,
[latestSession.sessionId]: {
session: latestSession,
payload,
generationState,
error: null,
},
}));
enterCreateTab();
selectionStageRef.current = 'puzzle-generating';
activePuzzleGenerationSessionIdRef.current = latestSession.sessionId;
pushPuzzleGeneratingHistoryEntry(latestSession);
setSelectionStage('puzzle-generating');
};
const openPuzzleReadyResultSession = (
latestSession: PuzzleAgentSessionSnapshot,
) => {
const payload = buildPuzzleFormPayloadFromSession(latestSession);
puzzleFlow.setSession(latestSession);
setPuzzleFormDraftPayload(payload);
setPuzzleGenerationState(null);
setPuzzleBackgroundCompileTasks((current) => {
const next = { ...current };
delete next[latestSession.sessionId];
return next;
});
enterCreateTab();
selectionStageRef.current = 'puzzle-result';
activePuzzleGenerationSessionIdRef.current = null;
markDraftNoticeSeen(buildPuzzleDraftOpenNoticeKeys(item));
pushPuzzleResultHistoryEntry(latestSession);
setSelectionStage('puzzle-result');
};
if (openIntent.type === 'open-published-detail') {
await openPuzzleDetail(item.profileId, { tab: 'create' });
@@ -12175,6 +12263,10 @@ export function PlatformEntryFlowShellImpl({
enterCreateTab();
selectionStageRef.current = 'puzzle-generating';
activePuzzleGenerationSessionIdRef.current = sourceSessionId;
pushPuzzleGeneratingHistoryEntry(
failedSession,
buildPuzzleCreationUrlStateFromWork(item),
);
setPuzzleGenerationState(failedGenerationState);
setSelectionStage('puzzle-generating');
return;
@@ -12189,6 +12281,10 @@ export function PlatformEntryFlowShellImpl({
enterCreateTab();
selectionStageRef.current = 'puzzle-generating';
activePuzzleGenerationSessionIdRef.current = sourceSessionId;
pushPuzzleGeneratingHistoryEntry(
puzzleSession ?? backgroundTask?.session ?? null,
buildPuzzleCreationUrlStateFromWork(item),
);
setPuzzleGenerationState(rebasedGenerationState);
if (backgroundTask) {
setPuzzleBackgroundCompileTasks((current) => ({
@@ -12219,6 +12315,7 @@ export function PlatformEntryFlowShellImpl({
enterCreateTab();
selectionStageRef.current = 'puzzle-generating';
activePuzzleGenerationSessionIdRef.current = sourceSessionId;
pushPuzzleGeneratingHistoryEntry(rebasedTask.session);
setSelectionStage('puzzle-generating');
return;
}
@@ -12227,42 +12324,14 @@ export function PlatformEntryFlowShellImpl({
try {
const { session: latestSession } =
await getPuzzleAgentSession(sourceSessionId);
const payload = buildPuzzleFormPayloadFromSession(latestSession);
const startedAtMs = resolveMiniGameDraftGenerationStartedAtMs(
latestSession.updatedAt,
);
const baseGenerationState =
createMiniGameDraftGenerationStateForRestoredDraft(
'puzzle',
{
puzzleAiRedraw: payload.aiRedraw ?? true,
puzzleProgressPercent:
latestSession.draft && !latestSession.draft.formDraft
? latestSession.progressPercent
: undefined,
},
startedAtMs,
);
const generationState = mergePuzzleSessionProgressIntoGenerationState(
baseGenerationState,
latestSession,
);
puzzleFlow.setSession(latestSession);
setPuzzleFormDraftPayload(payload);
setPuzzleGenerationState(generationState);
setPuzzleBackgroundCompileTasks((current) => ({
...current,
[latestSession.sessionId]: {
session: latestSession,
payload,
generationState,
error: null,
},
}));
enterCreateTab();
selectionStageRef.current = 'puzzle-generating';
activePuzzleGenerationSessionIdRef.current = sourceSessionId;
setSelectionStage('puzzle-generating');
if (
!isPuzzleFormOnlyDraft(latestSession) &&
isPuzzleCompileActionReady(latestSession)
) {
openPuzzleReadyResultSession(latestSession);
return;
}
restorePuzzleGeneratingSession(latestSession);
return;
} catch (error) {
setPuzzleError(
@@ -12288,6 +12357,10 @@ export function PlatformEntryFlowShellImpl({
setSelectionStage('puzzle-agent-workspace');
} else {
setPuzzleFormDraftPayload(null);
pushPuzzleResultHistoryEntry(restoredSession);
selectionStageRef.current = 'puzzle-result';
activePuzzleGenerationSessionIdRef.current = null;
setSelectionStage('puzzle-result');
}
},
[