补充下一步建议命令

新增聊天侧next命令基于当前状态给出安全草稿建议

补充主窗口下一步建议测试和帮助命令覆盖

同步AI游戏创作App技术方案和共享决策记录
This commit is contained in:
AIGameCreator App
2026-07-03 04:05:42 +08:00
parent b8cb088056
commit 6992dede5b
4 changed files with 115 additions and 1 deletions
+90
View File
@@ -1825,6 +1825,7 @@ const chatCommandHelp = [
'/capabilities:查看 Agent 能力清单',
'/audit:审计当前项目的 Agent 能力证据',
'/status:查看项目状态',
'/next:查看下一步建议',
'/open-project:在系统文件管理器中显示项目目录',
'/switch-project:回到项目启动器切换工作区',
'/index:刷新本地项目索引',
@@ -1972,6 +1973,78 @@ function summarizeProjectStatus(
.join('\n');
}
function summarizeNextProjectActions(
nextManifest: GameCreationAppManifest,
trace: GameCreationAgentRunTrace | null,
) {
const suggestions: Array<{ label: string; command?: string }> = [];
const addSuggestion = (label: string, command?: string) => {
if (command && suggestions.some((item) => item.command === command)) {
return;
}
suggestions.push({ label, command });
};
const preview = nextManifest.preview;
if (!trace) {
addSuggestion('直接输入一句游戏需求,确认后生成首版原型');
} else if (
trace.lifecycleStatus === 'killed' ||
trace.status === 'failed' ||
trace.stopReason === 'max-passes-exhausted'
) {
addSuggestion('补充说明并继续最近 run', '/agent-resume ');
} else if (
trace.status === 'passed' ||
trace.status === 'artifacts-written' ||
trace.stopReason === 'evaluator-passed'
) {
addSuggestion(
preview?.status === 'running' && preview.url
? '打开当前本地预览'
: '运行自检并启动本地预览',
preview?.status === 'running' && preview.url ? '/open-preview' : '/run',
);
} else {
addSuggestion('查看最近 loop 进展', '/trace');
}
const readyTasks = selectGameCreationAppReadyTasks({
tasks: taskRowsFromManifest(nextManifest),
});
if (readyTasks.length > 0) {
addSuggestion(`查看 ${readyTasks.length} 个 ready 任务`, '/tasks');
} else {
addSuggestion('查看任务拆分和等待项', '/tasks');
}
if (nextManifest.assets.length > 0) {
addSuggestion(`查看 ${nextManifest.assets.length} 个本地资产`, '/assets');
} else {
addSuggestion(
'登记本地素材或同步画板资源',
'/asset-register assets/hero.png image image/png',
);
addSuggestion('同步已有画板项目资源', '/sync-canvas-project ');
}
if (trace) {
addSuggestion('查看最近 trace 摘要', '/trace');
addSuggestion('列出最近 Run 产物', '/run-artifacts');
}
addSuggestion('打开产物命令列表', '/artifacts');
addSuggestion('打开日志命令列表', '/logs');
const firstCommand = suggestions.find((item) => item.command);
return {
text: `下一步建议:\n${suggestions
.map((item) => `- ${item.label}${item.command ? `:${item.command}` : ''}`)
.join('\n')}`,
draftCommand: firstCommand?.command,
draftCommandLabel: firstCommand?.label,
};
}
function summarizeMainProjectHeader(
nextManifest: GameCreationAppManifest,
agents: AgentStatusCard[],
@@ -5215,6 +5288,23 @@ export function App() {
return;
}
if (prompt === '/next') {
if (!requireChatProjectForUserAction()) {
return;
}
const summary = summarizeNextProjectActions(manifest, agentRunTrace);
setMessages((current) => [
...current,
{
role: 'assistant',
text: summary.text,
draftCommand: summary.draftCommand,
draftCommandLabel: summary.draftCommandLabel,
},
]);
return;
}
if (prompt === '/index') {
void queueOrExecuteProjectIndex();
return;
@@ -2119,6 +2119,27 @@ describe('AI 游戏创作 App 界面边界', () => {
expect(await screen.findByText(/项目:未命名游戏原型/)).not.toBeNull();
expect(screen.getByText(/目录:\/tmp\/authorized-game/)).not.toBeNull();
const runLocalCountBeforeNext = invoke.mock.calls.filter(
([command]) => command === 'run_limited_local_command',
).length;
submitChat('/next');
expect(await screen.findByText(/下一步建议:/)).not.toBeNull();
expect(screen.getByText(/运行自检并启动本地预览:\/run/)).not.toBeNull();
expect(screen.getByText(/查看 .* 个 ready 任务:\/tasks/)).not.toBeNull();
const nextMessageList = document.querySelector('.message-list');
expect(nextMessageList).not.toBeNull();
fireEvent.click(
within(nextMessageList as HTMLElement).getByRole('button', {
name: '运行自检并启动本地预览',
}),
);
expect(screen.getByLabelText('创作想法')).toHaveProperty('value', '/run');
expect(
invoke.mock.calls.filter(
([command]) => command === 'run_limited_local_command',
),
).toHaveLength(runLocalCountBeforeNext);
fireEvent.click(screen.getByRole('button', { name: '权限' }));
expect(
await screen.findByText(/策略:\.agent\/policy\.json/),
@@ -7675,6 +7696,7 @@ describe('AI 游戏创作 App 界面边界', () => {
expect(
screen.getByText(/\/switch-project:回到项目启动器切换工作区/),
).not.toBeNull();
expect(screen.getByText(/\/next:查看下一步建议/)).not.toBeNull();
expect(
screen.getByText(
/\/asset-register 路径 \[kind\] \[mediaType\]:登记项目内已有资产/,