From b136a7c3464598f4658f37ee2ac05a4507f956f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=BE=B7=E5=AE=87?= Date: Wed, 2 Sep 2026 19:24:09 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=A0=E9=99=A4Direct=E6=89=93=E5=BC=80?= =?UTF-8?q?=E9=A1=B9=E7=9B=AE=E8=87=AA=E5=8A=A8=E9=87=8D=E5=8F=91=E6=B5=8B?= =?UTF-8?q?=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 移除已废弃的hydrated Direct回合自动恢复场景。 保留当前新发送与历史回放语义的测试覆盖。 --- .../tests/appSurface/home.suite.ts | 297 ------------------ 1 file changed, 297 deletions(-) diff --git a/apps/ai-game-creator-shell/tests/appSurface/home.suite.ts b/apps/ai-game-creator-shell/tests/appSurface/home.suite.ts index a2fa4ed27..649d81d3f 100644 --- a/apps/ai-game-creator-shell/tests/appSurface/home.suite.ts +++ b/apps/ai-game-creator-shell/tests/appSurface/home.suite.ts @@ -2302,303 +2302,6 @@ export function registerHomeProjectCreationTests() { ), ).toHaveLength(1); }); - - it('releases a hydrated Direct Codex turn claim after an in-progress rejection so the same App can resume it later', async () => { - const projectPath = - 'C:\\Users\\tester\\Documents\\Genarrative GameAgent\\running-direct-project'; - const manifest = createGameCreationAppManifest( - 'running-direct-project', - '运行中直连项目', - ); - const stableTurnId = 'stable-running-turn-001'; - let directTurnCallCount = 0; - const persistedMessages: Array> = [ - { - schemaVersion: 'game-creator-conversation.v1', - role: 'user', - content: '继续完成运行中的项目', - agentId: null, - messageId: `direct-codex:${stableTurnId}:user`, - updatedAt: 1, - }, - ]; - const invoke = vi.fn( - async (command: string, args?: Record) => { - if (command === 'get_local_game_manifest') { - return manifest; - } - if (command === 'read_local_conversation') { - return { - path: `${projectPath}/.agent/conversations/project.jsonl`, - agentId: null, - sessionId: null, - messages: [...persistedMessages], - }; - } - if (command === 'append_local_permission_log') { - return {}; - } - if (command === 'read_project_permission_policy') { - return { - path: '.agent/policy.json', - policy: { deniedCommands: [], confirmCommands: [] }, - }; - } - if (command === 'append_local_conversation_message') { - const message = args?.message as Record; - const messageId = String(args?.messageId ?? ''); - if ( - !messageId || - !persistedMessages.some( - (candidate) => candidate.messageId === messageId, - ) - ) { - persistedMessages.push({ - schemaVersion: 'game-creator-conversation.v1', - ...message, - messageId, - updatedAt: Number( - message.updatedAt ?? persistedMessages.length + 1, - ), - }); - } - return { - path: `${projectPath}/.agent/conversations/project.jsonl`, - agentId: null, - sessionId: null, - messages: [...persistedMessages], - }; - } - if (command === 'chat_with_game_creator_direct_codex') { - directTurnCallCount += 1; - if (directTurnCallCount === 1) { - throw new Error( - 'direct-codex-turn-already-running: 当前 Direct 客户端回合仍在运行', - ); - } - return '恢复后的最终回复'; - } - throw new Error(`unexpected invoke ${command}`); - }, - ); - window.__TAURI__ = { core: { invoke } }; - - render( - React.createElement(App, { - initialProjectPath: projectPath, - initialProjectManifest: manifest, - projectSupervisorOnly: true, - }), - ); - - expect(await screen.findByText('继续完成运行中的项目')).not.toBeNull(); - await waitFor(() => { - expect(invoke).toHaveBeenCalledWith( - 'chat_with_game_creator_direct_codex', - { - projectPath, - prompt: '继续完成运行中的项目', - clientTurnId: stableTurnId, - }, - ); - }); - await act(async () => { - await Promise.resolve(); - await Promise.resolve(); - }); - expect(persistedMessages).toHaveLength(1); - expect( - invoke.mock.calls.filter( - ([command, args]) => - command === 'append_local_conversation_message' && - (args as Record | undefined)?.messageId === - `direct-codex:${stableTurnId}:assistant`, - ), - ).toHaveLength(0); - expect(screen.queryByText(/direct-codex-turn-already-running/)).toBeNull(); - - const directComposer = screen.getByLabelText('陶泥儿对话内容'); - fireEvent.change(directComposer, { target: { value: '/history' } }); - fireEvent.submit(directComposer.closest('form') as HTMLFormElement); - - expect(await screen.findByText('恢复后的最终回复')).not.toBeNull(); - await waitFor(() => { - expect(directTurnCallCount).toBe(2); - expect( - persistedMessages.filter( - (message) => - message.messageId === `direct-codex:${stableTurnId}:assistant`, - ), - ).toEqual([ - expect.objectContaining({ - role: 'assistant', - content: '恢复后的最终回复', - }), - ]); - }); - expect( - invoke.mock.calls.filter( - ([command]) => command === 'read_local_conversation', - ).length, - ).toBeGreaterThanOrEqual(2); - }); - - it.each([ - { - caseName: 'a successful reply', - firstError: null, - firstReply: '首次成功回复', - firstVisibleText: '首次成功回复', - }, - { - caseName: 'an ordinary error reply', - firstError: 'codex-app-server-error:unauthorized', - firstReply: null, - firstVisibleText: '陶泥儿智能创作 鉴权失败,请检查 API Key 或登录态', - }, - ])( - 'reconciles a hydrated Direct Codex claim after persisting $caseName fails', - async ({ firstError, firstReply, firstVisibleText }) => { - const projectPath = - 'C:\\Users\\tester\\Documents\\Genarrative GameAgent\\retry-terminal-persistence'; - const manifest = createGameCreationAppManifest( - 'retry-terminal-persistence', - '终态持久化重试项目', - ); - const stableTurnId = 'stable-terminal-persistence-001'; - let directTurnCallCount = 0; - let allowAssistantPersistence = false; - let failedAssistantPersistenceCount = 0; - const directTurnIds: string[] = []; - const persistedMessages: Array> = [ - { - schemaVersion: 'game-creator-conversation.v1', - role: 'user', - content: '恢复终态持久化失败的回合', - agentId: null, - messageId: `direct-codex:${stableTurnId}:user`, - updatedAt: 1, - }, - ]; - const invoke = vi.fn( - async (command: string, args?: Record) => { - if (command === 'get_local_game_manifest') { - return manifest; - } - if (command === 'read_local_conversation') { - return { - path: `${projectPath}/.agent/conversations/project.jsonl`, - agentId: null, - sessionId: null, - messages: [...persistedMessages], - }; - } - if (command === 'append_local_permission_log') { - return {}; - } - if (command === 'read_project_permission_policy') { - return { - path: '.agent/policy.json', - policy: { deniedCommands: [], confirmCommands: [] }, - }; - } - if (command === 'append_local_conversation_message') { - const message = args?.message as Record; - if (message.role === 'assistant' && !allowAssistantPersistence) { - failedAssistantPersistenceCount += 1; - throw new Error('assistant conversation persistence unavailable'); - } - const messageId = String(args?.messageId ?? ''); - if ( - !messageId || - !persistedMessages.some( - (candidate) => candidate.messageId === messageId, - ) - ) { - persistedMessages.push({ - schemaVersion: 'game-creator-conversation.v1', - ...message, - messageId, - updatedAt: Number( - message.updatedAt ?? persistedMessages.length + 1, - ), - }); - } - return { - path: `${projectPath}/.agent/conversations/project.jsonl`, - agentId: null, - sessionId: null, - messages: [...persistedMessages], - }; - } - if (command === 'chat_with_game_creator_direct_codex') { - directTurnCallCount += 1; - directTurnIds.push(String(args?.clientTurnId ?? '')); - if (directTurnCallCount === 1) { - if (firstError) { - throw new Error(firstError); - } - persistedMessages.push({ - schemaVersion: 'game-creator-conversation.v1', - role: 'assistant', - content: firstReply, - agentId: null, - messageId: `direct-codex:${stableTurnId}:assistant`, - updatedAt: 2, - }); - return firstReply ?? ''; - } - allowAssistantPersistence = true; - return '恢复后的最终回复'; - } - throw new Error(`unexpected invoke ${command}`); - }, - ); - window.__TAURI__ = { core: { invoke } }; - - render( - React.createElement(App, { - initialProjectPath: projectPath, - initialProjectManifest: manifest, - projectSupervisorOnly: true, - }), - ); - - expect(await screen.findByText(firstVisibleText)).not.toBeNull(); - await waitFor(() => { - expect(directTurnCallCount).toBe(1); - expect(failedAssistantPersistenceCount).toBeGreaterThan( - firstError ? 1 : 0, - ); - expect(persistedMessages).toHaveLength(firstError ? 1 : 2); - }); - - const directComposer = screen.getByLabelText('陶泥儿对话内容'); - fireEvent.change(directComposer, { target: { value: '/history' } }); - fireEvent.submit(directComposer.closest('form') as HTMLFormElement); - - expect( - await screen.findByText(firstError ? '恢复后的最终回复' : firstReply!), - ).not.toBeNull(); - await waitFor(() => { - expect(directTurnCallCount).toBe(firstError ? 2 : 1); - expect(directTurnIds).toEqual( - firstError ? [stableTurnId, stableTurnId] : [stableTurnId], - ); - expect( - persistedMessages.filter( - (message) => - message.messageId === `direct-codex:${stableTurnId}:assistant`, - ), - ).toEqual([ - expect.objectContaining({ - role: 'assistant', - content: firstError ? '恢复后的最终回复' : firstReply, - }), - ]); - }); - }, - ); } export function registerRecentProjectsTests() {