Skip to content

fix(sse): retry empty translated stream turns through the normal path - #14213

Merged
diegosouzapw merged 4 commits into
diegosouzapw:release/v3.8.51from
maxmad64bis:fix/flush-empty-retry
Sep 22, 2026
Merged

diegosouzapw merged 4 commits into
diegosouzapw:release/v3.8.51from
maxmad64bis:fix/flush-empty-retry

Conversation

@maxmad64bis

@maxmad64bis maxmad64bis commented Sep 19, 2026 •

Copy link
Copy Markdown
Contributor

⚠️ base-red inherited: #13866

Summary

Empty translated streaming turns (reasoning-only 200, zero-chunk 502, pre-first-byte drop, header-then-quiet stall) are retried through the normal credential path within an EMPTY_TURN_RETRY_MAX (4) budget, the stall once STREAM_READINESS_TIMEOUT_MS passes. Off by default behind FLUSH_EMPTY_RETRY_ENABLED; flag off = byte-identical path.

Related Issues

Validation

  • Change type: provider
  • Focused tests and category gates from the golden path
  • npm run lint
  • Reconciled with the current active release base; focused checks rerun afterward
  • Production-code changes include a new or updated automated test in this PR

Tests Added Or Updated

  • flush-empty-retry.test.ts (22: classifier, parity, four read outcomes, verdict, stall replay/passthrough, budget).
  • flush-empty-retry-hook.test.ts (7 through handleChat: flag off, served content, budget 1, no sibling fallback, drop, exhaustion).
  • feature-flags-settings.test.ts (counter 74 to 75).

Coverage Notes

  • emptyTurnRetry.ts via the classifier/parity/read-outcome cases; chatCore.ts hook via handleChat; streamEmptyChoices.ts via parity plus existing suites.

Reviewer Notes

  • Behaviour change: the bounded classification read carries the request readiness budget (caps per-chunk gap, never a productive turn; 0 keeps the unbounded read). A stalled turn with nothing usable replays; one with content passes through; mid-read throw takes the retry path. A disconnected client never costs another dispatch.
  • File-size rebaseline at this head (c15043036d): _rebaseline_2026_09_21_14213_empty_turn_retry_growth pins frozen[chatCore.ts]=6392 (gate count, +105 irreducible wiring; logic in new emptyTurnRetry.ts under the cap); gate green locally. TTFT cost when armed: small valid turn fully buffered; flag defaults off.
  • CI reds are inherited from the red base (🔴 Release branch not green: release/v3.8.51 #13866), not from this diff: the third-party PR fix(sse): treat antigravity empty completions with a normal stop as valid 200s (#14160) #14243 on the same base release/v3.8.51 fails the same 9 jobs (API Route Typecheck, Docs Gates, Fast Quality Gates, Merge integrity, ESLint, Unit fast-path 1-4/4); every file cited by the failing gates is outside this diff. Non-blocking for this PR.

@maxmad64bis
maxmad64bis force-pushed the fix/flush-empty-retry branch 4 times, most recently from 4ccc8e0 to 9300ebe Compare September 19, 2026 21:54
@maxmad64bis maxmad64bis changed the title fix(sse): retry once on another account on empty translated stream turn fix(sse): retry empty translated stream turns through the normal path Sep 19, 2026
@maxmad64bis
maxmad64bis marked this pull request as ready for review September 19, 2026 22:13
@maxmad64bis
maxmad64bis force-pushed the fix/flush-empty-retry branch 3 times, most recently from 961a99d to 9ef847d Compare September 20, 2026 12:05
# Conflicts:
#	config/quality/file-size-baseline.json
#	docs/reference/FEATURE_FLAGS.md
#	tests/unit/feature-flags-settings.test.ts
#	tests/unit/server-owned-tool-loop-flag.test.ts
# Conflicts:
#	config/quality/file-size-baseline.json
@diegosouzapw
diegosouzapw merged commit 8bf6b60 into diegosouzapw:release/v3.8.51 Sep 22, 2026
9 of 16 checks passed
diegosouzapw added a commit to maxmad64bis/OmniRoute that referenced this pull request Sep 22, 2026
…ter the diegosouzapw#14353/diegosouzapw#14213 merge

diegosouzapw#14353 moved the opencode member list off the shared instance, so the
rotation-attribution snapshot/skip enumeration now walks the per-request
list; opencode.ts settles at 1318. The registry gained
FLUSH_EMPTY_RETRY_ENABLED from diegosouzapw#14213, taking the catalog to 77 flags
(Network 19).
diegosouzapw added a commit that referenced this pull request Sep 22, 2026
… (Refs #13866)

All three reproduce on the pure release tip; none is this PR's defect except the
last, which is this PR's own measured growth.

- check:deps — "@opencode/plugin" is not in the dependency allowlist. #14370
  ported the opencode plugin to the v2 contract, which lives under a DIFFERENT
  scope from the already-approved "@opencode-ai/plugin". That scope change is
  exactly the slopsquatting shape this gate exists to catch, so it was verified
  before being allowlisted: npm shows both packages under the same maintainer
  (thdxr <d@ironbay.co>, who also publishes @opencode-ai/plugin), with
  @opencode/plugin created 2026-09-02. Legitimate v2 scope of the same publisher.
  The verification is recorded in the allowlist's _justifications entry.

- hard-session-lease-bypass-inventory — #14213's bounded empty-turn retry added a
  credential-resolution site in open-sse/handlers/chatCore.ts that the frozen
  inventory did not list. Inventoried as class B: it resolves through the normal
  getProviderCredentials path (its own log line says so) and does not reach past
  the lease, so it is inventoried rather than exempted.

- check:file-size — tests/unit/chatcore-translation-paths.test.ts 3546 -> 3564,
  this PR's own growth from the #14316 realignment: one shared credentials const
  plus the comment recording why the connection shape changed and that no
  assertion did. Rebaselined with that attribution; nothing was condensed away.

Validated: check-deps 13/13, hard-session-lease-bypass-inventory 3/3,
check:file-size OK (both halves).
diegosouzapw pushed a commit that referenced this pull request Sep 22, 2026
…ry (#14544)

Merged — closes #11725. Thank you, @RaviTharuma.

Correlating the credential CLIProxyAPI actually selected with the usage row is the kind of plumbing that only pays off later, when someone is trying to work out *which* account burned the quota. Storing the opaque `auth_index` on all three paths (success, streaming, error) with a backfill when the first write missed the header, and resolving the human-readable label at **read** time from the sanitized account-health projection, is the right split: the column never holds an email, a path, a token or a raw management payload, and a missing or unrecognized header stays unattributed instead of failing the request.

Validation before merge: boarded onto the release tip with the other seven PRs of your batch, then reconciled twice as the branch moved under it.

- **First move:** #14559 (another session) corrected the docs migration count 178 → 181, colliding with this PR on 69 files — `README.md`, `AGENTS.md`, `llm.txt` and 66 i18n `llm.txt` mirrors, 270 hunks. All 270 were proven mechanically to be pure numeral collisions (base 178 / ours 182 / theirs 181, byte-identical otherwise), and the resolution keeps the tip's exact line shape with 182. I checked separately that no mirror lost its translated prose: 270 removed lines and 270 added lines, each pair identical but for the numeral.
- **Second move:** #14069 landed and both sides had *added* a new top-level `_rebaseline_*` key to `config/quality/file-size-baseline.json` — an add/add, so both were kept and #14069's entry is intact.

The 182 is verified, not carried over: the tip has 181 migration files and this PR adds `185_usage_history_cpa_auth_index.sql`. `check:migration-numbering` reports `182 migrations, 0 duplicates` and `check:docs-counts-sync` passes its STRICT migration-count assertion across all four claim sites.

`cpa-trace-auth-index` + `cpa-auth-index-usage` + `db/migration-185-cpa-auth-index` + `chatcore-failure-usage` 12 pass / 0 fail. `check:file-size` OK — note your `chatCore.ts` ceiling is now 6402, measured after the commit; that file had been sitting at exactly 6400 with zero headroom since #14213.

`typecheck:core` reports exactly one error, and it is **not yours**: `src/lib/services/cliproxyAccountHealth.ts` TS2322 on `host: options.host ?? externalHost`. That expression is byte-identical on the pure tip at line 146 — this PR only shifts it to 157 by adding `labelForCliproxyAuthIndex` above — and it touches neither the `host: string` type nor `externalHost`. Inherited base defect, tracked separately.

Two things your PR did that I want to name, since both were on my checklist and neither needed a bounce: you bumped the migration count in `AGENTS.md`/`llm.txt` yourself (those are agent-instruction surfaces, so I confirmed the change was purely the numeral before merging), and in doing so you drained the 178 → 181 docs drift the previous batch had deferred.

A leftover for someone else: `docs/i18n/fr/README.md` and `docs/i18n/phi/README.md` still say 178 — #14559 updated the `llm.txt` mirrors but missed the README ones. Pre-existing on the tip, outside this diff.
diegosouzapw added a commit that referenced this pull request Sep 24, 2026
…s lossy policy; drain 12 base-red files

#14529 moved lossy engines off the header-less path in the runtime but not in
deriveEffectivePreviewPlan(), so the dashboard preview showed rtk -> caveman
while requests ran session-dedup -> lite (#12063 again). The preview now
applies downgradeUnrequestedLossy(); the #12063 test pins preview == runtime
for the profile, engines-map and safe-profile cases (fails on the old code).

Test guards realigned to merged design changes, each traced to its commit:
- #14529: compression suites opt in with allow-lossy where they test the
  operator plan, and assert the header-less downgrade; default seed is
  session-dedup + lite; the #10503 probe ignores the loopback dashboard
  telemetry POST that stacked compression emits (the context gate still
  rejects locally — verified with logging).
- #14530: breaker profile asserted on the connection breaker; the
  provider-wide cooldown case drives the network-error path.
- #14370: @opencode/plugin (stable OpenCode 2.x contract, npm maintainer
  thdxr) added to the dependency allowlist.
- #14213: the opt-in empty-turn retry credential site is inventoried as
  class A (dispatch goes through assertManagedLeaseFence).
- #14223 / #14329: flag count 77, quota registry 13 (muse-code).

Refs #14496
@maxmad64bis
maxmad64bis deleted the fix/flush-empty-retry branch September 24, 2026 21:13
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