fix(sse): honor per-step connection pins instead of rotating accounts on fallback

A combo step pinned with an explicit `connectionId` (or a request pinned via
`x-omniroute-connection`) is an operator instruction, not a hint. The generic
account-fallback branch in handleSingleModelChat excluded the pinned connection
after an upstream failure and re-selected a sibling account of the same provider,
so a priority combo repeating one provider/model with two different fixed accounts
ran both attempts under the FIRST step: the second step, with its own pin, never
executed and per-step attribution (comboStepId / comboExecutionKey) was wrong.

Gate the rotation on `!hasForcedConnection`, matching the antigravity
stream-readiness, pre-response-timeout and account-semaphore branches that already
let pinned steps fall through to combo orchestration. Cooldown recording via
markAccountUnavailable is unchanged, and unpinned selection still excludes burned
connections.

Refs tests/integration/combo-routing-e2e.test.ts
This commit is contained in:
Xiangzhe
2026-08-25 19:34:49 -03:00
parent 2dfb730241
commit a11930ec44

View File

@@ -2294,7 +2294,14 @@ async function handleSingleModelChat(
}
);
if (shouldFallback) {
// An explicit pin (combo step `connectionId` / `x-omniroute-connection`) is an
// operator instruction, not a suggestion: the account cooldown above is still
// recorded, but selection must NOT silently rotate to a sibling account of the
// same provider. Pinned steps fall through to combo orchestration, which moves
// to the next target — with ITS own pin. Same rule the antigravity
// stream-readiness / pre-response-timeout and account-semaphore paths above
// already apply.
if (shouldFallback && !hasForcedConnection) {
if (Number.isFinite(cooldownMs) && cooldownMs > 0) {
lastCooldownMs = cooldownMs;
requestRetryLastCooldownMs = cooldownMs;