Add provider handoff compaction on model switches#1911
Add provider handoff compaction on model switches#1911juliusmarminge wants to merge 2 commits intomainfrom
Conversation
- Compact the active thread before switching providers - Preserve context with a handoff summary in the next turn - Update orchestration and adapter tests for compaction
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 2 potential issues.
Bugbot Autofix prepared fixes for both issues found in the latest run.
- ✅ Fixed: Unguarded cache clear on mismatched provider session exit
- Added
shouldApplyThreadLifecycleguard to theclearTurnStateForSessioncall so it only runs when the exiting provider matches the active session, preventing a replaced provider's exit from wiping the new provider's turn caches.
- Added
- ✅ Fixed: Broad
looksLikeCompactionItemmatches any item with summary- Removed the overly broad
typeof record.summary === "string"fallback fromlooksLikeCompactionItem, keeping only the specificcompact_summaryandcompactSummarychecks that reliably identify compaction items.
- Removed the overly broad
Or push these changes by commenting:
@cursor push d4c9511f80
Preview (d4c9511f80)
diff --git a/apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.ts b/apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.ts
--- a/apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.ts
+++ b/apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.ts
@@ -1147,7 +1147,7 @@
}
}
- if (event.type === "session.exited") {
+ if (event.type === "session.exited" && shouldApplyThreadLifecycle) {
yield* clearTurnStateForSession(thread.id);
}
diff --git a/apps/server/src/provider/handoffSummary.ts b/apps/server/src/provider/handoffSummary.ts
--- a/apps/server/src/provider/handoffSummary.ts
+++ b/apps/server/src/provider/handoffSummary.ts
@@ -72,11 +72,7 @@
if (COMPACTION_TYPE_SNIPPETS.some((snippet) => type.includes(snippet))) {
return true;
}
- return (
- typeof record.compact_summary === "string" ||
- typeof record.compactSummary === "string" ||
- typeof record.summary === "string"
- );
+ return typeof record.compact_summary === "string" || typeof record.compactSummary === "string";
}
export function extractCompactionSummaryFromSnapshot(snapshot: {You can send follow-ups to the cloud agent here.
Reviewed by Cursor Bugbot for commit 84b54f7. Configure here.
|
|
||
| const shouldApplyRuntimeError = !STRICT_PROVIDER_LIFECYCLE_GUARD | ||
| ? true | ||
| : activeTurnId === null || eventTurnId === undefined || sameId(activeTurnId, eventTurnId); |
There was a problem hiding this comment.
Unguarded cache clear on mismatched provider session exit
High Severity
After a provider switch, the old provider's session.exited event is correctly blocked from updating thread session state by the new guard at lines 895–904 (via shouldApplyThreadLifecycle). However, clearTurnStateForSession at line 1150 runs unconditionally for any session.exited event, regardless of whether the event's provider matches the active session. When the replaced provider exits, this wipes the turn message/proposed-plan caches that may already belong to the new provider's in-progress turn.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 84b54f7. Configure here.
| typeof record.compactSummary === "string" || | ||
| typeof record.summary === "string" | ||
| ); | ||
| } |
There was a problem hiding this comment.
Broad looksLikeCompactionItem matches any item with summary
Medium Severity
looksLikeCompactionItem returns true for any object that has a summary property of type string (line 78). Since many regular thread items (e.g. tool results, assistant messages) commonly carry a summary field, this heuristic is overly broad and can misidentify non-compaction items as compaction items, extracting incorrect text as the handoff summary.
Reviewed by Cursor Bugbot for commit 84b54f7. Configure here.
ApprovabilityVerdict: Needs human review This PR introduces a new provider handoff feature with significant runtime behavior changes across orchestration, provider adapters, and UI. Two unresolved review comments identify potential bugs: a high-severity cache clearing issue during provider switches and a medium-severity heuristic issue in compaction summary extraction. You can customize Macroscope's approvability policy. Learn more. |



Summary
thread/compact/start.Testing
bun fmtbun lintbun typecheckbun run testNote
Medium Risk
Changes provider/session lifecycle by allowing mid-thread provider switching with compaction and handoff, which can impact routing, state correctness, and event ingestion across concurrent sessions.
Overview
Enables mid-thread provider switching by compacting the active provider thread, starting a new session on the target provider, and prepending a
<provider_handoff>summary to the next user turn.Adds a
compactThreadcapability across adapters andProviderService, plusstopSessionForProviderto cleanly terminate the replaced provider session without breaking the new active binding; updates runtime ingestion guards to ignore lifecycle/error events from non-active providers.Updates web chat logic to keep provider/model selection consistent during handoff and render
provider.handoff.*activities as dedicated transition banners, with expanded test coverage for the new handoff/compaction flow.Reviewed by Cursor Bugbot for commit 84b54f7. Bugbot is set up for automated code reviews on this repo. Configure here.
Note
Add provider handoff compaction when switching AI providers mid-thread
<provider_handoff>preamble containing the compaction summary.compactThreadoperation: Claude enqueues/compactand awaits aPostCompacthook callback (60s timeout); Codex triggersthread/compact/startand waits for athread/compactednotification.ProviderServicegainscompactThreadandstopSessionForProvidermethods to support provider-specific session teardown without disturbing other active bindings.provider.handoff.compactingandprovider.handoff.completedactivities, surfaced in the work log and rendered in the chat UI as a provider-to-provider transition pill with animated state indicators.deriveEffectiveComposerModelStateis fixed to ignore model selections from a different provider than the currently selected one, preventing cross-provider model bleedthrough.STRICT_PROVIDER_LIFECYCLE_GUARD.Macroscope summarized 84b54f7.