fix(copilot): skip transcript upload when builder does not cover full session prefix

When transcript download fails or returns invalid content on a session with
prior messages, the transcript builder only contains the current turn. Uploading
it with message_count=len(session.messages) would overstate coverage, causing
_build_query_message to skip gap reconstruction on the next turn.

Add _transcript_covers_prefix flag that is set to False when download fails,
and check it before uploading to prevent partial transcripts from being stored
as if they covered the entire session history.
This commit is contained in:
Zamil Majdy
2026-03-14 23:48:54 +07:00
parent e17e1616d9
commit c4a51d2804

View File

@@ -864,6 +864,12 @@ async def stream_chat_completion_sdk(
resume_file: str | None = None
transcript_builder = TranscriptBuilder()
sdk_cwd = ""
# True when transcript_builder represents a full prefix of session history.
# First turn (<=1 prior message) is fully covered even without a download.
# Set to True when load_previous succeeds; stays False when download fails
# on a session with prior messages, preventing a partial upload that would
# mislead _build_query_message into skipping gap reconstruction next turn.
_transcript_covers_prefix = True
# Acquire stream lock to prevent concurrent streams to the same session
lock = AsyncClusterLock(
@@ -1002,12 +1008,14 @@ async def stream_chat_completion_sdk(
)
else:
logger.warning("%s Transcript downloaded but invalid", log_prefix)
_transcript_covers_prefix = False
elif config.claude_agent_use_resume and user_id and len(session.messages) > 1:
logger.warning(
"%s No transcript available (%d messages in session)",
log_prefix,
len(session.messages),
)
_transcript_covers_prefix = False
yield StreamStart(messageId=message_id, sessionId=session_id)
@@ -1719,6 +1727,14 @@ async def stream_chat_completion_sdk(
log_prefix,
entry_count,
)
elif not _transcript_covers_prefix:
logger.warning(
"%s Skipping transcript upload — builder does not "
"cover full session prefix (entries=%d, session=%d)",
log_prefix,
entry_count,
len(session.messages),
)
else:
logger.info(
"%s Uploading transcript (entries=%d, bytes=%d)",