diff --git a/apps/ai-game-creator-shell/src/App.tsx b/apps/ai-game-creator-shell/src/App.tsx index a51c313ee..982cfd334 100644 --- a/apps/ai-game-creator-shell/src/App.tsx +++ b/apps/ai-game-creator-shell/src/App.tsx @@ -2938,12 +2938,20 @@ export function WorkspaceLauncher({ return; } if (savedUserResult) { - setAgentChatMessages(savedUserResult.messages); - setAgentChatStatus( - `已保存用户消息;Agent 回复失败:${ - error instanceof Error ? error.message : String(error) - }`, - ); + const message = `已保存用户消息;Agent 回复失败:${ + error instanceof Error ? error.message : String(error) + }`; + setAgentChatMessages([ + ...savedUserResult.messages, + { + schemaVersion: 'game-creator-conversation.v1', + role: 'assistant', + content: message, + agentId: null, + updatedAt: Date.now(), + }, + ]); + setAgentChatStatus(message); } else { setAgentChatInput(content); setAgentChatStatus(error instanceof Error ? error.message : String(error)); @@ -10552,10 +10560,6 @@ function summarizeAgentRunHistoryReadDrafts( : 'Run 历史读取命令:暂无已加载 run'; } -function localAgentConversationReceipt(agent: Pick) { - return `已记录给 ${agent.title}。下一次生成会把这条对话作为该 agent 的上下文读取。`; -} - function summarizeLlmConversation(trace: GameCreationAgentRunTrace) { const llmSteps = trace.steps.filter((step) => step.toolCalls.some((toolCall) => toolCall.toolId.startsWith('llm.')), @@ -12159,6 +12163,18 @@ export function App() { return; } setAgentConversationMessages(savedUserResult.messages); + setAgentConversationStatus('Agent 正在思考'); + const reply = await invoke( + 'chat_with_game_creator_role_agent', + { + projectPath: nextProjectPath, + agentId: agent.id, + prompt: content, + }, + ); + if (agentConversationLoadVersionRef.current !== saveVersion) { + return; + } const assistantResult = await invoke( 'append_local_conversation_message', { @@ -12166,7 +12182,7 @@ export function App() { agentId: agent.id, message: { role: 'assistant', - content: localAgentConversationReceipt(agent), + content: reply.replyText, agentId: null, }, }, @@ -12184,12 +12200,20 @@ export function App() { return; } if (savedUserResult) { - setAgentConversationMessages(savedUserResult.messages); - setAgentConversationStatus( - `已保存用户消息;Agent 回执失败:${ - error instanceof Error ? error.message : String(error) - }`, - ); + const message = `已保存用户消息;Agent 回复失败:${ + error instanceof Error ? error.message : String(error) + }`; + setAgentConversationMessages([ + ...savedUserResult.messages, + { + schemaVersion: 'game-creator-conversation.v1', + role: 'assistant', + content: message, + agentId: null, + updatedAt: Date.now(), + }, + ]); + setAgentConversationStatus(message); } else { setAgentConversationInput(content); setAgentConversationStatus( diff --git a/apps/ai-game-creator-shell/tests/appSurface.test.ts b/apps/ai-game-creator-shell/tests/appSurface.test.ts index 5e674b049..5afae6340 100644 --- a/apps/ai-game-creator-shell/tests/appSurface.test.ts +++ b/apps/ai-game-creator-shell/tests/appSurface.test.ts @@ -908,6 +908,11 @@ describe('AI 游戏创作 App 界面边界', () => { })), }; } + if (command === 'chat_with_game_creator_role_agent') { + return { + replyText: `Agent 真回复:${String(args?.prompt ?? '')}`, + }; + } if (command === 'append_local_conversation_message') { const message = args?.message as { role: 'user' | 'assistant' | 'tool'; @@ -925,11 +930,6 @@ describe('AI 游戏创作 App 界面边界', () => { })), }; } - if (command === 'chat_with_game_creator_role_agent') { - return { - replyText: `Agent 回复:${String(args?.prompt ?? '')}`, - }; - } throw new Error(`unexpected invoke ${command}`); }, ); @@ -959,7 +959,7 @@ describe('AI 游戏创作 App 界面边界', () => { ).not.toBeNull(); expect( await screen.findByText( - 'Agent 回复:请单独评估这个角色设定流程', + 'Agent 真回复:请单独评估这个角色设定流程', ), ).not.toBeNull(); expect(invoke).toHaveBeenCalledWith('append_local_conversation_message', { @@ -976,7 +976,7 @@ describe('AI 游戏创作 App 界面边界', () => { agentId: 'design-director', message: { role: 'assistant', - content: 'Agent 回复:请单独评估这个角色设定流程', + content: 'Agent 真回复:请单独评估这个角色设定流程', agentId: null, }, }); @@ -1215,6 +1215,11 @@ describe('AI 游戏创作 App 界面边界', () => { manifestPath: '/tmp/home-created-game/.agent/manifest.json', }; } + if (command === 'chat_with_game_creator_role_agent') { + return { + replyText: `Agent 真回复:${String(args?.prompt ?? '')}`, + }; + } if (command === 'append_local_conversation_message') { return { path: '.agent/conversations/project.jsonl', @@ -2278,6 +2283,11 @@ describe('AI 游戏创作 App 界面边界', () => { messages: [], }; } + if (command === 'chat_with_game_creator_role_agent') { + return { + replyText: `Agent 真回复:${String(args?.prompt ?? '')}`, + }; + } if (command === 'append_local_conversation_message') { return { path: '/tmp/authorized-game/.agent/conversations/project.jsonl', @@ -10637,6 +10647,11 @@ describe('AI 游戏创作 App 界面边界', () => { if (command === 'list_local_project_files') { return { projectPath: String(args?.projectPath ?? ''), files: [] }; } + if (command === 'chat_with_game_creator_role_agent') { + return { + replyText: `Agent 真回复:${String(args?.prompt ?? '')}`, + }; + } if (command === 'append_local_conversation_message') { appendAttempts += 1; const message = args?.message as { content: string }; @@ -11099,6 +11114,11 @@ describe('AI 游戏创作 App 界面边界', () => { ], }; } + if (command === 'chat_with_game_creator_role_agent') { + return { + replyText: `Agent 真回复:${String(args?.prompt ?? '')}`, + }; + } if (command === 'append_local_conversation_message') { const message = args?.message as { role: 'user' | 'assistant'; @@ -11157,7 +11177,7 @@ describe('AI 游戏创作 App 界面边界', () => { ).not.toBeNull(); expect( screen.getByText( - '已记录给 拆解创作方向。下一次生成会把这条对话作为该 agent 的上下文读取。', + 'Agent 真回复:优先保留轻量像素风', ), ).not.toBeNull(); expect(invoke).toHaveBeenCalledWith('read_local_conversation', { @@ -11198,11 +11218,15 @@ describe('AI 游戏创作 App 界面边界', () => { agentId: 'design-director', message: { role: 'assistant', - content: - '已记录给 拆解创作方向。下一次生成会把这条对话作为该 agent 的上下文读取。', + content: 'Agent 真回复:优先保留轻量像素风', agentId: null, }, }); + expect(invoke).toHaveBeenCalledWith('chat_with_game_creator_role_agent', { + projectPath: '/tmp/authorized-game', + agentId: 'design-director', + prompt: '优先保留轻量像素风', + }); fireEvent.change(screen.getByLabelText('Agent 对话内容'), { target: { value: '稳定结论:锅铲音效要跟随连击节奏' }, }); @@ -11551,6 +11575,11 @@ describe('AI 游戏创作 App 界面边界', () => { exists: false, }; } + if (command === 'chat_with_game_creator_role_agent') { + return { + replyText: `Agent 真回复:${String(args?.prompt ?? '')}`, + }; + } if (command === 'append_local_conversation_message') { const message = args?.message as { role: 'user' | 'assistant'; @@ -11608,7 +11637,7 @@ describe('AI 游戏创作 App 界面边界', () => { expect(screen.getByText('先记住这个方向')).not.toBeNull(); expect( screen.getByText( - '已记录给 拆解创作方向。下一次生成会把这条对话作为该 agent 的上下文读取。', + 'Agent 真回复:先记住这个方向', ), ).not.toBeNull(); expect(invoke).toHaveBeenCalledWith('append_local_conversation_message', { @@ -11625,11 +11654,15 @@ describe('AI 游戏创作 App 界面边界', () => { agentId: 'design-director', message: { role: 'assistant', - content: - '已记录给 拆解创作方向。下一次生成会把这条对话作为该 agent 的上下文读取。', + content: 'Agent 真回复:先记住这个方向', agentId: null, }, }); + expect(invoke).toHaveBeenCalledWith('chat_with_game_creator_role_agent', { + projectPath: '/tmp/authorized-game', + agentId: 'design-director', + prompt: '先记住这个方向', + }); }); it('shows agent conversation history in recent batches', async () => { @@ -11761,6 +11794,11 @@ describe('AI 游戏创作 App 界面边界', () => { exists: false, }; } + if (command === 'chat_with_game_creator_role_agent') { + return { + replyText: `Agent 真回复:${String(args?.prompt ?? '')}`, + }; + } if (command === 'append_local_conversation_message') { const message = args?.message as { role: 'user' | 'assistant'; @@ -11940,15 +11978,15 @@ describe('AI 游戏创作 App 界面边界', () => { exists: false, }; } + if (command === 'chat_with_game_creator_role_agent') { + throw new Error('Agent LLM 未配置'); + } if (command === 'append_local_conversation_message') { const message = args?.message as { role: 'user' | 'assistant'; content: string; agentId: string | null; }; - if (message.role === 'assistant') { - throw new Error('保存 Agent 回执失败'); - } agentMessages.push({ schemaVersion: 'game-creator-conversation.v1', role: message.role, @@ -11983,12 +12021,16 @@ describe('AI 游戏创作 App 界面边界', () => { fireEvent.submit(input.closest('form') as HTMLFormElement); expect( - await screen.findByText(/已保存用户消息;Agent 回执失败/), - ).not.toBeNull(); + ( + await screen.findAllByText( + /已保存用户消息;Agent 回复失败:Agent LLM 未配置/, + ) + ).length, + ).toBeGreaterThan(0); expect(screen.getByText('先保留这个方向')).not.toBeNull(); expect( screen.queryByText( - '已记录给 拆解创作方向。下一次生成会把这条对话作为该 agent 的上下文读取。', + 'Agent 真回复:先保留这个方向', ), ).toBeNull(); expect(screen.getByLabelText('Agent 对话内容')).toHaveProperty('value', ''); @@ -12098,6 +12140,11 @@ describe('AI 游戏创作 App 界面边界', () => { exists: false, }; } + if (command === 'chat_with_game_creator_role_agent') { + return { + replyText: `Agent 真回复:${String(args?.prompt ?? '')}`, + }; + } if (command === 'append_local_conversation_message') { const message = args?.message as { role: 'user' | 'assistant'; @@ -12141,7 +12188,7 @@ describe('AI 游戏创作 App 界面边界', () => { expect(screen.getByText('先记住这个方向')).not.toBeNull(); expect( screen.getByText( - '已记录给 拆解创作方向。下一次生成会把这条对话作为该 agent 的上下文读取。', + 'Agent 真回复:先记住这个方向', ), ).not.toBeNull(); expect(screen.getByLabelText('Agent 对话内容')).toHaveProperty('value', '');