Skip to content
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
4efa1c4
fix(copilot): set session_id on mode-switch T1 to enable --resume on …
majdyz Apr 15, 2026
df205b5
fix(backend/copilot): strip CLI session file to prevent auto-compacti…
majdyz Apr 15, 2026
d27d221
Merge branch 'master' of github.com:Significant-Gravitas/AutoGPT into…
majdyz Apr 15, 2026
5fccd8a
Merge branch 'master' of github.com:Significant-Gravitas/AutoGPT into…
majdyz Apr 15, 2026
af8a86e
refactor(backend/copilot): consolidate session storage to single GCS …
majdyz Apr 15, 2026
2ec20e7
fix(backend/copilot): address review comments cycle 1
majdyz Apr 15, 2026
6023d3e
fix(backend/copilot): use explicit side_effect list in download excep…
majdyz Apr 15, 2026
3e137eb
refactor(backend/copilot): pure-GCS restore/upload, disk I/O moves to…
majdyz Apr 15, 2026
95a90b9
chore: merge dev into fix/copilot-single-session-store
majdyz Apr 15, 2026
d6d4fd5
refactor(backend/copilot): unify transcript API — TranscriptDownload,…
majdyz Apr 15, 2026
9118d61
fix(backend/copilot): use backend.util.json in _append_gap_to_builder…
majdyz Apr 15, 2026
5b48782
fix(backend/copilot): address review cycle 2 — write stripped bytes, …
majdyz Apr 15, 2026
f3bf44c
refactor(backend/copilot): extract _restore_cli_session_for_turn to f…
majdyz Apr 15, 2026
7737b7c
fix(backend/copilot): fallback empty text block for empty-content gap…
majdyz Apr 15, 2026
2e92efa
test(backend/copilot): add TestDetectGap unit tests for detect_gap bo…
majdyz Apr 15, 2026
d30ff9e
test(backend/copilot): add coverage for mode field, gap-fill, and SDK…
majdyz Apr 15, 2026
bd2efed
fix(frontend): allow zooming out more in the builder (#12690)
chernistry Apr 15, 2026
f6a2a11
fix(backend/copilot): fix import sort order and black formatting in t…
majdyz Apr 15, 2026
5cdc7d1
Merge branch 'dev' of github.com:Significant-Gravitas/AutoGPT into fi…
majdyz Apr 15, 2026
e11e384
fix(backend/copilot): sanitize OSError path in write log, patch confi…
majdyz Apr 15, 2026
2c7ba36
fix(backend/copilot): use e.strerror in _read_cli_session_from_disk O…
majdyz Apr 15, 2026
0732fb6
fix(backend/copilot): update stale upload_cli_session/restore_cli_ses…
majdyz Apr 15, 2026
cbf71fd
fix(backend/copilot): skip --resume for DB-reconstructed transcripts
majdyz Apr 15, 2026
9415166
fix(backend/copilot): split broad except in _read_cli_session_from_di…
majdyz Apr 15, 2026
c3aaa1d
remove useless env
majdyz Apr 16, 2026
c305ce5
fix(backend/copilot): use JSONL coverage count as transcript watermark
majdyz Apr 16, 2026
dfa07d8
refactor(backend/copilot): unified transcript context — extract_conte…
majdyz Apr 16, 2026
d91cfb5
Merge branch 'master' into fix/copilot-single-session-store
majdyz Apr 16, 2026
0c3a158
fix(backend/copilot): set transcript_content on baseline restore, fix…
majdyz Apr 16, 2026
c263fbc
docs(backend/copilot): document tool_calls flattening in extract_cont…
majdyz Apr 16, 2026
7aef023
fix(backend/copilot): encode content to bytes in cmd_load upload_tran…
majdyz Apr 16, 2026
2f3003f
fix(backend/copilot): make upload_transcript atomic — sequential writ…
majdyz Apr 16, 2026
3fb63d7
remove: test screenshots accidentally cherry-picked
majdyz Apr 16, 2026
b05846d
fix(backend/copilot): narrow broad except, fix len unit, add invarian…
majdyz Apr 16, 2026
33a7b83
fix(backend/copilot): fix len(source) log metric, add retry comment, …
majdyz Apr 16, 2026
add4f83
fix(backend/copilot): fix lines-stripped metric, narrow exception, us…
majdyz Apr 16, 2026
8b9b2e0
fix(backend/copilot): warn and skip malformed tool-gap messages lacki…
majdyz Apr 16, 2026
44e070c
nit(backend/copilot): convert f-string to %-logging in _format_sdk_co…
majdyz Apr 16, 2026
427b592
fix(backend/copilot): run black formatter on service.py after lint fix
majdyz Apr 16, 2026
bb64e08
fix(backend/copilot): baseline always uploads when GCS has no transcript
majdyz Apr 16, 2026
872de0e
fix(backend/copilot): guard session.messages[-1] against empty list i…
majdyz Apr 16, 2026
532a1cb
fix(backend/copilot): use len(session.messages) watermark — eliminate…
majdyz Apr 16, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
123 changes: 78 additions & 45 deletions autogpt_platform/backend/backend/copilot/baseline/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,9 @@
STOP_REASON_END_TURN,
STOP_REASON_TOOL_USE,
TranscriptDownload,
detect_gap,
download_transcript,
strip_for_upload,
upload_transcript,
validate_transcript,
)
Expand Down Expand Up @@ -699,26 +701,6 @@ async def _compress_session_messages(
return messages


def is_transcript_stale(dl: TranscriptDownload | None, session_msg_count: int) -> bool:
"""Return ``True`` when a download doesn't cover the current session.

A transcript is stale when it has a known ``message_count`` and that
count doesn't reach ``session_msg_count - 1`` (i.e. the session has
already advanced beyond what the stored transcript captures).
Loading a stale transcript would silently drop intermediate turns,
so callers should treat stale as "skip load, skip upload".

An unknown ``message_count`` (``0``) is treated as **not stale**
because older transcripts uploaded before msg_count tracking
existed must still be usable.
"""
if dl is None:
return False
if not dl.message_count:
return False
return dl.message_count < session_msg_count - 1


def should_upload_transcript(
user_id: str | None, transcript_covers_prefix: bool
) -> bool:
Expand All @@ -732,47 +714,98 @@ def should_upload_transcript(
return bool(user_id) and transcript_covers_prefix


def _append_gap_to_builder(
Comment thread
majdyz marked this conversation as resolved.
gap: list[ChatMessage],
builder: TranscriptBuilder,
) -> None:
"""Append gap messages from chat-db into the TranscriptBuilder.

Converts ChatMessage (OpenAI format) to TranscriptBuilder entries
(Claude CLI JSONL format) so the uploaded transcript covers all turns.
"""
import orjson
Comment thread
majdyz marked this conversation as resolved.
Outdated

for msg in gap:
if msg.role == "user":
builder.append_user(msg.content or "")
elif msg.role == "assistant":
content_blocks: list[dict] = []
if msg.content:
content_blocks.append({"type": "text", "text": msg.content})
if msg.tool_calls:
for tc in msg.tool_calls:
fn = tc.get("function", {}) if isinstance(tc, dict) else {}
try:
input_data = orjson.loads(fn.get("arguments", "{}"))
except Exception:
input_data = {}
content_blocks.append({
"type": "tool_use",
"id": tc.get("id", "") if isinstance(tc, dict) else "",
"name": fn.get("name", "unknown"),
"input": input_data,
})
if content_blocks:
builder.append_assistant(content_blocks=content_blocks)
Comment thread
majdyz marked this conversation as resolved.
Outdated
elif msg.role == "tool" and msg.tool_call_id:
builder.append_tool_result(
tool_use_id=msg.tool_call_id,
content=msg.content or "",
)


async def _load_prior_transcript(
user_id: str,
session_id: str,
session_msg_count: int,
session_messages: list[ChatMessage],
transcript_builder: TranscriptBuilder,
) -> bool:
"""Download and load the prior transcript into ``transcript_builder``.
"""Download and load the prior CLI session into ``transcript_builder``.

Returns ``True`` when the loaded transcript fully covers the session
prefix; ``False`` otherwise (stale, missing, invalid, or download
error). Callers should suppress uploads when this returns ``False``
to avoid overwriting a more complete version in storage.
Returns ``True`` when the loaded session fully covers the session
prefix; ``False`` otherwise (missing, invalid, or download error).
Comment thread
majdyz marked this conversation as resolved.
Outdated
Callers should suppress uploads when this returns ``False`` to avoid
overwriting a more complete version in storage.
"""
try:
dl = await download_transcript(user_id, session_id, log_prefix="[Baseline]")
restore = await download_transcript(
user_id, session_id, log_prefix="[Baseline]"
)
except Exception as e:
logger.warning("[Baseline] Transcript download failed: %s", e)
logger.warning("[Baseline] Session restore failed: %s", e)
return False

if dl is None:
logger.debug("[Baseline] No transcript available")
if restore is None:
logger.debug("[Baseline] No CLI session available")
return False

if not validate_transcript(dl.content):
logger.warning("[Baseline] Downloaded transcript but invalid")
try:
raw_str = restore.content.decode("utf-8")
except UnicodeDecodeError:
logger.warning("[Baseline] CLI session content is not valid UTF-8")
return False

if is_transcript_stale(dl, session_msg_count):
logger.warning(
"[Baseline] Transcript stale: covers %d of %d messages, skipping",
dl.message_count,
session_msg_count,
)
stripped = strip_for_upload(raw_str)
if not validate_transcript(stripped):
logger.warning("[Baseline] CLI session content invalid after strip")
return False

transcript_builder.load_previous(dl.content, log_prefix="[Baseline]")
transcript_builder.load_previous(stripped, log_prefix="[Baseline]")
logger.info(
"[Baseline] Loaded transcript: %dB, msg_count=%d",
len(dl.content),
dl.message_count,
"[Baseline] Loaded CLI session: %dB, msg_count=%d",
len(restore.content),
restore.message_count,
)

gap = detect_gap(restore, session_messages)
if gap:
_append_gap_to_builder(gap, transcript_builder)
logger.info(
"[Baseline] Filled gap: loaded %d transcript msgs + %d gap msgs from DB",
restore.message_count,
len(gap),
)

return True


Expand Down Expand Up @@ -807,10 +840,10 @@ async def _upload_final_transcript(
upload_transcript(
user_id=user_id,
session_id=session_id,
content=content,
content=content.encode("utf-8"),
message_count=session_msg_count,
mode="baseline",
log_prefix="[Baseline]",
skip_strip=True,
)
)
_background_tasks.add(upload_task)
Expand Down Expand Up @@ -922,7 +955,7 @@ async def stream_chat_completion_baseline(
_load_prior_transcript(
user_id=user_id,
session_id=session_id,
session_msg_count=len(session.messages),
session_messages=session.messages,
transcript_builder=transcript_builder,
),
prompt_task,
Expand Down
Loading
Loading