补充项目简报命令入口

新增聊天侧brief命令基于当前状态生成项目简报

补充帮助命令和主窗口简报入口测试

同步AI游戏创作App技术方案和共享决策记录
This commit is contained in:
AIGameCreator App
2026-07-03 04:12:49 +08:00
parent 6992dede5b
commit d046866c07
4 changed files with 84 additions and 2 deletions
+64
View File
@@ -1825,6 +1825,7 @@ const chatCommandHelp = [
'/capabilities:查看 Agent 能力清单',
'/audit:审计当前项目的 Agent 能力证据',
'/status:查看项目状态',
'/brief:生成当前项目简报',
'/next:查看下一步建议',
'/open-project:在系统文件管理器中显示项目目录',
'/switch-project:回到项目启动器切换工作区',
@@ -1973,6 +1974,52 @@ function summarizeProjectStatus(
.join('\n');
}
function summarizeProjectBrief(
nextManifest: GameCreationAppManifest,
nextProjectPath: string,
trace: GameCreationAgentRunTrace | null,
) {
const tasks = taskRowsFromManifest(nextManifest);
const completedCount = tasks.filter(
(task) => task.status === 'completed',
).length;
const failedCount = tasks.filter((task) => task.status === 'failed').length;
const readyCount = selectGameCreationAppReadyTasks({ tasks }).length;
const sourceCounts = nextManifest.assets.reduce(
(counts, asset) => {
counts[asset.source.kind] += 1;
return counts;
},
{ uploaded: 0, generated: 0, canvas: 0 },
);
const assetSummary =
nextManifest.assets.length > 0
? `${nextManifest.assets.length} 个 · 上传 ${sourceCounts.uploaded} / 生成 ${sourceCounts.generated} / 画板 ${sourceCounts.canvas}`
: '暂无';
const preview = nextManifest.preview;
const previewSummary =
preview?.status === 'running' && preview.url
? `运行中 ${preview.url}`
: preview
? previewStatusLabels[preview.status]
: '未启动';
const commandRuns = nextManifest.commandRuns ?? [];
const latestCommandRun = commandRuns[commandRuns.length - 1];
const runSummary = trace
? `${trace.runId} · ${trace.status}${
trace.lifecycleStatus ? ` / ${trace.lifecycleStatus}` : ''
} · ${trace.passes}/${trace.maxPasses} · ${trace.stopReason}`
: '暂无最近 run';
return `项目简报:\n- 项目:${nextManifest.name}\n- 目录:${nextProjectPath}\n- 任务:完成 ${completedCount}/${tasks.length} · ready ${readyCount} · 失败 ${failedCount}\n- 资产:${assetSummary}\n- 最近 Run${runSummary}\n- 预览:${previewSummary}\n- 最近命令:${
latestCommandRun
? `${latestCommandRun.commandId} · ${
latestCommandRun.status === 'completed' ? '完成' : '失败'
}`
: '暂无'
}`;
}
function summarizeNextProjectActions(
nextManifest: GameCreationAppManifest,
trace: GameCreationAgentRunTrace | null,
@@ -5288,6 +5335,23 @@ export function App() {
return;
}
if (prompt === '/brief') {
const nextProjectPath = requireChatProjectForUserAction();
if (!nextProjectPath) {
return;
}
setMessages((current) => [
...current,
{
role: 'assistant',
text: summarizeProjectBrief(manifest, nextProjectPath, agentRunTrace),
draftCommand: '/next',
draftCommandLabel: '查看下一步',
},
]);
return;
}
if (prompt === '/next') {
if (!requireChatProjectForUserAction()) {
return;
@@ -2119,6 +2119,21 @@ describe('AI 游戏创作 App 界面边界', () => {
expect(await screen.findByText(/项目:未命名游戏原型/)).not.toBeNull();
expect(screen.getByText(/目录:\/tmp\/authorized-game/)).not.toBeNull();
const manifestReadCountBeforeBrief = invoke.mock.calls.filter(
([command]) => command === 'get_local_game_manifest',
).length;
submitChat('/brief');
expect(await screen.findByText(/项目简报:/)).not.toBeNull();
expect(screen.getByText(/任务:完成 0\/16 · ready 1/)).not.toBeNull();
expect(screen.getByText(/最近 Runrun-main-shortcut-trace/)).not.toBeNull();
fireEvent.click(screen.getByRole('button', { name: '查看下一步' }));
expect(screen.getByLabelText('创作想法')).toHaveProperty('value', '/next');
expect(
invoke.mock.calls.filter(
([command]) => command === 'get_local_game_manifest',
),
).toHaveLength(manifestReadCountBeforeBrief);
const runLocalCountBeforeNext = invoke.mock.calls.filter(
([command]) => command === 'run_limited_local_command',
).length;
@@ -7696,6 +7711,7 @@ describe('AI 游戏创作 App 界面边界', () => {
expect(
screen.getByText(/\/switch-project:回到项目启动器切换工作区/),
).not.toBeNull();
expect(screen.getByText(/\/brief:生成当前项目简报/)).not.toBeNull();
expect(screen.getByText(/\/next:查看下一步建议/)).not.toBeNull();
expect(
screen.getByText(
@@ -3856,6 +3856,7 @@
- 2026-06-26 调整,2026-07-03 更新:AI 游戏创作 App 借鉴 Harbour 的控制平面思想,但不搬 Harbour 后台。最近 run 在 `.agent/run.latest.json` 增加可选 `lifecycleStatus`,并通过 `/agent-status``/agent-kill``/agent-retry``/agent-resume [说明]` 控制本地生命周期,写入 `.agent/activity.jsonl``.agent/output.jsonl``.agent/context.bundle.json`;聊天里的状态 / 控制结果可填入 `/read .agent/output.jsonl` 草稿继续查看 run 输出,但不直接读取文件或绕过 `file.read` 策略。v1 的 kill/retry/resume 只更新本地状态和上下文包,不伪装成能中断已发出的上游 LLM 请求;后续引入独立 runner 后再把 `pending` 接入 claim。
- 2026-07-03 调整:主窗口 Agent 状态栏新增“继续说明”,只把 `/agent-resume ` 填入聊天输入框,让用户补充说明后再走原确认流;策略快捷入口新增 project.index、asset.register、memory.write、preview.open、preview.stop、conversation.read 和 conversation.write 确认草稿,同样只填输入框,不直接写 `.agent/policy.json`
- 2026-07-03 调整:主窗口 header 常驻项目摘要只从当前已加载的 manifest / trace 派生任务完成数、ready 数、资产来源分布和最近命令结果;未选择工作区时不显示,不为了摘要额外触发 Tauri 读取或写入,也不把任务、文件、run history 或预览开发面板搬进普通用户窗口。
- 2026-07-03 调整:普通用户通过聊天输入 `/brief` 触发项目简报入口,只基于主窗口当前已加载的 manifest、最近 run trace、预览状态、资产数量和最近命令生成聊天内简报,并提供 `/next` 作为后续草稿;该入口不得触发 Tauri 读写、不得读取文件、不得启动或打开预览,也不得新增普通用户面板。
- 2026-07-03 调整:`/llm-status` 读取到的 agent 级 LLM 配置状态可回填到主窗口 Agent 状态列表、聊天侧 `/agents` 汇总和单 Agent 对话头部,显示 provider 类型、模型、流式开关和 API Key 是否已读取;密钥本体仍不能进入聊天、状态列表、manifest、trace 或本地项目文件。
- 2026-07-03 调整:开发窗口日志面板提供 `.agent/logs/command.log``.agent/logs/preview.log``.agent/logs/agent.log` 的只读查看入口,复用 `file.read` 授权策略;普通用户聊天输入 `/logs` 只列出这三个日志文件对应的 `/read ...` 草稿 / 命令并提供首个草稿,不直接读取日志,不新增普通用户日志面板,实际读取仍走聊天侧 `file.read`
- 2026-07-03 调整:单 Agent 对话面板允许用户把当前输入手动追加到该 agent 的 `memory/agents/<group>/<role>.md` 私有记忆;写入复用 `memory.write` 项目策略、项目锁和 Tauri 本地目录能力,不把普通对话流水自动混入私有记忆;聊天侧 `/agent-conversations``/agent-memories` 只列出同一批 Agent 对话与私有记忆读取命令并提供首个 `/read` 草稿,不直接读取文件。
File diff suppressed because one or more lines are too long