fix(providers): backfill combo context limit from snapshot after cold start (#13000) - #13759
Merged
diegosouzapw merged 3 commits intoSep 16, 2026
Merged
Conversation
… start (#13000) Root cause was two-fold in @omniroute/opencode-plugin: (1) the static catalog builder (buildStaticProviderEntry, used by createOmniRouteConfigHook) computed a combo's limit.context purely as Math.min(member context_length) and never consulted the server-computed combo.computed_context_length field at all, unlike the dynamic hook's mapComboToModelV2; (2) even where computed_context_length IS consulted, a background refresh whose live /api/combos response comes back without the field (e.g. right after a restart, before the server finishes recomputing it) had no fallback to the last-known-good disk snapshot, so it silently overwrote a correct 245000 limit with the degraded Math.min(member) value (163840 in the reported case). Fix: buildStaticProviderEntry now prefers computed_context_length the same way mapComboToModelV2 does, and doRefresh() backfills a combo's missing/zero computed_context_length from warmSnapshot.rawCombos by id before caching/publishing/persisting, scoped to that single field only. Regression test: @omniroute/opencode-plugin/tests/issue-13000-cold-start-combo-limit.test.ts
…0-combo-context-limits-fallback-cold
…ack-cold (base-red fix #13747)
muhamadgalihsaputra
pushed a commit
to niyatna/NiyatnaRoute
that referenced
this pull request
Sep 27, 2026
… start (diegosouzapw#13000) (diegosouzapw#13759) Merged in the 2026-09-16 sweep of the maintainer's own open PRs, at the owner's explicit instruction. No push was made to the PR branch: the merge took the head as the owning session left it (verified OPEN, non-draft and MERGEABLE against the release tip immediately before merging).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #13000
Root cause (short)
Two gaps in
@omniroute/opencode-plugin(client library), both surfacing as the combocontext limit downgrading from the correct server-computed value (245000) to a raw
Math.min(member context_length)lower bound (163840) after a restart:buildStaticProviderEntry(the static-catalog builder used bycreateOmniRouteConfigHook, which is what actually publishes the combo'slimit.contexton this path) computed the combo limit purely as
Math.min(member context_length)andnever consulted
combo.computed_context_lengthat all — unlike the dynamic hook'smapComboToModelV2, which already had a "prefer computed_context_length" branch. This isa gap the original plan-file's root-cause analysis didn't catch (it assumed
buildStaticProviderEntryalready respected the field); confirmed by reproducing the bugagainst
createOmniRouteConfigHookand finding the backfill alone had zero effect untilthis was also fixed.
computed_context_lengthis consulted, a background refresh(
doRefresh()) whose live/api/combosresponse comes back without the field (e.g. rightafter a restart, before the server finishes recomputing it) had no fallback to the
last-known-good disk snapshot already sitting in scope (
warmSnapshot) — so it silentlyoverwrote a correct value with the degraded one.
Fix
buildStaticProviderEntry's combo-limit computation now preferscombo.computed_context_lengththe same waymapComboToModelV2does, falling back toMath.min(member context_length)only when the field is absent/0.doRefresh()backfills a combo's missing/zerocomputed_context_lengthfromwarmSnapshot.rawCombos(matched by comboid) before caching, publishing, and persistingthe refreshed block — scoped strictly to that one derived field; no other combo field
(
models/name/etc.) is ever overwritten with stale snapshot data.Regression test
@omniroute/opencode-plugin/tests/issue-13000-cold-start-combo-limit.test.ts(added to thepackage's
testscript inpackage.jsonsoopencode-plugin-ci.ymlactually runs it —that workflow lists test files explicitly).
RED (against unfixed code):
GREEN (after both fixes):
A second control test asserts the documented, non-regressive behavior for a pure cold start
with no prior disk snapshot: the
Math.min(member)fallback is still used (nothing tobackfill from).
Gates run
npx eslint --suppressions-location config/quality/eslint-suppressions.json <changed files>→ clean, no output.npx tsc --noEmit -p @omniroute/opencode-plugin/tsconfig.json→ clean, no output. (Thispackage has its own
tsconfig.json; it is not covered bytypecheck:coreorcheck:open-sse-typecheck.)node scripts/check/check-file-size.mjs→ only a pre-existing unrelated flag onopen-sse/utils/stream.ts(base drift, not touched by this PR).node scripts/check/check-complexity.mjs/check-cognitive-complexity.mjs→ notapplicable — both gates scan only
src/,open-sse/,electron/,bin/(
ESLINT_SCAN_DIRSinscripts/check/complexityEslintReport.mjs);@omniroute/*is out ofscope.
node scripts/check/check-test-discovery.mjs→ not applicable — the gate's own headercomment documents
@omniroute/* ficam fora do walk (têm CI próprio: opencode-*-ci.yml).Discovery for this package is instead the package's own
testscript, which this PR updatesto include the new test file.
cd @omniroute/opencode-plugin && npm test(full 25-file suite, now 26 with this PR) →368/369 passing (370 with this PR's 2 new tests, 369 unaffected pre-existing). The one
failure (
scaffold.test.ts) is a pre-existing environment gap unrelated to this change: thisworktree never ran
npm run build, sodist/index.jsdoesn't exist yet — confirmed byls distfailing before any of this PR's edits.Existing tests aligned
None — no existing assertion encoded the buggy contract, so nothing needed realignment.
Not covered here
/api/combositself ever omitscomputed_context_lengthserver-side for a combo with an explicit DB override, vs. the losshappening only in the plugin's own fetch) is left as documented follow-up, not blocking —
this fix protects the client either way.
@omniroute/opencode-plugin/package.json; checked recent precedent (b0557543,#12607,same class of fix) and this repo does not bump the package version per fix-PR.