删除Direct打开项目自动重发测试
Project CI / Repository checks (pull_request) Failing after 10s
Project CI / Backend tests (pull_request) Failing after 10s
Project CI / Frontend tests (pull_request) Has been cancelled
Project CI / Native shell tests (pull_request) Has been cancelled

移除已废弃的hydrated Direct回合自动恢复场景。

保留当前新发送与历史回放语义的测试覆盖。
This commit is contained in:
2026-09-02 19:24:09 +08:00
parent b1a9a296e8
commit b136a7c346
@@ -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<Record<string, unknown>> = [
{
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<string, unknown>) => {
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<string, unknown>;
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<string, unknown> | 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<Record<string, unknown>> = [
{
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<string, unknown>) => {
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<string, unknown>;
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() {