diff --git a/apps/ai-game-creator-shell/src/view/project-development/chat/components/DirectProjectConversation/DirectProjectConversation.test.tsx b/apps/ai-game-creator-shell/src/view/project-development/chat/components/DirectProjectConversation/DirectProjectConversation.test.tsx
index 3dc7c91b2..c9409b1fb 100644
--- a/apps/ai-game-creator-shell/src/view/project-development/chat/components/DirectProjectConversation/DirectProjectConversation.test.tsx
+++ b/apps/ai-game-creator-shell/src/view/project-development/chat/components/DirectProjectConversation/DirectProjectConversation.test.tsx
@@ -204,6 +204,11 @@ describe('前插锚点的标记', () => {
't1:f',
'usage',
]);
+ expect(
+ view.container
+ .querySelector('[data-testid="turn-process"]')
+ ?.hasAttribute('open'),
+ ).toBe(true);
});
});
diff --git a/apps/ai-game-creator-shell/src/view/project-development/chat/components/DirectProjectConversation/DirectProjectTurn.tsx b/apps/ai-game-creator-shell/src/view/project-development/chat/components/DirectProjectConversation/DirectProjectTurn.tsx
index 047e5cf0f..fa901e0fb 100644
--- a/apps/ai-game-creator-shell/src/view/project-development/chat/components/DirectProjectConversation/DirectProjectTurn.tsx
+++ b/apps/ai-game-creator-shell/src/view/project-development/chat/components/DirectProjectConversation/DirectProjectTurn.tsx
@@ -76,6 +76,7 @@ function renderTurnProcess(turn: DirectChatTurn, streamingKey: string | null) {
data-testid="turn-process"
data-turn-key={turn.key}
data-block-key={PROCESS_BLOCK_KEY}
+ open
>
执行过程
{blocks}
diff --git a/apps/ai-game-creator-shell/src/view/project-development/chat/conversation/directThreadItemProjection.test.ts b/apps/ai-game-creator-shell/src/view/project-development/chat/conversation/directThreadItemProjection.test.ts
new file mode 100644
index 000000000..131b6dda5
--- /dev/null
+++ b/apps/ai-game-creator-shell/src/view/project-development/chat/conversation/directThreadItemProjection.test.ts
@@ -0,0 +1,38 @@
+import { describe, expect, it } from 'vitest';
+
+import { projectDirectThreadItem } from './directThreadItemProjection';
+
+describe('DirectProject 工具条目投影', () => {
+ it('CC 无参数、无输出的工具在开始和完成后都保留卡片', () => {
+ const started = projectDirectThreadItem(
+ {
+ itemType: 'mcpToolCall',
+ itemId: 'cc-tool-1',
+ tool: 'mcp__agc__read_project_context',
+ arguments: '',
+ output: null,
+ status: 'inProgress',
+ at: 1,
+ },
+ { startedAt: 2 },
+ );
+ const completed = projectDirectThreadItem(
+ {
+ itemType: 'mcpToolCall',
+ itemId: 'cc-tool-1',
+ tool: 'mcp__agc__read_project_context',
+ arguments: '',
+ output: null,
+ status: 'completed',
+ at: 3,
+ },
+ { completedAt: 4 },
+ );
+
+ expect(started?.kind).toBe('tool');
+ expect(started?.toolCall?.status).toBe('running');
+ expect(started?.toolCall?.summary).toBe('mcp__agc__read_project_context');
+ expect(completed?.kind).toBe('tool');
+ expect(completed?.toolCall?.status).toBe('completed');
+ });
+});
diff --git a/apps/ai-game-creator-shell/src/view/project-development/chat/conversation/directThreadItemProjection.ts b/apps/ai-game-creator-shell/src/view/project-development/chat/conversation/directThreadItemProjection.ts
index 2e09173fb..429f41912 100644
--- a/apps/ai-game-creator-shell/src/view/project-development/chat/conversation/directThreadItemProjection.ts
+++ b/apps/ai-game-creator-shell/src/view/project-development/chat/conversation/directThreadItemProjection.ts
@@ -173,9 +173,9 @@ function buildToolCard(
if (input.command && !input.outputOnly) detail.command = input.command;
if (input.output) detail.output = input.output;
if (changes.length > 0) detail.changes = changes;
- // 没有命令 / 输出 / 文件明细的条目不渲染成卡片:一张空卡片对用户没有信息量。
- if (!detail.command && !detail.output && !detail.changes?.length) return null;
-
+ // CC 的 MCP 工具可能在开始事件和完成事件里都没有可展开正文;工具名、状态和操作数
+ // 仍然是有效的过程证据,不能因为缺少输入/输出就把整张卡丢掉,否则实时、收口和历史
+ // 三条路径都会表现成“没有执行过程”。
const summarySource =
(input.kind === 'mcp_tool' ? (input.tool ?? '') : '') ||
detail.command ||
diff --git a/docs/technical/【技术方案】GameAgent对话工具调用卡片-2026-09-14.md b/docs/technical/【技术方案】GameAgent对话工具调用卡片-2026-09-14.md
index b47f28b1f..c1e801717 100644
--- a/docs/technical/【技术方案】GameAgent对话工具调用卡片-2026-09-14.md
+++ b/docs/technical/【技术方案】GameAgent对话工具调用卡片-2026-09-14.md
@@ -62,7 +62,7 @@
### 前端合并与渲染(回合唯一归属,连续工具成块)
- 加载对话时按历史条目进入 `project.jsonl` 的原始顺序投影:用户消息、文本与工具块保持原序,连续工具合为一块、遇到文本另起一块,不按 `turnId` 重新归并、也不再有 `seq` 交替。
-- 回合完成后,中间文本及所有工具块统一收进默认关闭的“执行过程”;最终回复及失败提示留在外面。展开后仍按原顺序查看中间输出和工具详情;运行中不使用外层折叠区。用户消息的发送时间从消息自身的历史时间读取,不能拿工具起点补造。
+- 回合完成后,中间文本及所有工具块统一收进默认展开的“执行过程”;最终回复及失败提示留在外面。用户仍可收起过程块,重开项目后过程默认再次可见;运行中不使用外层折叠区。用户消息的发送时间从消息自身的历史时间读取,不能拿工具起点补造。
- 实时与回读共用同一投影,正文、工具和耗时不另建实时/未归属渲染出口。先在完整历史按消息身份关联,再分页;禁止按第 N 个工具回合匹配第 N 条用户消息。详情通过当前回合 `callId` 关联;同项目回读与实时增量幂等合并,切项目清空旧状态。完整合同见 [AGC 实施计划](./【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md) 的“DirectProject 回合展示唯一归属”。
- 块 DOM 与交互(对齐 Codex):
@@ -105,7 +105,7 @@
- 当前 Agent 与策划 Agent 共用 `packages/shared` 的 `AgentMessageContent` 表现组件:正文为 14px / `--platform-text-strong`,思考、中间输出和工具调用为 12px / `--platform-text-soft`。实时与历史思考共用同一个折叠入口;工具输入输出继承过程色,失败状态保留错误色。Markdown 标题、表格及代码高亮在过程区同步弱化,最终回复和文档预览仍保留正常排版,不按 Agent 类型复制样式。输入提示与禁用状态保持原有反馈。
- Windows 命令展示:仅 `command` 卡片识别 `pwsh` / `powershell`(含完整路径、`.exe`、常见启动选项)的 `-Command` / `-c` 外层包装,摘要和展开输入只展示脚本正文,并解开单个 shell 参数的引用拼接。摘要优先读取已脱敏的 `detail.command`,再按首行 120 字符截断,避免历史摘要被可执行文件路径占满。无法识别的启动方式、`-File`、`-EncodedCommand`、普通命令和 MCP 输入原样展示;执行参数、持久化原文、脱敏和输出均不改变。
- 调试属性:块与行都带 `data-duration-ms`(原始毫秒,无法计算时为空串)与稳定 `data-testid`(块 `agent-tool-call-group`、行 `agent-tool-call-row`)。
-- 必须用 `