import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import type { CustomWorldAgentActionRequest, CustomWorldAgentOperationRecord, CustomWorldAgentSessionSnapshot, SendCustomWorldAgentMessageRequest, } from '../../../packages/shared/src/contracts/customWorldAgent'; import { buildAgentDraftFoundationAnchorEntries, buildAgentDraftFoundationGenerationProgress, buildAgentDraftFoundationSettingText, isDraftFoundationOperation, isDraftFoundationOperationRunning, } from '../../services/customWorldAgentGenerationProgress'; import { readCustomWorldAgentUiState, shouldRestoreCustomWorldAgentUiState, writeCustomWorldAgentUiState, } from '../../services/customWorldAgentUiState'; import { createRpgCreationSession, executeRpgCreationAction, getRpgCreationResultView, getRpgCreationSession, streamRpgCreationMessage, } from '../../services/rpg-creation'; import { rpgCreationPreviewAdapter } from '../../services/rpg-creation/rpgCreationPreviewAdapter'; import type { CustomWorldProfile } from '../../types'; import { buildOptimisticAgentMessage, createFailedAgentOperation, resolveRpgCreationErrorMessage, } from './rpgEntryShared'; import type { CustomWorldGenerationViewSource, CustomWorldResultViewSource, SelectionStage, } from './rpgEntryTypes'; type UseRpgCreationSessionControllerParams = { userId: string | null | undefined; openLoginModal?: | ((postLoginAction?: (() => void) | null) => void) | undefined; selectionStage: SelectionStage; setSelectionStage: (stage: SelectionStage) => void; enterCreateTab?: (() => void) | undefined; onSessionOpened?: (() => void) | undefined; }; type PendingAgentUserMessage = { sessionId: string; message: CustomWorldAgentSessionSnapshot['messages'][number]; }; const AGENT_DRAFT_RESULT_AUTO_OPEN_MAX_ATTEMPTS = 12; const AGENT_DRAFT_RESULT_AUTO_OPEN_RETRY_MS = 900; export function useRpgCreationSessionController( params: UseRpgCreationSessionControllerParams, ) { const { userId, openLoginModal, selectionStage, setSelectionStage, enterCreateTab, onSessionOpened, } = params; const initialAgentUiStateRef = useRef(readCustomWorldAgentUiState()); const shouldRestoreInitialAgentUiStateRef = useRef( shouldRestoreCustomWorldAgentUiState(), ); const initialAgentSessionId = initialAgentUiStateRef.current.activeSessionId; const isInitialAgentGenerationRestore = Boolean(initialAgentUiStateRef.current.activeOperationId) && initialAgentUiStateRef.current.customWorldGenerationSource === 'agent-draft-foundation'; const canResolveInitialAgentSessionOwner = !initialAgentSessionId || !userId || Boolean(initialAgentUiStateRef.current.ownerUserId) || isInitialAgentGenerationRestore; const isInitialAgentUiStateOwnedByCurrentUser = canResolveInitialAgentSessionOwner && (!initialAgentUiStateRef.current.ownerUserId || initialAgentUiStateRef.current.ownerUserId === userId); const isHydratingInitialAgentWorkspaceRef = useRef( Boolean( initialAgentSessionId && shouldRestoreInitialAgentUiStateRef.current && isInitialAgentUiStateOwnedByCurrentUser, ), ); const hasAppliedInitialAgentWorkspaceRef = useRef(false); const hasRequestedInitialAgentWorkspaceAuthRef = useRef(false); const isAgentDraftResultAutoOpenSuppressedRef = useRef(false); const currentAgentSessionIdRef = useRef(null); const activeAgentReplyAbortControllerRef = useRef( null, ); const latestAgentSessionSyncRequestIdRef = useRef(0); const [isCreatingAgentSession, setIsCreatingAgentSession] = useState(false); const [activeAgentSessionId, setActiveAgentSessionId] = useState< string | null >(() => shouldRestoreInitialAgentUiStateRef.current && isInitialAgentUiStateOwnedByCurrentUser ? (initialAgentUiStateRef.current.activeSessionId ?? null) : null, ); const [activeAgentOperationId, setActiveAgentOperationId] = useState< string | null >(() => shouldRestoreInitialAgentUiStateRef.current && isInitialAgentUiStateOwnedByCurrentUser ? (initialAgentUiStateRef.current.activeOperationId ?? null) : null, ); const [agentSession, setAgentSession] = useState(null); const [agentOperation, setAgentOperation] = useState(null); const [streamingAgentReplyText, setStreamingAgentReplyText] = useState(''); const [isStreamingAgentReply, setIsStreamingAgentReply] = useState(false); const [pendingAgentUserMessage, setPendingAgentUserMessage] = useState(null); const [isLoadingAgentSession, setIsLoadingAgentSession] = useState(false); const [creationTypeError, setCreationTypeError] = useState( null, ); const [agentWorkspaceRestoreError, setAgentWorkspaceRestoreError] = useState< string | null >(null); const [generatedCustomWorldProfile, setGeneratedCustomWorldProfile] = useState(null); const [customWorldError, setCustomWorldError] = useState(null); const [customWorldGenerationViewSource, setCustomWorldGenerationViewSource] = useState(null); const [customWorldResultViewSource, setCustomWorldResultViewSource] = useState(null); const [agentDraftGenerationStartedAt, setAgentDraftGenerationStartedAt] = useState(null); const pendingAgentUserMessageRef = useRef( null, ); const latestAgentResultViewOpenRequestIdRef = useRef(0); useEffect(() => { currentAgentSessionIdRef.current = agentSession?.sessionId ?? null; }, [agentSession]); useEffect(() => { pendingAgentUserMessageRef.current = pendingAgentUserMessage; }, [pendingAgentUserMessage]); const invalidateAgentSessionSyncRequests = useCallback(() => { latestAgentSessionSyncRequestIdRef.current += 1; }, []); const abortActiveAgentReplyStream = useCallback(() => { activeAgentReplyAbortControllerRef.current?.abort(); activeAgentReplyAbortControllerRef.current = null; }, []); const mergePendingAgentUserMessageIntoSession = useCallback( ( session: CustomWorldAgentSessionSnapshot | null, pending: PendingAgentUserMessage | null = pendingAgentUserMessageRef.current, ) => { if (!session || !pending || pending.sessionId !== session.sessionId) { return session; } const hasServerEchoedPendingMessage = session.messages.some( (message) => message.id === pending.message.id, ); if (hasServerEchoedPendingMessage) { return session; } return { ...session, messages: [...session.messages, pending.message], updatedAt: pending.message.createdAt, }; }, [], ); const persistAgentUiState = useCallback( ( nextSessionId: string | null, nextOperationId: string | null, nextGenerationSource: CustomWorldGenerationViewSource = null, ) => { setActiveAgentSessionId(nextSessionId); setActiveAgentOperationId(nextOperationId); writeCustomWorldAgentUiState({ activeSessionId: nextSessionId, activeOperationId: nextOperationId, customWorldGenerationSource: nextGenerationSource, // 工作区 session 是按 userId 持久化的,恢复指针必须绑定当前登录用户, // 避免切换账号或复用旧 URL 时反复请求不属于当前用户的 session 产生 404。 ownerUserId: nextSessionId ? userId : null, }); }, [userId], ); const syncAgentSessionSnapshot = useCallback( async (sessionId: string) => { const requestId = latestAgentSessionSyncRequestIdRef.current + 1; latestAgentSessionSyncRequestIdRef.current = requestId; const nextSession = await getRpgCreationSession(sessionId); const mergedSession = mergePendingAgentUserMessageIntoSession(nextSession); if (latestAgentSessionSyncRequestIdRef.current === requestId) { setAgentSession(mergedSession); const currentPendingAgentUserMessage = pendingAgentUserMessageRef.current; const hasServerEchoedPendingMessage = currentPendingAgentUserMessage?.sessionId === nextSession.sessionId && nextSession.messages.some( (message) => message.id === currentPendingAgentUserMessage.message.id, ); if (hasServerEchoedPendingMessage) { setPendingAgentUserMessage(null); } } return mergedSession; }, [mergePendingAgentUserMessageIntoSession], ); const syncAgentCreationResultView = useCallback( async (sessionId: string) => { const resultView = await getRpgCreationResultView(sessionId); const mergedSession = mergePendingAgentUserMessageIntoSession( resultView.session, ); setAgentSession(mergedSession); return { ...resultView, session: mergedSession ?? resultView.session, }; }, [mergePendingAgentUserMessageIntoSession], ); useEffect(() => { const initialAgentSessionId = initialAgentUiStateRef.current.activeSessionId; if (!initialAgentSessionId || hasAppliedInitialAgentWorkspaceRef.current) { return; } if ( initialAgentUiStateRef.current.ownerUserId && userId && initialAgentUiStateRef.current.ownerUserId !== userId ) { hasAppliedInitialAgentWorkspaceRef.current = true; isHydratingInitialAgentWorkspaceRef.current = false; persistAgentUiState(null, null); return; } if (!shouldRestoreInitialAgentUiStateRef.current) { return; } enterCreateTab?.(); if (!userId) { if (!hasRequestedInitialAgentWorkspaceAuthRef.current) { hasRequestedInitialAgentWorkspaceAuthRef.current = true; openLoginModal?.(() => { if ( initialAgentUiStateRef.current.activeOperationId && initialAgentUiStateRef.current.customWorldGenerationSource === 'agent-draft-foundation' ) { setCustomWorldGenerationViewSource('agent-draft-foundation'); setSelectionStage('custom-world-generating'); return; } setSelectionStage('agent-workspace'); }); } return; } if ( !initialAgentUiStateRef.current.ownerUserId && !( initialAgentUiStateRef.current.activeOperationId && initialAgentUiStateRef.current.customWorldGenerationSource === 'agent-draft-foundation' ) ) { hasAppliedInitialAgentWorkspaceRef.current = true; isHydratingInitialAgentWorkspaceRef.current = false; persistAgentUiState(null, null); return; } if ( initialAgentUiStateRef.current.ownerUserId && initialAgentUiStateRef.current.ownerUserId !== userId ) { hasAppliedInitialAgentWorkspaceRef.current = true; isHydratingInitialAgentWorkspaceRef.current = false; persistAgentUiState(null, null); return; } hasAppliedInitialAgentWorkspaceRef.current = true; if ( initialAgentUiStateRef.current.activeOperationId && initialAgentUiStateRef.current.customWorldGenerationSource === 'agent-draft-foundation' ) { setCustomWorldGenerationViewSource('agent-draft-foundation'); setCustomWorldResultViewSource(null); setSelectionStage('custom-world-generating'); return; } setSelectionStage('agent-workspace'); }, [ enterCreateTab, openLoginModal, persistAgentUiState, setSelectionStage, userId, ]); useEffect(() => { if ( selectionStage !== 'agent-workspace' && selectionStage !== 'custom-world-generating' ) { abortActiveAgentReplyStream(); setStreamingAgentReplyText(''); setIsStreamingAgentReply(false); } }, [abortActiveAgentReplyStream, selectionStage]); useEffect(() => { return () => { abortActiveAgentReplyStream(); }; }, [abortActiveAgentReplyStream]); useEffect(() => { if (!activeAgentSessionId) { abortActiveAgentReplyStream(); invalidateAgentSessionSyncRequests(); setAgentSession(null); setAgentOperation(null); setIsLoadingAgentSession(false); setStreamingAgentReplyText(''); setIsStreamingAgentReply(false); setPendingAgentUserMessage(null); setAgentWorkspaceRestoreError(null); isHydratingInitialAgentWorkspaceRef.current = false; return; } if (!userId) { abortActiveAgentReplyStream(); invalidateAgentSessionSyncRequests(); setAgentSession(null); setAgentOperation(null); setIsLoadingAgentSession(false); setStreamingAgentReplyText(''); setIsStreamingAgentReply(false); setPendingAgentUserMessage(null); setAgentWorkspaceRestoreError(null); return; } let cancelled = false; const isInitialWorkspaceRestore = isHydratingInitialAgentWorkspaceRef.current && activeAgentSessionId === initialAgentUiStateRef.current.activeSessionId; if (currentAgentSessionIdRef.current !== activeAgentSessionId) { abortActiveAgentReplyStream(); setAgentSession(null); setAgentOperation(null); setStreamingAgentReplyText(''); setIsStreamingAgentReply(false); setPendingAgentUserMessage(null); } setIsLoadingAgentSession(true); void syncAgentSessionSnapshot(activeAgentSessionId) .then(() => { if (!cancelled) { setCreationTypeError(null); setAgentWorkspaceRestoreError(null); isHydratingInitialAgentWorkspaceRef.current = false; } }) .catch((error) => { if (cancelled) { return; } // 登录后自动恢复的是“上一次残留的工作区指针”, // 这里失败时应优先静默清理,避免把旧恢复错误冒充成当前登录已失效。 if (isInitialWorkspaceRestore) { setAgentWorkspaceRestoreError(null); } else { setAgentWorkspaceRestoreError( resolveRpgCreationErrorMessage( error, '读取 Agent 共创工作区失败。', ), ); } setAgentSession(null); setAgentOperation(null); setStreamingAgentReplyText(''); setIsStreamingAgentReply(false); isHydratingInitialAgentWorkspaceRef.current = false; persistAgentUiState(null, null); enterCreateTab?.(); setSelectionStage('platform'); }) .finally(() => { if (!cancelled) { setIsLoadingAgentSession(false); } }); return () => { cancelled = true; }; }, [ activeAgentSessionId, abortActiveAgentReplyStream, enterCreateTab, invalidateAgentSessionSyncRequests, persistAgentUiState, setSelectionStage, syncAgentSessionSnapshot, userId, ]); useEffect(() => { if ( !isDraftFoundationOperationRunning(agentOperation) || agentDraftGenerationStartedAt ) { return; } setAgentDraftGenerationStartedAt(Date.now()); }, [agentDraftGenerationStartedAt, agentOperation]); useEffect(() => { if ( selectionStage !== 'custom-world-generating' || customWorldGenerationViewSource !== 'agent-draft-foundation' || !isDraftFoundationOperation(agentOperation) || agentOperation.status !== 'completed' ) { return; } let cancelled = false; void (async () => { for ( let attempt = 1; attempt <= AGENT_DRAFT_RESULT_AUTO_OPEN_MAX_ATTEMPTS; attempt += 1 ) { await new Promise((resolve) => { window.setTimeout(resolve, AGENT_DRAFT_RESULT_AUTO_OPEN_RETRY_MS); }); if (cancelled) { return; } const latestResultView = activeAgentSessionId ? await syncAgentCreationResultView(activeAgentSessionId).catch( () => null, ) : null; if (cancelled) { return; } const draftResultProfile = rpgCreationPreviewAdapter.buildPreviewFromResultView( latestResultView, ); if (!draftResultProfile) { continue; } setGeneratedCustomWorldProfile(draftResultProfile); setAgentDraftGenerationStartedAt(null); setCustomWorldGenerationViewSource(null); setCustomWorldResultViewSource('agent-draft'); setSelectionStage('custom-world-result'); return; } if (!cancelled) { setAgentDraftGenerationStartedAt(null); } })(); return () => { cancelled = true; }; }, [ activeAgentSessionId, agentOperation, agentSession, customWorldGenerationViewSource, selectionStage, setSelectionStage, syncAgentCreationResultView, ]); const agentDraftSettingPreview = useMemo( () => buildAgentDraftFoundationSettingText(agentSession), [agentSession], ); const agentDraftAnchorPreviewEntries = useMemo( () => buildAgentDraftFoundationAnchorEntries(agentSession), [agentSession], ); const agentDraftGenerationProgress = useMemo( () => buildAgentDraftFoundationGenerationProgress( agentOperation, agentDraftGenerationStartedAt, ), [agentDraftGenerationStartedAt, agentOperation], ); const isAgentDraftGenerationView = customWorldGenerationViewSource === 'agent-draft-foundation'; const isAgentDraftResultView = customWorldResultViewSource === 'agent-draft'; const isActiveGenerationRunning = isDraftFoundationOperationRunning(agentOperation); const activeGenerationError = isDraftFoundationOperation(agentOperation) && agentOperation.status === 'failed' ? agentOperation.error || agentOperation.phaseDetail : null; useEffect(() => { if ( !agentSession || !activeAgentSessionId || agentSession.draftCards.length === 0 ) { return; } if (isAgentDraftResultAutoOpenSuppressedRef.current) { return; } if ( selectionStage !== 'agent-workspace' && selectionStage !== 'custom-world-result' ) { return; } if ( selectionStage === 'custom-world-result' && generatedCustomWorldProfile ) { return; } const requestId = latestAgentResultViewOpenRequestIdRef.current + 1; latestAgentResultViewOpenRequestIdRef.current = requestId; let cancelled = false; void syncAgentCreationResultView(activeAgentSessionId) .then((resultView) => { if ( cancelled || latestAgentResultViewOpenRequestIdRef.current !== requestId || isAgentDraftResultAutoOpenSuppressedRef.current || resultView.targetStage !== 'custom-world-result' ) { return; } const resultProfile = rpgCreationPreviewAdapter.buildPreviewFromResultView(resultView); if (!resultProfile) { return; } setGeneratedCustomWorldProfile(resultProfile); setCustomWorldGenerationViewSource(null); setCustomWorldResultViewSource( resultView.resultViewSource ?? 'agent-draft', ); isAgentDraftResultAutoOpenSuppressedRef.current = false; if (selectionStage === 'agent-workspace') { setSelectionStage('custom-world-result'); } }) .catch(() => {}); return () => { cancelled = true; }; }, [ activeAgentSessionId, agentSession, generatedCustomWorldProfile, selectionStage, setSelectionStage, syncAgentCreationResultView, ]); const openRpgAgentWorkspace = useCallback( async (seedText = '') => { if (isCreatingAgentSession) { return; } setIsCreatingAgentSession(true); setCreationTypeError(null); isAgentDraftResultAutoOpenSuppressedRef.current = false; invalidateAgentSessionSyncRequests(); setAgentSession(null); setAgentOperation(null); setStreamingAgentReplyText(''); setIsStreamingAgentReply(false); setPendingAgentUserMessage(null); setGeneratedCustomWorldProfile(null); setCustomWorldError(null); setAgentDraftGenerationStartedAt(null); setCustomWorldGenerationViewSource(null); setCustomWorldResultViewSource(null); try { const { session } = await createRpgCreationSession( seedText ? { seedText } : {}, ); isHydratingInitialAgentWorkspaceRef.current = false; setAgentSession(session); setAgentOperation(null); setGeneratedCustomWorldProfile(null); setCustomWorldError(null); setAgentDraftGenerationStartedAt(null); setCustomWorldGenerationViewSource(null); setCustomWorldResultViewSource(null); enterCreateTab?.(); onSessionOpened?.(); persistAgentUiState(session.sessionId, null); setSelectionStage('agent-workspace'); } catch (error) { setCreationTypeError( resolveRpgCreationErrorMessage(error, '开启共创工作台失败。'), ); } finally { setIsCreatingAgentSession(false); } }, [ enterCreateTab, invalidateAgentSessionSyncRequests, isCreatingAgentSession, onSessionOpened, persistAgentUiState, setSelectionStage, ], ); const submitAgentMessage = useCallback( async (payload: SendCustomWorldAgentMessageRequest) => { if (!activeAgentSessionId || isStreamingAgentReply) { return; } const optimisticUserMessage = buildOptimisticAgentMessage({ id: payload.clientMessageId, role: 'user', kind: 'chat', text: payload.text.trim(), }); const pendingMessagePayload: PendingAgentUserMessage = { sessionId: activeAgentSessionId, message: optimisticUserMessage, }; setAgentOperation(null); persistAgentUiState(activeAgentSessionId, null); setStreamingAgentReplyText(''); setIsStreamingAgentReply(true); setPendingAgentUserMessage(pendingMessagePayload); const replyAbortController = new AbortController(); activeAgentReplyAbortControllerRef.current = replyAbortController; setAgentSession((current) => mergePendingAgentUserMessageIntoSession(current, pendingMessagePayload), ); try { const nextSession = await streamRpgCreationMessage( activeAgentSessionId, payload, { onUpdate: (text) => { if (replyAbortController.signal.aborted) { return; } setStreamingAgentReplyText(text); }, signal: replyAbortController.signal, }, ); if (replyAbortController.signal.aborted) { return; } const mergedNextSession = mergePendingAgentUserMessageIntoSession( nextSession, pendingMessagePayload, ); setAgentSession(mergedNextSession); setAgentOperation(null); setStreamingAgentReplyText(''); const hasServerEchoedPendingMessage = nextSession.messages.some( (message) => message.id === optimisticUserMessage.id, ); setPendingAgentUserMessage( hasServerEchoedPendingMessage ? null : pendingMessagePayload, ); } catch (error) { if (replyAbortController.signal.aborted) { return; } const errorMessage = resolveRpgCreationErrorMessage( error, '发送共创消息失败。', ); const warningMessage = buildOptimisticAgentMessage({ id: `message-error-${Date.now()}`, role: 'assistant', kind: 'warning', text: errorMessage, }); setAgentSession((current) => { const mergedCurrentSession = mergePendingAgentUserMessageIntoSession( current, pendingMessagePayload, ); return mergedCurrentSession ? { ...mergedCurrentSession, messages: [...mergedCurrentSession.messages, warningMessage], updatedAt: warningMessage.createdAt, } : current; }); setPendingAgentUserMessage(null); setStreamingAgentReplyText(''); persistAgentUiState(activeAgentSessionId, null); } finally { if ( activeAgentReplyAbortControllerRef.current === replyAbortController ) { activeAgentReplyAbortControllerRef.current = null; } if (!replyAbortController.signal.aborted) { setIsStreamingAgentReply(false); } } }, [ activeAgentSessionId, isStreamingAgentReply, mergePendingAgentUserMessageIntoSession, persistAgentUiState, ], ); const executeAgentAction = useCallback( async (payload: CustomWorldAgentActionRequest) => { if (!activeAgentSessionId) { return; } const isDraftFoundationAction = payload.action === 'draft_foundation'; if (isDraftFoundationAction) { isAgentDraftResultAutoOpenSuppressedRef.current = false; setGeneratedCustomWorldProfile(null); setCustomWorldError(null); setCustomWorldGenerationViewSource('agent-draft-foundation'); setCustomWorldResultViewSource(null); setAgentDraftGenerationStartedAt(Date.now()); setSelectionStage('custom-world-generating'); } try { const { operation } = await executeRpgCreationAction( activeAgentSessionId, payload, ); setAgentOperation(operation); persistAgentUiState( activeAgentSessionId, operation.operationId, isDraftFoundationAction ? 'agent-draft-foundation' : null, ); } catch (error) { const errorMessage = resolveRpgCreationErrorMessage( error, '执行共创操作失败。', ); setAgentOperation( createFailedAgentOperation({ type: payload.action === 'draft_foundation' ? 'draft_foundation' : payload.action, phaseLabel: '执行操作失败', error: errorMessage, }), ); persistAgentUiState( activeAgentSessionId, null, isDraftFoundationAction ? 'agent-draft-foundation' : null, ); } }, [activeAgentSessionId, persistAgentUiState, setSelectionStage], ); const setNormalizedGeneratedCustomWorldProfile = useCallback( (profile: CustomWorldProfile | null) => { setGeneratedCustomWorldProfile(profile); }, [], ); const resetSessionViewState = useCallback(() => { setAgentOperation(null); setStreamingAgentReplyText(''); setIsStreamingAgentReply(false); setPendingAgentUserMessage(null); setAgentDraftGenerationStartedAt(null); setCustomWorldGenerationViewSource(null); setCustomWorldResultViewSource(null); }, []); const suppressAgentDraftResultAutoOpen = useCallback(() => { isAgentDraftResultAutoOpenSuppressedRef.current = true; }, []); const releaseAgentDraftResultAutoOpenSuppression = useCallback(() => { isAgentDraftResultAutoOpenSuppressedRef.current = false; }, []); return { initialAgentSessionId: shouldRestoreInitialAgentUiStateRef.current && isInitialAgentUiStateOwnedByCurrentUser ? (initialAgentUiStateRef.current.activeSessionId ?? null) : null, isCreatingAgentSession, activeAgentSessionId, activeAgentOperationId, agentSession, setAgentSession, agentOperation, setAgentOperation, resetSessionViewState, streamingAgentReplyText, isStreamingAgentReply, isLoadingAgentSession, creationTypeError, setCreationTypeError, agentWorkspaceRestoreError, customWorldError, setCustomWorldError, generatedCustomWorldProfile, setGeneratedCustomWorldProfile: setNormalizedGeneratedCustomWorldProfile, rawSetGeneratedCustomWorldProfile: setGeneratedCustomWorldProfile, customWorldGenerationViewSource, setCustomWorldGenerationViewSource, customWorldResultViewSource, setCustomWorldResultViewSource, agentDraftGenerationStartedAt, setAgentDraftGenerationStartedAt, agentDraftSettingPreview, agentDraftAnchorPreviewEntries, agentDraftResultProfile: rpgCreationPreviewAdapter.buildPreviewFromResultPreview( agentSession?.resultPreview, ), agentDraftGenerationProgress, isAgentDraftGenerationView, isAgentDraftResultView, isActiveGenerationRunning, activeGenerationError, isAgentDraftResultAutoOpenSuppressedRef, suppressAgentDraftResultAutoOpen, releaseAgentDraftResultAutoOpenSuppression, persistAgentUiState, syncAgentSessionSnapshot, syncAgentCreationResultView, openRpgAgentWorkspace, submitAgentMessage, executeAgentAction, }; }