Skip to content

feat(opencode): bound Responses headers wait with opt-in rotation budget - #14558

Merged
diegosouzapw merged 5 commits into
diegosouzapw:release/v3.8.51from
maxmad64bis:feat/opencode-headers-wait-rotation
Sep 24, 2026
Merged

diegosouzapw merged 5 commits into
diegosouzapw:release/v3.8.51from
maxmad64bis:feat/opencode-headers-wait-rotation

Conversation

@maxmad64bis

@maxmad64bis maxmad64bis commented Sep 22, 2026 •

Copy link
Copy Markdown
Contributor

⚠️ base-red inherited: #14547

Summary

No default change, off-by-default. A streamed Responses call that waits for upstream response headers no longer holds the full headers window when another account is still available: an opt-in per-attempt budget (OPENCODE_RESPONSES_HEADERS_WAIT_MS, 0 = off, suggested 30000, max 2 rotations via OPENCODE_RESPONSES_HEADERS_WAIT_MAX_ROTATIONS) stops waiting on a queued request and moves on to the next account. No host scoping: the window only shortens the effective fetch-start ceiling, so the 600 s opencode-go registry cap neutralizes it there.

Related Issues

No linked issue — opt-in rotation budget for the Responses headers wait has no open tracker; #13484 (Responses first-byte stall rotation, merged) covers the post-headers phase, not the headers wait.

Validation

  • Change type: provider
  • Focused tests and category gates from the golden path
  • npm run lint — ESLint on the touched files is clean (open-sse/executors/opencode.ts, opencodeHeadersWait.ts, runtimeTimeouts.ts, rotation test); the full run is red on the base (🔴 Release branch not green: release/v3.8.51 #14547)
  • Reconciled with the current active release base; focused checks rerun afterward (rev-list HEAD..upstream/release/v3.8.51 = 0 @ 3a82bbe0)
  • Production-code changes include a new or updated automated test in this PR

Tests Added Or Updated

  • tests/unit/opencode-headers-wait-rotation.test.ts — 17 cases (getters, window policy incl. chat/completions untouched, race ok/expired/aborted, budget/last-account, abort without rotation, no-op off-by-default, seam rotation on delayed headers).

Coverage Notes

N/A — open-sse/ change covered by the new suite (17/17) plus neighbors: stall 14/14, egress-throttle 22/22, park-resume 8/8, transient-rotation 11/11, retry-delay 11/11, failure-predicate 6/6, chatcore-timeouts 7/7, body-read 6/6, body-integration 8/8.

Reviewer Notes

  • Rebaseline file-size (own growth, documented): open-sse/executors/opencode.ts 1301 → 1338 (irreducible seam: policy-once-per-request call plus headers-wait dispatch branch; bulk logic in new open-sse/executors/opencodeHeadersWait.ts, 210 lines under cap); the abort path releases the pacing slot via throwPacedError.
  • chat/completions and non-streamed calls never take the window (4 asserts); abort never rotates; the last account keeps the full ceiling.
  • Reconciled 2026-09-24: merged upstream/release/v3.8.51 @ 7d23bcf8 on top of the owner commits (3a82bbe0, no reset); single conflict in config/quality/file-size-baseline.json resolved by keeping both rebaseline keys; seam suite 17/17 locally after the merge.
  • Inherited (not caused by this PR), non-blocking: API Route Typecheck 4 ✗ (auggie.ts TS2769/TS18047, projectCombo.ts TS2459/TS2724), open-sse-typecheck 2 ✗ (same auggie.ts) + 1 ✗ chatCore.ts TS2304 from base feat(providers): correlate X-CPA-TRACE-ID auth_index with usage history #14544 (readCpaAuthIndex(providerResponse), diff $mb empty), dashboard-typecheck 1 ✗ (intelligentRouting.ts TS2698, diff $mb empty); Docs Gates migrations drift fixed by docs: migration count 178 -> 181 in README, AGENTS.md and llm.txt #14559 (soft drifts only); env-doc-sync (DEEP_HEALTH_CHECK_ENABLED) and mutation --strict (8 missing tap.testFiles) identical on the bare base.

Maintainer rework (merge-batch 2026-09-24)

  • Merged release/v3.8.51 (@d124bb78) into the branch with a real merge commit (08b5b1bb); no conflicts, your commit is untouched.
  • config/quality/file-size-baseline.json (85341381): the tip had shrunk open-sse/executors/opencode.ts to 1301 lines (gate count) under the old 1318 ceiling, so this PR's +37 seam lands at 1338, not 1355. The frozen ceiling is now the measured 1338 and the annotation carries the real numbers. I also restored the original position of the two neighbouring _rebaseline_2026_09_22_* keys that the branch had moved to the end of the file (a merge artifact, no content change).
  • Red→green: with the release-tip opencode.ts (keeping your runtimeTimeouts.ts / opencodeHeadersWait.ts), opencode-headers-wait-rotation is 15/17 — the two executor-seam cases (rotates past a queued Responses dispatch to a healthy account, a client abort during the bound window never rotates) fail; with this branch it is 17/17.
  • Neighbour suites (stall, transient rotation/retry-delay, 429 park-resume, egress throttle, executor, empty-rejection, park-marker, accounts-per-request, request-format race): all green except two failures that also fail with the release-tip sources and are not from this PR: opencode-executor → omits accept header when stream is false and opencode-transient-rotation → executor rotation lines carry correlationId.
  • Gates on the reconciled tree: typecheck:core (only the known inherited cliproxyAccountHealth.ts TS2322), check:open-sse-typecheck (only the known inherited auggie.ts TS18047), eslint with the frozen suppressions on the touched files, check:file-size measured after the commit — green. check:env-doc-sync has one inherited miss (DEEP_HEALTH_CHECK_ENABLED, absent from the tip's .env.example); your two new vars are documented in both files.

@maxmad64bis
maxmad64bis force-pushed the feat/opencode-headers-wait-rotation branch 2 times, most recently from 07bf010 to d7aef05 Compare September 22, 2026 22:02
@maxmad64bis
maxmad64bis marked this pull request as ready for review September 22, 2026 22:05
@maxmad64bis
maxmad64bis force-pushed the feat/opencode-headers-wait-rotation branch from d7aef05 to 11ec8da Compare September 22, 2026 23:05
No default change, off-by-default: without OPENCODE_RESPONSES_HEADERS_WAIT_MS
the dispatch path is untouched (window 0, no timer). When an operator sets a
positive window below the effective fetch-start ceiling, a streamed Responses
attempt stops waiting for upstream headers after the window and rotates to the
next account (budget OPENCODE_RESPONSES_HEADERS_WAIT_MAX_ROTATIONS, default 2);
the last remaining account always keeps the full headers window. Expiry reuses
the stall settle (slot release, cooldown, tried-set); client aborts propagate
and never rotate. Only shortens, never extends, the fetch-start ceiling.
@diegosouzapw

Copy link
Copy Markdown
Owner

Clean, well-scoped addition — off by default, restricted to streaming Responses
calls, and it reuses the existing stall-guard rotation machinery instead of
duplicating it. The pure policy functions (resolveHeadersWaitWindowMs,
headersWaitWaitMs) being separate from the dispatch wiring makes this easy to
reason about. Nothing blocking from my side — go ahead and merge once your own CI is
green (the fast-path failures on this PR match the currently inherited base-red,
#14547).

diegosouzapw and others added 4 commits September 24, 2026 02:26
…ase tip

The tip had shrunk open-sse/executors/opencode.ts to 1301 lines under the
old 1318 ceiling, so the headers-wait seam (+37) lands at 1338, not 1355.
Set the frozen ceiling to the measured 1338 and restore the original key
order of the neighbouring rebaseline annotations (the branch had moved two
of them to the end of the file as a merge artifact).
…ncode-headers-wait-rotation

Reconcile with the base tip: keep the opt-in headers-wait seam, take the base 429 quota curve and proxyFetch growth, keep both file-size rebaseline keys.
# Conflicts:
#	config/quality/file-size-baseline.json
@diegosouzapw
diegosouzapw merged commit 02bb598 into diegosouzapw:release/v3.8.51 Sep 24, 2026
4 of 7 checks passed
@maxmad64bis
maxmad64bis deleted the feat/opencode-headers-wait-rotation branch September 24, 2026 21:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants