import { type FormEvent } from 'react'; import { resolveTauriInvoke } from '../../app/tauri'; import type { AgentChatPendingRuntimeRun, AgentConversationSessionRecord, AgentGoalMutationResult, AgentRuntimeContextCompactionResult, AgentRuntimeResult, AgentRuntimeUserInputRequest, LauncherAgentChatAgent, LocalConversationResult, TauriInvoke, } from '../../app/types'; import { agentGoalStatusIsPaused, agentGoalStatusIsTerminal, agentRuntimeCancelStatus, agentRuntimeConversationStatus, agentRuntimeStartStatus, agentRuntimeStateFromResult, createAgentChatRunId, isAgentRuntimeTerminalState, mergeAgentGoalRecordFromRuntime, parseAgentGoalItems, } from '../agent-runtime'; import type { DeveloperAgentState } from './useDeveloperAgentState'; type DeveloperAgentControlOptions = { state: DeveloperAgentState; validateAgentChatProjectPath: (projectPath?: string) => string | null; selectedLauncherAgentChatAgent: ( agentId?: string, ) => LauncherAgentChatAgent | null; selectedLauncherAgentChatSession: ( sessionId?: string | null, ) => AgentConversationSessionRecord | null; agentChatSessionInvokeArgs: (sessionId: string | null) => { sessionId?: string; }; updateAgentChatSessionMessageCount: ( sessionId: string | null, messageCount: number, ) => void; getCurrentAgentChatLlmWarning: ( agent?: LauncherAgentChatAgent | null, ) => string | null; setAgentChatPendingRuntimeRun: ( pendingRun: AgentChatPendingRuntimeRun | null, ) => void; }; export function createDeveloperAgentControls({ state, validateAgentChatProjectPath, selectedLauncherAgentChatAgent, selectedLauncherAgentChatSession, agentChatSessionInvokeArgs, updateAgentChatSessionMessageCount, getCurrentAgentChatLlmWarning, setAgentChatPendingRuntimeRun, }: DeveloperAgentControlOptions) { const { agentChatMessages, setAgentChatMessages, agentChatSelectedSessionId, setAgentChatConversationPath, setAgentChatInteractionMode, setAgentChatStatus, agentChatBusy, agentChatBackgroundBusy, setAgentChatBackgroundBusy, agentChatRuntime, setAgentChatRuntime, setAgentChatActiveRuntime, setAgentChatRuntimeError, agentChatGoal, setAgentChatGoal, agentChatGoalError, setAgentChatGoalError, agentChatGoalDialog, setAgentChatGoalDialog, setAgentChatGoalDialogError, agentChatLoadVersionRef, agentChatProjectPathRef, agentChatSelectedAgentIdRef, agentChatSelectedSessionIdRef, agentChatActiveSessionIdRef, agentChatPendingRuntimeRunRef, } = state; function applyAgentChatGoalMutationResult(result: AgentGoalMutationResult) { const runtimeState = agentRuntimeStateFromResult(result.runtime); setAgentChatGoal(result.goal); setAgentChatGoalError(''); setAgentChatRuntime(runtimeState); if ( agentChatActiveSessionIdRef.current === null || agentChatActiveSessionIdRef.current === result.goal.sessionId ) { setAgentChatActiveRuntime(runtimeState); } setAgentChatRuntimeError(''); return runtimeState; } async function refreshAgentChatConversationAfterGoalMutation( invoke: TauriInvoke, projectPathForChat: string, agentId: string, sessionId: string, saveVersion: number, ) { const conversation = await invoke( 'read_local_conversation', { projectPath: projectPathForChat, agentId, sessionId, }, ); if ( agentChatLoadVersionRef.current !== saveVersion || agentChatProjectPathRef.current.trim() !== projectPathForChat || agentChatSelectedAgentIdRef.current !== agentId || agentChatSelectedSessionIdRef.current !== sessionId ) { return null; } setAgentChatMessages(conversation.messages); setAgentChatConversationPath(conversation.path); updateAgentChatSessionMessageCount(sessionId, conversation.messages.length); return conversation; } function openAgentChatGoalDialog(mode: 'create' | 'edit') { const projectPathForChat = validateAgentChatProjectPath(); const agent = selectedLauncherAgentChatAgent(); const session = selectedLauncherAgentChatSession(); const sessionId = agentChatSelectedSessionId; if ( !projectPathForChat || !agent || !sessionId || agentChatBusy || agentChatBackgroundBusy ) { if (!sessionId) { setAgentChatStatus('请先读取并选择 Agent Session'); } return; } if (session?.archivedAt !== null && session?.archivedAt !== undefined) { setAgentChatStatus('已归档会话只能查看 Goal'); return; } if (agentChatGoalError) { setAgentChatStatus(agentChatGoalError); return; } if (mode === 'edit' && !agentChatGoal) { setAgentChatStatus('当前 Session 没有可编辑的持久目标'); return; } if ( mode === 'create' && agentChatGoal && !agentGoalStatusIsTerminal(agentChatGoal.status) ) { setAgentChatStatus('当前 Session 已有未结束的持久目标'); return; } const goal = mode === 'edit' ? agentChatGoal : null; setAgentChatInteractionMode('goal'); setAgentChatGoalDialogError(''); setAgentChatGoalDialog({ mode, projectPath: projectPathForChat, agentId: agent.id, sessionId, goalId: goal?.goalId ?? null, expectedRevision: goal?.revision ?? null, outcome: goal?.outcome ?? '', constraintsText: goal?.constraints.join('\n') ?? '', verificationText: goal?.verification.join('\n') ?? '', }); } async function handleAgentChatGoalDialogSubmit( event: FormEvent, ) { event.preventDefault(); const dialog = agentChatGoalDialog; if (!dialog || agentChatBusy || agentChatBackgroundBusy) { return; } if ( agentChatProjectPathRef.current.trim() !== dialog.projectPath || agentChatSelectedAgentIdRef.current !== dialog.agentId || agentChatSelectedSessionIdRef.current !== dialog.sessionId ) { setAgentChatGoalDialogError('Agent 或 Session 已变化,请关闭后重新打开'); return; } const outcome = dialog.outcome.trim(); const constraints = parseAgentGoalItems(dialog.constraintsText); const verification = parseAgentGoalItems(dialog.verificationText); if (!outcome) { setAgentChatGoalDialogError('Outcome 不能为空'); return; } if ([...outcome].length > 4_000) { setAgentChatGoalDialogError('Outcome 不能超过 4000 个字符'); return; } if (constraints.length > 8 || verification.length > 8) { setAgentChatGoalDialogError('Constraints 和 Verification 各最多 8 条'); return; } if ( [...constraints, ...verification].some((item) => [...item].length > 1_000) ) { setAgentChatGoalDialogError('每条约束或完成标准不能超过 1000 个字符'); return; } if ( new Set(constraints).size !== constraints.length || new Set(verification).size !== verification.length ) { setAgentChatGoalDialogError('Constraints 或 Verification 不能重复'); return; } const llmWarning = getCurrentAgentChatLlmWarning( selectedLauncherAgentChatAgent(dialog.agentId), ); if (llmWarning) { setAgentChatGoalDialogError(llmWarning); return; } const invoke = resolveTauriInvoke(); if (!invoke) { setAgentChatGoalDialogError('需要在 Tauri App 内运行'); return; } const saveVersion = agentChatLoadVersionRef.current + 1; agentChatLoadVersionRef.current = saveVersion; const previousPendingRun = agentChatPendingRuntimeRunRef.current; setAgentChatBackgroundBusy(true); setAgentChatGoalDialogError(''); setAgentChatStatus( dialog.mode === 'create' ? '正在开始持久目标' : '正在更新持久目标', ); try { const result = dialog.mode === 'create' ? await invoke( 'start_game_creator_agent_goal', { projectPath: dialog.projectPath, agentId: dialog.agentId, sessionId: dialog.sessionId, outcome, constraints, verification, runId: createAgentChatRunId('launcher-agent-goal'), }, ) : await invoke( 'edit_game_creator_agent_goal', { projectPath: dialog.projectPath, agentId: dialog.agentId, sessionId: dialog.sessionId, goalId: dialog.goalId, expectedRevision: dialog.expectedRevision, outcome, constraints, verification, }, ); if (agentChatLoadVersionRef.current !== saveVersion) { return; } if ( result.goal.agentId !== dialog.agentId || result.goal.sessionId !== dialog.sessionId || (dialog.mode === 'edit' && result.goal.goalId !== dialog.goalId) ) { throw new Error('Goal command 返回了错误的 Agent 或 Session 身份'); } const runtimeState = applyAgentChatGoalMutationResult(result); const conversation = await refreshAgentChatConversationAfterGoalMutation( invoke, dialog.projectPath, dialog.agentId, dialog.sessionId, saveVersion, ); if (agentChatLoadVersionRef.current !== saveVersion) { return; } if (agentGoalStatusIsPaused(result.goal.status)) { if ( agentChatPendingRuntimeRunRef.current?.runId === result.goal.runId ) { setAgentChatPendingRuntimeRun(null); } } else if (!agentGoalStatusIsTerminal(result.goal.status)) { setAgentChatPendingRuntimeRun({ projectPath: dialog.projectPath, agentId: dialog.agentId, sessionId: dialog.sessionId, runId: result.goal.runId || runtimeState.runId, messageCount: conversation?.messages.length ?? agentChatMessages.length, }); } setAgentChatGoalDialog(null); setAgentChatGoalDialogError(''); setAgentChatStatus( dialog.mode === 'create' ? `已开始持久目标:${result.goal.goalId}` : `持久目标已更新到 Revision ${result.goal.revision}${ result.providerInterrupted ? ',Provider 已中断并重新规划' : '' }`, ); } catch (error) { if (agentChatLoadVersionRef.current !== saveVersion) { return; } setAgentChatPendingRuntimeRun(previousPendingRun); const message = error instanceof Error ? error.message : String(error); setAgentChatGoalDialogError(message); setAgentChatStatus(`持久目标操作失败:${message}`); } finally { if (agentChatLoadVersionRef.current === saveVersion) { setAgentChatBackgroundBusy(false); } } } async function handleAgentChatGoalControl( operation: 'pause' | 'resume' | 'clear', ) { const projectPathForChat = validateAgentChatProjectPath(); const agent = selectedLauncherAgentChatAgent(); const session = selectedLauncherAgentChatSession(); const sessionId = agentChatSelectedSessionId; const goal = agentChatGoal; if ( !projectPathForChat || !agent || !sessionId || !goal || agentChatBusy || agentChatBackgroundBusy ) { return; } if (session?.archivedAt !== null && session?.archivedAt !== undefined) { setAgentChatStatus('已归档会话只能查看 Goal'); return; } if (goal.agentId !== agent.id || goal.sessionId !== sessionId) { setAgentChatStatus('当前 Goal 与 Agent Session 身份不匹配,请刷新'); return; } const invoke = resolveTauriInvoke(); if (!invoke) { setAgentChatStatus('需要在 Tauri App 内运行'); return; } const saveVersion = agentChatLoadVersionRef.current + 1; agentChatLoadVersionRef.current = saveVersion; setAgentChatBackgroundBusy(true); setAgentChatStatus( operation === 'pause' ? '正在暂停持久目标' : operation === 'resume' ? '正在恢复持久目标' : '正在清理持久目标', ); try { const args = { projectPath: projectPathForChat, agentId: agent.id, sessionId, goalId: goal.goalId, expectedRevision: goal.revision, }; const result = operation === 'pause' ? await invoke( 'pause_game_creator_agent_goal', args, ) : operation === 'resume' ? await invoke( 'resume_game_creator_agent_goal', args, ) : await invoke( 'clear_game_creator_agent_goal', args, ); if (agentChatLoadVersionRef.current !== saveVersion) { return; } if ( result.goal.goalId !== goal.goalId || result.goal.agentId !== agent.id || result.goal.sessionId !== sessionId ) { throw new Error('Goal command 返回了错误的 Goal 身份'); } applyAgentChatGoalMutationResult(result); if (operation === 'pause') { if (agentChatPendingRuntimeRunRef.current?.runId === goal.runId) { setAgentChatPendingRuntimeRun(null); } } else if (operation === 'resume') { setAgentChatPendingRuntimeRun({ projectPath: projectPathForChat, agentId: agent.id, sessionId, runId: result.goal.runId, messageCount: agentChatMessages.length, }); } else if (result.goal.status === 'cleared') { if (agentChatPendingRuntimeRunRef.current?.runId === goal.runId) { setAgentChatPendingRuntimeRun(null); } } else { setAgentChatPendingRuntimeRun({ projectPath: projectPathForChat, agentId: agent.id, sessionId, runId: result.goal.runId, messageCount: agentChatMessages.length, }); } setAgentChatStatus( operation === 'pause' ? result.goal.status === 'paused' ? '持久目标已暂停' : '持久目标正在安全边界暂停' : operation === 'resume' ? '持久目标已恢复,同一 Run 正在继续' : `持久目标清理状态:${result.goal.status}`, ); } catch (error) { if (agentChatLoadVersionRef.current !== saveVersion) { return; } setAgentChatStatus( `持久目标操作失败:${ error instanceof Error ? error.message : String(error) }`, ); } finally { if (agentChatLoadVersionRef.current === saveVersion) { setAgentChatBackgroundBusy(false); } } } async function handleAgentChatCompactContext() { const projectPathForChat = validateAgentChatProjectPath(); const agent = selectedLauncherAgentChatAgent(); const selectedSession = selectedLauncherAgentChatSession(); if ( !projectPathForChat || !agent || !selectedSession || selectedSession.archivedAt ) { setAgentChatStatus('请选择可写的 Agent Session'); return; } const invoke = resolveTauriInvoke(); if (!invoke) { setAgentChatStatus('上下文压缩需要在 Tauri App 内运行'); return; } setAgentChatBackgroundBusy(true); setAgentChatStatus('正在压缩当前 Agent Session 的旧上下文'); try { const result = await invoke( 'compact_game_creator_agent_runtime_context', { projectPath: projectPathForChat, agentId: agent.id, sessionId: selectedSession.sessionId, }, ); const runtime = await invoke( 'read_game_creator_agent_runtime', { projectPath: projectPathForChat, agentId: agent.id, sessionId: selectedSession.sessionId, }, ); setAgentChatRuntime((current) => agentRuntimeStateFromResult(runtime, current), ); setAgentChatStatus( result.reused ? `上下文已是最新压缩 revision ${result.revision}` : `上下文压缩完成:revision ${result.revision},预计 ${result.estimatedTokensBefore} -> ${result.estimatedTokensAfter} tokens`, ); } catch (error) { setAgentChatStatus( `上下文压缩失败:${ error instanceof Error ? error.message : String(error) }`, ); } finally { setAgentChatBackgroundBusy(false); } } async function handleAgentChatCancelRuntimeTask(runId: string) { const projectPathForChat = validateAgentChatProjectPath(); const agent = selectedLauncherAgentChatAgent(); const selectedSession = selectedLauncherAgentChatSession(); if ( !projectPathForChat || !agent || !runId || agentChatBusy || agentChatBackgroundBusy ) { return; } if (selectedSession && selectedSession.archivedAt !== null) { setAgentChatStatus('已归档会话只能查看 Runtime 历史'); return; } const invoke = resolveTauriInvoke(); if (!invoke) { setAgentChatStatus('需要在 Tauri App 内运行'); return; } const saveVersion = agentChatLoadVersionRef.current + 1; agentChatLoadVersionRef.current = saveVersion; setAgentChatBackgroundBusy(true); setAgentChatStatus('正在取消 Agent 后台任务'); try { const runtime = await invoke( 'cancel_game_creator_agent_runtime_task', { projectPath: projectPathForChat, agentId: agent.id, runId, }, ); if (agentChatLoadVersionRef.current !== saveVersion) { return; } const runtimeState = agentRuntimeStateFromResult(runtime); setAgentChatRuntime(runtimeState); setAgentChatActiveRuntime(runtimeState); setAgentChatGoal((current) => mergeAgentGoalRecordFromRuntime(current, runtimeState), ); setAgentChatRuntimeError(''); setAgentChatStatus(agentRuntimeCancelStatus(runtimeState, runId)); } catch (error) { if (agentChatLoadVersionRef.current !== saveVersion) { return; } setAgentChatStatus( error instanceof Error ? error.message : String(error), ); } finally { if (agentChatLoadVersionRef.current === saveVersion) { setAgentChatBackgroundBusy(false); } } } async function handleAgentChatRetryRuntimeTask(runId: string) { const projectPathForChat = validateAgentChatProjectPath(); const agent = selectedLauncherAgentChatAgent(); const selectedSession = selectedLauncherAgentChatSession(); const sessionIdForTask = agentChatSelectedSessionId; if ( !projectPathForChat || !agent || !runId || agentChatBusy || agentChatBackgroundBusy ) { return; } if (selectedSession && selectedSession.archivedAt !== null) { setAgentChatStatus('已归档会话不能重试任务'); return; } if ( agentGoalStatusIsPaused(agentChatGoal?.status) || agentGoalStatusIsPaused(agentChatRuntime?.goalStatus) || agentGoalStatusIsPaused(agentChatRuntime?.status) || agentGoalStatusIsPaused(agentChatRuntime?.phase) ) { setAgentChatStatus('持久目标已暂停,请先恢复 Goal'); return; } const llmWarning = getCurrentAgentChatLlmWarning(agent); if (llmWarning) { setAgentChatStatus(llmWarning); return; } const invoke = resolveTauriInvoke(); if (!invoke) { setAgentChatStatus('需要在 Tauri App 内运行'); return; } const saveVersion = agentChatLoadVersionRef.current + 1; agentChatLoadVersionRef.current = saveVersion; setAgentChatBackgroundBusy(true); setAgentChatStatus('正在重试 Agent 后台任务'); try { const runtime = await invoke( 'retry_game_creator_agent_runtime_task', { projectPath: projectPathForChat, agentId: agent.id, runId, nextRunId: createAgentChatRunId('launcher-agent-retry'), }, ); if (agentChatLoadVersionRef.current !== saveVersion) { return; } const runtimeState = agentRuntimeStateFromResult(runtime); setAgentChatRuntime(runtimeState); setAgentChatActiveRuntime(runtimeState); setAgentChatGoal((current) => mergeAgentGoalRecordFromRuntime(current, runtimeState), ); setAgentChatRuntimeError(''); const conversation = await invoke( 'read_local_conversation', { projectPath: projectPathForChat, agentId: agent.id, ...agentChatSessionInvokeArgs(sessionIdForTask), }, ); if (agentChatLoadVersionRef.current !== saveVersion) { return; } setAgentChatMessages(conversation.messages); setAgentChatStatus(agentRuntimeStartStatus(runtime)); } catch (error) { if (agentChatLoadVersionRef.current !== saveVersion) { return; } setAgentChatStatus( error instanceof Error ? error.message : String(error), ); } finally { if (agentChatLoadVersionRef.current === saveVersion) { setAgentChatBackgroundBusy(false); } } } async function handleAgentChatConfirmRuntimeTask( runId: string, actionId: string, ) { const projectPathForChat = validateAgentChatProjectPath(); const agent = selectedLauncherAgentChatAgent(); const selectedSession = selectedLauncherAgentChatSession(); const sessionIdForTask = agentChatSelectedSessionId; if ( !projectPathForChat || !agent || !runId || !actionId || agentChatBusy || agentChatBackgroundBusy ) { return; } if (selectedSession && selectedSession.archivedAt !== null) { setAgentChatStatus('已归档会话不能确认工具动作'); return; } const llmWarning = getCurrentAgentChatLlmWarning(agent); if (llmWarning) { setAgentChatStatus(llmWarning); return; } const invoke = resolveTauriInvoke(); if (!invoke) { setAgentChatStatus('需要在 Tauri App 内运行'); return; } const saveVersion = agentChatLoadVersionRef.current + 1; agentChatLoadVersionRef.current = saveVersion; setAgentChatBackgroundBusy(true); setAgentChatStatus('正在确认并继续 Agent 后台任务'); try { const runtime = await invoke( 'confirm_game_creator_agent_runtime_task', { projectPath: projectPathForChat, agentId: agent.id, runId, actionId, note: '开发者已确认待执行工具动作', }, ); if (agentChatLoadVersionRef.current !== saveVersion) { return; } const runtimeState = agentRuntimeStateFromResult(runtime); setAgentChatRuntime(runtimeState); setAgentChatActiveRuntime(runtimeState); setAgentChatGoal((current) => mergeAgentGoalRecordFromRuntime(current, runtimeState), ); setAgentChatRuntimeError(''); const conversation = await invoke( 'read_local_conversation', { projectPath: projectPathForChat, agentId: agent.id, ...agentChatSessionInvokeArgs(sessionIdForTask), }, ); if (agentChatLoadVersionRef.current !== saveVersion) { return; } setAgentChatMessages(conversation.messages); setAgentChatStatus(agentRuntimeStartStatus(runtime)); } catch (error) { if (agentChatLoadVersionRef.current !== saveVersion) { return; } setAgentChatStatus( error instanceof Error ? error.message : String(error), ); } finally { if (agentChatLoadVersionRef.current === saveVersion) { setAgentChatBackgroundBusy(false); } } } async function handleAgentChatRejectRuntimeTask( runId: string, actionId: string, ) { const projectPathForChat = validateAgentChatProjectPath(); const agent = selectedLauncherAgentChatAgent(); const selectedSession = selectedLauncherAgentChatSession(); const sessionIdForTask = agentChatSelectedSessionId; if ( !projectPathForChat || !agent || !runId || !actionId || agentChatBusy || agentChatBackgroundBusy ) { return; } if (selectedSession && selectedSession.archivedAt !== null) { setAgentChatStatus('已归档会话不能拒绝工具动作'); return; } const llmWarning = getCurrentAgentChatLlmWarning(agent); if (llmWarning) { setAgentChatStatus(llmWarning); return; } const invoke = resolveTauriInvoke(); if (!invoke) { setAgentChatStatus('需要在 Tauri App 内运行'); return; } const saveVersion = agentChatLoadVersionRef.current + 1; agentChatLoadVersionRef.current = saveVersion; setAgentChatBackgroundBusy(true); setAgentChatStatus('正在拒绝工具动作并继续 Agent 后台任务'); try { const runtime = await invoke( 'reject_game_creator_agent_runtime_task', { projectPath: projectPathForChat, agentId: agent.id, runId, actionId, note: '开发者拒绝待执行工具动作', }, ); if (agentChatLoadVersionRef.current !== saveVersion) { return; } const runtimeState = agentRuntimeStateFromResult(runtime); setAgentChatRuntime(runtimeState); setAgentChatActiveRuntime(runtimeState); setAgentChatGoal((current) => mergeAgentGoalRecordFromRuntime(current, runtimeState), ); setAgentChatRuntimeError(''); const conversation = await invoke( 'read_local_conversation', { projectPath: projectPathForChat, agentId: agent.id, ...agentChatSessionInvokeArgs(sessionIdForTask), }, ); if (agentChatLoadVersionRef.current !== saveVersion) { return; } setAgentChatMessages(conversation.messages); setAgentChatStatus(agentRuntimeStartStatus(runtime)); } catch (error) { if (agentChatLoadVersionRef.current !== saveVersion) { return; } setAgentChatStatus( error instanceof Error ? error.message : String(error), ); } finally { if (agentChatLoadVersionRef.current === saveVersion) { setAgentChatBackgroundBusy(false); } } } async function handleAgentChatSubmitUserInput( request: AgentRuntimeUserInputRequest, responseId: string, answers: Record, ) { const projectPathForChat = validateAgentChatProjectPath(); const agent = selectedLauncherAgentChatAgent(); const selectedSession = selectedLauncherAgentChatSession(); const sessionIdForTask = agentChatSelectedSessionId; const currentRequest = agentChatRuntime?.userInputRequest; if ( !projectPathForChat || !agent || !sessionIdForTask || !responseId || agentChatBusy || agentChatBackgroundBusy ) { return; } if (selectedSession && selectedSession.archivedAt !== null) { setAgentChatStatus('已归档会话不能回答 Agent 问题'); return; } if ( request.agentId !== agent.id || request.sessionId !== sessionIdForTask || request.runId !== agentChatRuntime?.runId || currentRequest?.requestId !== request.requestId || currentRequest?.actionId !== request.actionId ) { setAgentChatRuntimeError('待回答请求已变更,请刷新 Runtime 状态'); return; } const invoke = resolveTauriInvoke(); if (!invoke) { setAgentChatStatus('需要在 Tauri App 内运行'); return; } const saveVersion = agentChatLoadVersionRef.current + 1; agentChatLoadVersionRef.current = saveVersion; const previousPendingRun = agentChatPendingRuntimeRunRef.current; setAgentChatPendingRuntimeRun({ projectPath: projectPathForChat, agentId: agent.id, sessionId: sessionIdForTask, runId: request.runId, messageCount: agentChatMessages.length, }); setAgentChatBackgroundBusy(true); setAgentChatRuntimeError(''); setAgentChatStatus('正在提交回答并继续当前 Run'); try { const result = await invoke( 'answer_game_creator_agent_runtime_user_input', { projectPath: projectPathForChat, agentId: agent.id, runId: request.runId, actionId: request.actionId, requestId: request.requestId, responseId, answers, }, ); if (agentChatLoadVersionRef.current !== saveVersion) { return; } const runtimeState = agentRuntimeStateFromResult( result, agentChatRuntime, ); if ( runtimeState.agentId !== agent.id || runtimeState.sessionId !== sessionIdForTask || runtimeState.runId !== request.runId ) { throw new Error('Agent 回答后 Runtime 身份不匹配'); } setAgentChatRuntime(runtimeState); if ( agentChatActiveSessionIdRef.current === null || agentChatActiveSessionIdRef.current === sessionIdForTask ) { setAgentChatActiveRuntime(runtimeState); } setAgentChatGoal((current) => mergeAgentGoalRecordFromRuntime(current, runtimeState), ); const conversation = await invoke( 'read_local_conversation', { projectPath: projectPathForChat, agentId: agent.id, sessionId: sessionIdForTask, }, ); if (agentChatLoadVersionRef.current !== saveVersion) { return; } setAgentChatMessages(conversation.messages); setAgentChatConversationPath(conversation.path); updateAgentChatSessionMessageCount( sessionIdForTask, conversation.messages.length, ); setAgentChatPendingRuntimeRun( isAgentRuntimeTerminalState(runtimeState) ? null : { projectPath: projectPathForChat, agentId: agent.id, sessionId: sessionIdForTask, runId: request.runId, messageCount: conversation.messages.length, }, ); setAgentChatRuntimeError(''); setAgentChatStatus(agentRuntimeConversationStatus(runtimeState)); } catch (error) { if (agentChatLoadVersionRef.current !== saveVersion) { return; } setAgentChatPendingRuntimeRun(previousPendingRun); const message = error instanceof Error ? error.message : String(error); setAgentChatRuntimeError(message); setAgentChatStatus(`回答提交失败:${message}`); } finally { if (agentChatLoadVersionRef.current === saveVersion) { setAgentChatBackgroundBusy(false); } } } return { openAgentChatGoalDialog, handleAgentChatGoalDialogSubmit, handleAgentChatGoalControl, handleAgentChatCompactContext, handleAgentChatCancelRuntimeTask, handleAgentChatRetryRuntimeTask, handleAgentChatConfirmRuntimeTask, handleAgentChatRejectRuntimeTask, handleAgentChatSubmitUserInput, }; }