修重载对话后工具卡片消失(老项目回退路径)
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust smoke (pull_request) Has been cancelled
Project CI / AI game creator shell Rust crates (pull_request) Has been cancelled
Project CI / Backend tests (pull_request) Has been cancelled
Project CI / Native shell tests (pull_request) Has been cancelled
Project CI / Frontend tests (pull_request) Has been cancelled
Project CI / Repository checks (pull_request) Has been cancelled
Project CI / AI game creator shell web tests (pull_request) Has been cancelled

- 根因:没有 turn-stream.jsonl 的回合走回退路径,靠 direct-codex:<turnId>:assistant 合成 id 找锚点;老项目持久化的 assistant 消息 id 是 Codex 原始 id(如 0cef4af7-…),锚不上,工具调用被丢弃
- 修法:锚不上的工具按回合收集,渲染在消息列表末尾(按首个 startedAt 排序),绝不丢失
- 一并包含:文本段按"更长优先"合并(前后端两侧),修正文只剩前缀的问题
- tsc 0 错误、cargo build 0 error
This commit is contained in:
2026-09-16 00:53:38 +08:00
parent cae6006a96
commit 08eb475845
@@ -442,6 +442,9 @@ export function ProjectSupervisorView({
const toolCallsByAnchor = new Map<string, GameCreatorDirectToolCall[]>();
const liveToolCalls: GameCreatorDirectToolCall[] = [];
let liveToolCallTurnId = '';
// 老项目里持久化的 assistant 消息 id 是 Codex 原始 id(不是 `direct-codex:<turnId>:assistant`),
// 因此锚不上;这些工具的回合不能丢,统一收集后渲染在列表末尾。
const unanchoredToolCallsByTurn = new Map<string, GameCreatorDirectToolCall[]>();
// 正在跑的回合:它的流条目直接渲染在消息列表末尾,直到用户消息落盘、由那条消息接管。
const liveStreamTurnId = streamTurnId && turnStreamByTurn.has(streamTurnId)
? streamTurnId
@@ -472,9 +475,20 @@ export function ProjectSupervisorView({
liveToolCallTurnId = call.turnId;
}
liveToolCalls.push(call);
continue;
}
const bucket = unanchoredToolCallsByTurn.get(call.turnId) ?? [];
bucket.push(call);
unanchoredToolCallsByTurn.set(call.turnId, bucket);
}
}
const unanchoredToolCalls = [...unanchoredToolCallsByTurn.entries()]
.sort((left, right) => {
const leftAt = Math.min(...left[1].map((call) => call.startedAt || 0));
const rightAt = Math.min(...right[1].map((call) => call.startedAt || 0));
return leftAt - rightAt;
})
.map(([turnId, calls]) => ({ turnId, calls }));
// 该回合用户消息的 `updatedAt`:拿得到就在块头显示「发送 → 结束」,拿不到只显示结束时间。
const userMessageUpdatedAtForTurn = (turnId: string) => {
if (!turnId) {
@@ -738,6 +752,14 @@ export function ProjectSupervisorView({
</Fragment>
);
})}
{unanchoredToolCalls.map(({ turnId, calls }) => (
<ToolCallGroup
key={`unanchored-tools-${turnId}`}
calls={calls}
userSentAt={userMessageUpdatedAtForTurn(turnId)}
className="message-tool-call"
/>
))}
{liveToolCalls.length > 0 ? (
<ToolCallGroup
calls={liveToolCalls}