Files
Genarrative/apps/ai-game-creator-shell/tests/appSurface/project-conversation.suite.ts
k88936 6106b4e67c 退役AGC项目对话斜杠命令与终端swarm chat入口:应用与Rust实现删除
- 删除应用侧 /history 精确匹配分支与 reloadHistory、chatPromptPolish 的 / 前缀绕过、chatCommandMetadata、memoryCommands、projectSummaryConstants 命令清单
- 删除只服务退役摘要面板的 project-summary/*Summaries.ts 与 agentTrace.ts 及对应测试
- 删除 /sync-canvas-project、/read、/trace 草稿回填死链(agentPresentation.ts 与 Rust suggested_canvas_tool_call)
- 删除无人调用的 Tauri 命令 get_game_creation_agent_capabilities 与 get_limited_local_commands
- 删除 --swarm-chat 入口、SwarmChat 变体、src/swarm_cli.rs 与整个 swarm_cli/ 目录
- 收敛 agent/interaction.rs 至自然语言 steer 决策路径,删除交互内核整层
- 删除 SWARM_TURN_*_ERROR、print_runtime_response_stream_status 及其专属测试
- 更新 ChatMarkdownMessage、chatPromptPolish、rememberCommand 与 appSurface 用例,移除斜杠命令断言
2026-09-23 11:12:39 +08:00

841 lines
31 KiB
TypeScript

import { directCodexUserItemFromContent } from '../../src/features/project-workspace/resourceReferences';
import {
directCodexPolicyRetryInput,
isDirectCodexTurnAlreadyRunningError,
} from '../../src/view/project-development/chat/conversation/directCodexConversation';
import {
createGameCreationAppManifest,
emptyProjectPolicy,
expect,
fireEvent,
it,
mockRoleAgentReply,
renderAppAt,
roleAgentMockReply,
screen,
vi,
waitFor,
within,
} from './harness';
export function registerProjectConversationTests() {
it('filters only the stable same-turn in-progress rejection from terminal Direct Codex failures', () => {
expect(
isDirectCodexTurnAlreadyRunningError(
new Error(
'direct-codex-turn-already-running: 当前 Direct 客户端回合仍在运行',
),
),
).toBe(true);
expect(
isDirectCodexTurnAlreadyRunningError(
'codex-app-server-error:unauthorized',
),
).toBe(false);
expect(
isDirectCodexTurnAlreadyRunningError(
'direct-codex-turn-already-running 当前回合失败',
),
).toBe(false);
});
it('carries the whole direct turn input, including @ references, into the policy-confirmation retry', () => {
// 确认 `conversation.write` 之后重跑的是同一轮输入:漏掉任何一项都会让用户
// 在确认之后拿到另一轮内容。历史缺陷正是漏了 canonical user item 里的 @ 引用
// (引用被静默丢掉),所以这里把「首轮入参整体带过去」钉成硬约束。
const firstTurn = {
clientTurnId: 'direct-turn-1',
creationType: 'game' as const,
userItem: directCodexUserItemFromContent(
[
{ type: 'input_text' as const, text: '用这张图改一下' },
{
type: 'agc_resource_reference' as const,
resourceId: 'reference-hero',
},
{
type: 'agc_attachment_reference' as const,
name: '角色草图.png',
mediaType: 'image/png',
size: 128,
localPath: '',
status: 'imported' as const,
},
],
'direct-turn-1:user',
),
};
expect(directCodexPolicyRetryInput(firstTurn)).toEqual({
...firstTurn,
directPolicyChecked: true,
});
// canonical content 是这一次输入的判别项,单独再断言一遍,避免上面整体相等
// 被未来字段扩展掩盖。
expect(directCodexPolicyRetryInput(firstTurn).userItem.content).toEqual(
firstTurn.userItem.content,
);
});
it.skip('requires confirmation before reading a specific agent conversation when policy asks for it', async () => {
const manifest = createGameCreationAppManifest(
'local-project-draft',
'未命名游戏原型',
);
const invoke = vi.fn(
async (command: string, args?: Record<string, unknown>) => {
if (command === 'set_agc_plugin_project_path') return null;
if (command === 'list_agc_plugins') return [];
if (command === 'append_local_permission_log') {
return {};
}
if (command === 'init_local_game_project') {
const projectPath = String(args?.projectPath ?? '');
return {
projectPath,
manifestPath: `${projectPath}/.agent/manifest.json`,
manifest,
};
}
if (command === 'read_project_permission_policy') {
return {
path: '.agent/policy.json',
policy: {
deniedCommands: [],
confirmCommands: ['conversation.read'],
},
};
}
if (command === 'read_local_conversation') {
return {
path: args?.agentId
? '/tmp/authorized-game/.agent/conversations/agents/design-director.jsonl'
: '/tmp/authorized-game/.agent/conversations/project.jsonl',
agentId: args?.agentId ?? null,
messages: [],
};
}
if (command === 'read_local_agent_memory') {
return {
taskId: args?.taskId,
path: '/tmp/authorized-game/memory/agents/design/director.md',
content: '',
exists: false,
};
}
if (command === 'read_local_project_file') {
throw new Error(
'读取文件元数据失败:/tmp/authorized-game/.agent/run.latest.json: No such file or directory (os error 2)',
);
}
if (command === 'list_local_project_files') {
return { projectPath: String(args?.projectPath ?? ''), files: [] };
}
throw new Error(`unexpected invoke ${command}`);
},
);
window.__TAURI__ = { core: { invoke } };
renderAppAt('/?main&projectPath=%2Ftmp%2Fauthorized-game');
invoke.mockClear();
fireEvent.click(screen.getByRole('button', { name: /拆解创作方向/ }));
expect(await screen.findByText('准备读取 Agent 对话。')).not.toBeNull();
expect(screen.getByText('conversation.read')).not.toBeNull();
expect(invoke).not.toHaveBeenCalledWith('read_local_conversation', {
projectPath: '/tmp/authorized-game',
agentId: 'design-director',
});
fireEvent.click(screen.getByRole('button', { name: '确认' }));
expect(
await screen.findByText(
'已读取 0 条:/tmp/authorized-game/.agent/conversations/agents/design-director.jsonl',
),
).not.toBeNull();
expect(invoke).toHaveBeenCalledWith('read_local_conversation', {
projectPath: '/tmp/authorized-game',
agentId: 'design-director',
});
});
it.skip('leaves the agent conversation panel usable after cancelling read confirmation', async () => {
const manifest = createGameCreationAppManifest(
'local-project-draft',
'未命名游戏原型',
);
const invoke = vi.fn(
async (command: string, args?: Record<string, unknown>) => {
if (command === 'set_agc_plugin_project_path') return null;
if (command === 'list_agc_plugins') return [];
if (command === 'append_local_permission_log') {
return {};
}
if (command === 'init_local_game_project') {
const projectPath = String(args?.projectPath ?? '');
return {
projectPath,
manifestPath: `${projectPath}/.agent/manifest.json`,
manifest,
};
}
if (command === 'read_project_permission_policy') {
return {
path: '.agent/policy.json',
policy: {
deniedCommands: [],
confirmCommands: ['conversation.read'],
},
};
}
if (command === 'read_local_conversation') {
return {
path: args?.agentId
? '/tmp/authorized-game/.agent/conversations/agents/design-director.jsonl'
: '/tmp/authorized-game/.agent/conversations/project.jsonl',
agentId: args?.agentId ?? null,
messages: [],
};
}
if (command === 'read_local_project_file') {
throw new Error(
'读取文件元数据失败:/tmp/authorized-game/.agent/run.latest.json: No such file or directory (os error 2)',
);
}
if (command === 'list_local_project_files') {
return { projectPath: String(args?.projectPath ?? ''), files: [] };
}
throw new Error(`unexpected invoke ${command}`);
},
);
window.__TAURI__ = { core: { invoke } };
renderAppAt('/?main&projectPath=%2Ftmp%2Fauthorized-game');
invoke.mockClear();
fireEvent.click(screen.getByRole('button', { name: /拆解创作方向/ }));
const conversationReadCommand =
await screen.findByText('conversation.read');
fireEvent.click(
within(
conversationReadCommand.closest('.pending-command') as HTMLElement,
).getByRole('button', { name: '取消' }),
);
await waitFor(() => {
expect(screen.queryByText('conversation.read')).toBeNull();
});
expect(screen.getAllByText('已取消读取 Agent 对话').length).toBeGreaterThan(
0,
);
expect(screen.getByText('暂无对话')).not.toBeNull();
expect(invoke).not.toHaveBeenCalledWith('read_local_conversation', {
projectPath: '/tmp/authorized-game',
agentId: 'design-director',
});
});
it.skip('keeps loaded agent conversation after cancelling private memory read confirmation', async () => {
const manifest = createGameCreationAppManifest(
'local-project-draft',
'未命名游戏原型',
);
const invoke = vi.fn(
async (command: string, args?: Record<string, unknown>) => {
if (command === 'append_local_permission_log') {
return {};
}
if (command === 'init_local_game_project') {
const projectPath = String(args?.projectPath ?? '');
return {
projectPath,
manifestPath: `${projectPath}/.agent/manifest.json`,
manifest,
};
}
if (command === 'read_project_permission_policy') {
return {
path: '.agent/policy.json',
policy: {
deniedCommands: [],
confirmCommands: ['memory.read'],
},
};
}
if (command === 'read_local_conversation') {
return {
path: args?.agentId
? '/tmp/authorized-game/.agent/conversations/agents/design-director.jsonl'
: '/tmp/authorized-game/.agent/conversations/project.jsonl',
agentId: args?.agentId ?? null,
messages: args?.agentId
? [
{
schemaVersion: 'game-creator-conversation.v1',
role: 'assistant',
content: '已读到 Agent 对话',
agentId: 'design-director',
updatedAt: 1,
},
]
: [],
};
}
if (command === 'read_local_agent_memory') {
throw new Error('should wait for memory confirmation');
}
if (command === 'read_local_project_file') {
throw new Error(
'读取文件元数据失败:/tmp/authorized-game/.agent/run.latest.json: No such file or directory (os error 2)',
);
}
if (command === 'list_local_project_files') {
return { projectPath: String(args?.projectPath ?? ''), files: [] };
}
throw new Error(`unexpected invoke ${command}`);
},
);
window.__TAURI__ = { core: { invoke } };
renderAppAt('/?main&projectPath=%2Ftmp%2Fauthorized-game');
invoke.mockClear();
fireEvent.click(screen.getByRole('button', { name: /拆解创作方向/ }));
expect(await screen.findByText('已读到 Agent 对话')).not.toBeNull();
const memoryReadCommand = await screen.findByText('memory.read');
fireEvent.click(
within(
memoryReadCommand.closest('.pending-command') as HTMLElement,
).getByRole('button', { name: '取消' }),
);
await waitFor(() => {
expect(screen.queryByText('memory.read')).toBeNull();
});
expect(screen.getByText('已读到 Agent 对话')).not.toBeNull();
expect(screen.getByLabelText('Agent 私有记忆').textContent).toContain(
'已取消读取 Agent 私有记忆',
);
expect(invoke).not.toHaveBeenCalledWith('read_local_agent_memory', {
projectPath: '/tmp/authorized-game',
taskId: 'design-director',
});
});
it.skip('does not show unsaved agent messages when persistence fails', async () => {
const manifest = createGameCreationAppManifest(
'local-project-draft',
'未命名游戏原型',
);
const invoke = vi.fn(
async (command: string, args?: Record<string, unknown>) => {
if (command === 'append_local_permission_log') {
return {};
}
if (command === 'init_local_game_project') {
const projectPath = String(args?.projectPath ?? '');
return {
projectPath,
manifestPath: `${projectPath}/.agent/manifest.json`,
manifest,
};
}
if (command === 'read_project_permission_policy') {
return emptyProjectPolicy();
}
if (command === 'read_local_conversation') {
return {
path: '/tmp/authorized-game/.agent/conversations/agents/design-director.jsonl',
agentId: args?.agentId,
messages: [],
};
}
if (command === 'read_local_agent_memory') {
return {
taskId: args?.taskId,
path: '/tmp/authorized-game/memory/agents/design/director.md',
content: '',
exists: false,
};
}
if (command === 'append_local_conversation_message') {
throw new Error('保存 Agent 对话失败');
}
if (command === 'read_local_project_file') {
throw new Error(
'读取文件元数据失败:/tmp/authorized-game/.agent/run.latest.json: No such file or directory (os error 2)',
);
}
if (command === 'list_local_project_files') {
return { projectPath: String(args?.projectPath ?? ''), files: [] };
}
throw new Error(`unexpected invoke ${command}`);
},
);
window.__TAURI__ = { core: { invoke } };
renderAppAt('/?main&projectPath=%2Ftmp%2Fauthorized-game');
fireEvent.click(screen.getByRole('button', { name: /拆解创作方向/ }));
const input = await screen.findByLabelText('Agent 对话内容');
fireEvent.change(input, { target: { value: '这条不应该显示成已保存' } });
fireEvent.submit(input.closest('form') as HTMLFormElement);
expect(await screen.findByText('保存 Agent 对话失败')).not.toBeNull();
expect(screen.getByText('暂无对话')).not.toBeNull();
expect(screen.queryByText('这条不应该显示成已保存')).toBeNull();
expect(screen.getByLabelText('Agent 对话内容')).toHaveProperty(
'value',
'这条不应该显示成已保存',
);
});
it.skip('keeps the saved user message visible when the local agent receipt fails', async () => {
const manifest = createGameCreationAppManifest(
'local-project-draft',
'未命名游戏原型',
);
const agentMessages: Array<{
schemaVersion: string;
role: 'user' | 'assistant';
content: string;
agentId: string | null;
updatedAt: number;
}> = [];
const invoke = vi.fn(
async (command: string, args?: Record<string, unknown>) => {
if (command === 'append_local_permission_log') {
return {};
}
if (command === 'init_local_game_project') {
const projectPath = String(args?.projectPath ?? '');
return {
projectPath,
manifestPath: `${projectPath}/.agent/manifest.json`,
manifest,
};
}
if (command === 'read_project_permission_policy') {
return emptyProjectPolicy();
}
if (command === 'read_local_conversation') {
return {
path: '/tmp/authorized-game/.agent/conversations/agents/design-director.jsonl',
agentId: args?.agentId,
messages: agentMessages,
};
}
if (command === 'read_local_agent_memory') {
return {
taskId: args?.taskId,
path: '/tmp/authorized-game/memory/agents/design/director.md',
content: '',
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;
};
agentMessages.push({
schemaVersion: 'game-creator-conversation.v1',
role: message.role,
content: message.content,
agentId: message.agentId,
updatedAt: 1,
});
return {
path: '/tmp/authorized-game/.agent/conversations/agents/design-director.jsonl',
agentId: args?.agentId,
messages: agentMessages,
};
}
if (command === 'read_local_project_file') {
throw new Error(
'读取文件元数据失败:/tmp/authorized-game/.agent/run.latest.json: No such file or directory (os error 2)',
);
}
if (command === 'list_local_project_files') {
return { projectPath: String(args?.projectPath ?? ''), files: [] };
}
throw new Error(`unexpected invoke ${command}`);
},
);
window.__TAURI__ = { core: { invoke } };
renderAppAt('/?main&projectPath=%2Ftmp%2Fauthorized-game');
fireEvent.click(screen.getByRole('button', { name: /拆解创作方向/ }));
const input = await screen.findByLabelText('Agent 对话内容');
fireEvent.change(input, { target: { value: '先保留这个方向' } });
fireEvent.submit(input.closest('form') as HTMLFormElement);
expect(
(
await screen.findAllByText(
/已保存用户消息;Agent 回复失败:Agent LLM 未配置/,
)
).length,
).toBeGreaterThan(0);
expect(screen.getByText('先保留这个方向')).not.toBeNull();
expect(screen.queryByText(roleAgentMockReply)).toBeNull();
expect(screen.getByLabelText('Agent 对话内容')).toHaveProperty('value', '');
});
it.skip('shows LLM configuration gaps in the project agent conversation before sending', async () => {
const manifest = createGameCreationAppManifest(
'local-project-draft',
'未命名游戏原型',
);
const invoke = vi.fn(
async (command: string, args?: Record<string, unknown>) => {
if (command === 'init_local_game_project') {
const projectPath = String(args?.projectPath ?? '');
return {
projectPath,
manifestPath: `${projectPath}/.agent/manifest.json`,
manifest,
};
}
if (command === 'append_local_permission_log') {
return {};
}
if (command === 'read_project_permission_policy') {
return emptyProjectPolicy();
}
if (command === 'check_game_creator_llm_config') {
return {
configured: false,
apiKeyPresent: false,
baseUrl: 'https://api.openai.com/v1',
model: 'gpt-4.1',
apiKind: 'openai_responses',
stream: false,
webSearchEnabled: false,
error:
'LLM 未配置:请在 game-creator.config.json 的 llm.apiKey 中设置 API Key',
agents: [
{
agentId: 'design-director',
label: '拆解创作方向',
configured: false,
apiKeyPresent: false,
baseUrl: 'https://api.openai.com/v1',
model: 'gpt-4.1',
apiKind: 'openai_responses',
stream: false,
webSearchEnabled: false,
error:
'LLM 未配置:请在 agentLlm.design-director.apiKey 中设置 API Key',
},
],
};
}
if (command === 'read_local_conversation') {
return {
path: args?.agentId
? '/tmp/authorized-game/.agent/conversations/agents/design-director.jsonl'
: '/tmp/authorized-game/.agent/conversations/project.jsonl',
agentId: args?.agentId ?? null,
messages: [],
};
}
if (command === 'read_local_agent_memory') {
return {
taskId: args?.taskId,
path: '/tmp/authorized-game/memory/agents/design/director.md',
content: '',
exists: false,
};
}
if (command === 'read_local_project_file') {
throw new Error(
'读取文件元数据失败:/tmp/authorized-game/.agent/run.latest.json: No such file or directory (os error 2)',
);
}
if (command === 'list_local_project_files') {
return { projectPath: String(args?.projectPath ?? ''), files: [] };
}
throw new Error(`unexpected invoke ${command}`);
},
);
window.__TAURI__ = { core: { invoke } };
renderAppAt('/?main&projectPath=%2Ftmp%2Fauthorized-game');
fireEvent.click(screen.getByRole('button', { name: /拆解创作方向/ }));
const agentDialog = await screen.findByLabelText('Agent 对话');
const warning = await within(agentDialog).findByRole('status');
expect(warning.textContent).toContain(
'当前 Agent 智能服务未就绪:官方智能服务暂不可用,请稍后重试',
);
expect(within(agentDialog).getByLabelText('Agent 对话内容')).toHaveProperty(
'disabled',
true,
);
expect(
within(agentDialog).getByRole('button', { name: '发送' }),
).toHaveProperty('disabled', true);
expect(invoke).not.toHaveBeenCalledWith(
'chat_with_game_creator_role_agent',
expect.anything(),
);
});
it.skip('reports Tauri availability when saving an agent conversation without invoke', async () => {
const manifest = createGameCreationAppManifest(
'local-project-draft',
'未命名游戏原型',
);
const invoke = vi.fn(
async (command: string, args?: Record<string, unknown>) => {
if (command === 'append_local_permission_log') {
return {};
}
if (command === 'init_local_game_project') {
const projectPath = String(args?.projectPath ?? '');
return {
projectPath,
manifestPath: `${projectPath}/.agent/manifest.json`,
manifest,
};
}
if (command === 'read_project_permission_policy') {
return emptyProjectPolicy();
}
if (command === 'read_local_conversation') {
return {
path: '/tmp/authorized-game/.agent/conversations/agents/design-director.jsonl',
agentId: args?.agentId,
messages: [],
};
}
if (command === 'read_local_agent_memory') {
return {
taskId: args?.taskId,
path: '/tmp/authorized-game/memory/agents/design/director.md',
content: '',
exists: false,
};
}
if (command === 'read_local_project_file') {
throw new Error(
'读取文件元数据失败:/tmp/authorized-game/.agent/run.latest.json: No such file or directory (os error 2)',
);
}
if (command === 'list_local_project_files') {
return { projectPath: String(args?.projectPath ?? ''), files: [] };
}
throw new Error(`unexpected invoke ${command}`);
},
);
window.__TAURI__ = { core: { invoke } };
renderAppAt('/?main&projectPath=%2Ftmp%2Fauthorized-game');
fireEvent.click(screen.getByRole('button', { name: /拆解创作方向/ }));
const input = await screen.findByLabelText('Agent 对话内容');
fireEvent.change(input, { target: { value: '确认运行环境提示' } });
delete window.__TAURI__;
fireEvent.submit(input.closest('form') as HTMLFormElement);
expect(await screen.findByText('需要在 Tauri App 内运行')).not.toBeNull();
expect(screen.queryByText('请先初始化本地项目')).toBeNull();
});
it.skip('falls back to a saved normal reply when the agent stream listener rejects', async () => {
const manifest = createGameCreationAppManifest(
'local-project-draft',
'未命名游戏原型',
);
const savedAgentMessages: Array<{
schemaVersion: string;
role: 'user' | 'assistant';
content: string;
agentId: string | null;
updatedAt: number;
}> = [];
const invoke = vi.fn(
async (command: string, args?: Record<string, unknown>) => {
if (command === 'append_local_permission_log') {
return {};
}
if (command === 'init_local_game_project') {
const projectPath = String(args?.projectPath ?? '');
return {
projectPath,
manifestPath: `${projectPath}/.agent/manifest.json`,
manifest,
};
}
if (command === 'read_project_permission_policy') {
return emptyProjectPolicy();
}
if (command === 'read_local_conversation') {
return {
path: '/tmp/authorized-game/.agent/conversations/agents/design-director.jsonl',
agentId: args?.agentId,
messages: savedAgentMessages,
};
}
if (command === 'read_local_agent_memory') {
return {
taskId: args?.taskId,
path: '/tmp/authorized-game/memory/agents/design/director.md',
content: '',
exists: false,
};
}
if (command === 'chat_with_game_creator_role_agent') {
return {
replyText: mockRoleAgentReply(),
};
}
if (command === 'append_local_conversation_message') {
const message = args?.message as {
role: 'user' | 'assistant';
content: string;
agentId: string | null;
};
savedAgentMessages.push({
schemaVersion: 'game-creator-conversation.v1',
role: message.role,
content: message.content,
agentId: message.agentId,
updatedAt: 1,
});
return {
path: '/tmp/authorized-game/.agent/conversations/agents/design-director.jsonl',
agentId: args?.agentId,
messages: savedAgentMessages,
};
}
if (command === 'read_local_project_file') {
throw new Error(
'读取文件元数据失败:/tmp/authorized-game/.agent/run.latest.json: No such file or directory (os error 2)',
);
}
if (command === 'list_local_project_files') {
return { projectPath: String(args?.projectPath ?? ''), files: [] };
}
throw new Error(`unexpected invoke ${command}`);
},
);
const listen = vi.fn(async (eventName: string) => {
if (
eventName === 'game-creator-agent-progress' ||
eventName === 'game-creator-agent-runtime-update'
) {
return vi.fn();
}
if (eventName === 'game-creator-role-agent-chat-stream') {
throw new Error('core:event:allow-listen denied');
}
throw new Error(`unexpected listen ${eventName}`);
});
window.__TAURI__ = { core: { invoke }, event: { listen } };
renderAppAt('/?main&projectPath=%2Ftmp%2Fauthorized-game');
fireEvent.click(screen.getByRole('button', { name: /拆解创作方向/ }));
const input = await screen.findByLabelText('Agent 对话内容');
fireEvent.change(input, { target: { value: '先记住这个方向' } });
fireEvent.submit(input.closest('form') as HTMLFormElement);
expect(await screen.findByText(/已保存 2 条/)).not.toBeNull();
expect(screen.getByText('先记住这个方向')).not.toBeNull();
expect(screen.getByText(roleAgentMockReply)).not.toBeNull();
expect(screen.getByLabelText('Agent 对话内容')).toHaveProperty('value', '');
expect(listen).toHaveBeenCalledWith(
'game-creator-role-agent-chat-stream',
expect.any(Function),
);
expect(invoke).toHaveBeenCalledWith('chat_with_game_creator_role_agent', {
projectPath: '/tmp/authorized-game',
agentId: 'design-director',
prompt: '先记住这个方向',
});
});
it.skip('clears stale agent messages when another agent conversation fails to load', async () => {
const manifest = createGameCreationAppManifest(
'local-project-draft',
'未命名游戏原型',
);
const invoke = vi.fn(
async (command: string, args?: Record<string, unknown>) => {
if (command === 'append_local_permission_log') {
return {};
}
if (command === 'init_local_game_project') {
const projectPath = String(args?.projectPath ?? '');
return {
projectPath,
manifestPath: `${projectPath}/.agent/manifest.json`,
manifest,
};
}
if (command === 'read_project_permission_policy') {
return emptyProjectPolicy();
}
if (command === 'resume_game_creator_agent_runtime_tasks') {
return [];
}
if (command === 'read_game_creator_agent_runtimes') {
return [];
}
if (command === 'read_local_conversation') {
if (args?.agentId === null) {
return {
path: '/tmp/authorized-game/.agent/conversations/project.jsonl',
agentId: null,
messages: [],
};
}
if (args?.agentId === 'design-director') {
return {
path: '/tmp/authorized-game/.agent/conversations/agents/design-director.jsonl',
agentId: 'design-director',
messages: [
{
schemaVersion: 'game-creator-conversation.v1',
role: 'user',
content: '旧 Agent 历史消息',
agentId: 'design-director',
updatedAt: 1,
},
],
};
}
throw new Error('读取 Agent 对话失败');
}
if (command === 'read_local_agent_memory') {
return {
taskId: args?.taskId,
path: `/tmp/authorized-game/memory/agents/${String(
args?.taskId ?? '',
)}.md`,
content: '',
exists: false,
};
}
if (command === 'read_local_project_file') {
throw new Error(
'读取文件元数据失败:/tmp/authorized-game/.agent/run.latest.json: No such file or directory (os error 2)',
);
}
if (command === 'list_local_project_files') {
return { projectPath: String(args?.projectPath ?? ''), files: [] };
}
throw new Error(`unexpected invoke ${command}`);
},
);
window.__TAURI__ = { core: { invoke } };
renderAppAt('/?main&projectPath=%2Ftmp%2Fauthorized-game');
fireEvent.click(screen.getByRole('button', { name: /拆解创作方向/ }));
expect(await screen.findByText('旧 Agent 历史消息')).not.toBeNull();
fireEvent.click(screen.getByRole('button', { name: '关闭' }));
fireEvent.click(screen.getByRole('button', { name: /确定视觉方向/ }));
expect(await screen.findByText('读取 Agent 对话失败')).not.toBeNull();
expect(screen.getByText('暂无对话')).not.toBeNull();
expect(screen.queryByText('旧 Agent 历史消息')).toBeNull();
});
}