fix(backend/copilot): warn and skip malformed tool-gap messages lacking tool_call_id

In both _session_messages_to_transcript (SDK path) and _append_gap_to_builder
(baseline path), silently skipping a tool message with no tool_call_id can
leave the TranscriptBuilder missing a tool_result entry, which would corrupt
the JSONL conversation tree used by --resume.  Replace the silent drop with an
explicit warning so the issue is visible in logs, making it easier to diagnose
data corruption rather than discovering it as a broken --resume session later.
This commit is contained in:
Zamil Majdy
2026-04-16 14:49:03 +07:00
parent add4f8386e
commit 8b9b2e0721
2 changed files with 26 additions and 10 deletions

View File

@@ -755,11 +755,19 @@ def _append_gap_to_builder(
# so the builder's entry count matches the gap length.
content_blocks.append({"type": "text", "text": ""})
builder.append_assistant(content_blocks=content_blocks)
elif msg.role == "tool" and msg.tool_call_id:
builder.append_tool_result(
tool_use_id=msg.tool_call_id,
content=msg.content or "",
)
elif msg.role == "tool":
if msg.tool_call_id:
builder.append_tool_result(
tool_use_id=msg.tool_call_id,
content=msg.content or "",
)
else:
# Malformed tool message — no tool_call_id to link to an
# assistant tool_use block. Skip to avoid an unmatched
# tool_result entry in the builder (which would confuse --resume).
logger.warning(
"[Baseline] Skipping tool gap message with no tool_call_id"
)
async def _load_prior_transcript(

View File

@@ -1228,11 +1228,19 @@ def _session_messages_to_transcript(messages: list[ChatMessage]) -> str:
)
if blocks:
builder.append_assistant(blocks)
elif msg.role == "tool" and msg.tool_call_id:
builder.append_tool_result(
tool_use_id=msg.tool_call_id,
content=msg.content or "",
)
elif msg.role == "tool":
if msg.tool_call_id:
builder.append_tool_result(
tool_use_id=msg.tool_call_id,
content=msg.content or "",
)
else:
# Malformed tool message — no tool_call_id to link to an
# assistant tool_use block. Skip to avoid an unmatched
# tool_result entry in the builder (which would confuse --resume).
logger.warning(
"[SDK] Skipping tool gap message with no tool_call_id"
)
return builder.to_jsonl()