Repository navigation
fix(server): middle-truncate provider handoff only on budget overflow - #431
Conversation
When deliverContextHandoffs would throw Insufficient context allowance, fall back to head+tail middle truncation plus t3_thread_search / t3_thread_read recall instead of hard-failing. Normal handoffs that fit the budget are unchanged.
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
Thread transfer impact
This comment will update automatically after the next completed run. |
Intentional upstream touch for overflow-only middle-truncate on provider handoff budget errors.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 61f35ae97e
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| let selected = trySelect(input.messages); | ||
| if (historyCost(selected.messages, selected.context) <= effectiveBudget) { | ||
| return selected; |
There was a problem hiding this comment.
Truncate messages before returning the fallback selection
When overflow is caused by an oversized history item, selectHistory simply omits that item until the result fits the 2,048-byte emergency budget, so this condition immediately returns without ever reaching truncatedMessages. If the result does not fit, the excess is in the context wrapper and truncating message bodies cannot fix it. Consequently, the advertised head-and-tail fallback never preserves any part of oversized messages; for example, the new 50,000-character test messages all produce an empty message list. Apply the per-message truncation before accepting the fallback selection.
Useful? React with 👍 / 👎.
| messages, | ||
| omittedItems, | ||
| budget, | ||
| threadId: String(input.providerThread.appThreadId ?? pending[0]!.threadId), |
There was a problem hiding this comment.
Preserve the source thread in overflow recall instructions
For a fork_delta_summary handoff, both providerThread.appThreadId and handoff.threadId identify the target thread, while handoff.history.coverage was built with the distinct source thread in prepareForkDelta. The overflow fallback discards that coverage and tells the provider to run t3_thread_read against the target, so when source messages are omitted—especially the all-oversized case—the provider cannot recover the transferred history from the supplied identifier. Derive the recall thread from the source messages/coverage or retain a bounded version of the original coverage.
Useful? React with 👍 / 👎.
Unexport handoffRecallCoverage; pass omittedItems ?? 0 into selectHistory.
Summary
When provider handoff delivery would hard-fail with Insufficient context allowance for the provider handoff (
ContextHandoffBudgetError), fall back to the fork-style middle-truncate path instead of blocking the switch.selectHistory; always keepst3_thread_search/t3_search_threadandt3_thread_readrecall instructions.HANDOFF_TRUNCATE_FALLBACK_BUDGET = 2048) so the switch can proceed (slight dip into reserved headroom).Repro thread:
215d6410-d777-4254-8a2d-f64fb3f1286c.Test plan
vp test runContextHandoffBudget.test.ts+ProviderFailure.test.ts(33 pass)ContextHandoffService.test.ts(3 pass)Do not merge until Phil says go.