李航
0e15805e25
fix(credential-pool): exhaust all entries sharing a failed API key on 402
...
A 402/429/401 is an API-key–level failure (account out of balance,
rate-limited, or key rejected), but the same key can back more than one
pool entry — e.g. an explicit pool entry plus a `model_config` entry
auto-seeded from `model.api_key`, both carrying the identical
`runtime_api_key`.
`mark_exhausted_and_rotate(api_key_hint=...)` only marked the *first*
matching entry, leaving the sibling OK. `_select_unlocked()` then kept
handing back the same depleted key, so the billing-recovery `continue`
loop in the conversation retry path never converged: the request hung
until the client disconnected (~2.5min observed against DeepSeek),
emitting only `response.created` with no 402 ever surfaced to the user.
Mark every entry sharing the failed key so the pool can reach the
"no available entries" state and let the error propagate immediately.
Adds a regression test covering two entries backed by the same key.
2026-07-23 09:08:28 -07:00
..
2026-07-22 16:59:29 -07:00
2026-07-22 12:10:58 -05:00
2026-07-23 09:08:28 -07:00
2026-07-23 05:45:17 +00:00
2026-07-23 08:19:14 -07:00
2026-07-23 01:39:21 -05:00
2026-07-22 20:57:25 -07:00
2026-07-07 18:33:28 +10:00
2026-07-18 01:11:03 -07:00
2026-07-22 20:55:51 -07:00
2026-07-23 08:43:21 -07:00
2026-07-23 08:26:57 -07:00
2026-07-17 06:53:38 -07:00
2026-07-17 20:55:24 +00:00
2026-07-05 13:42:46 -07:00
2026-07-01 03:16:13 -07:00
2026-07-22 14:12:50 +05:30
2026-07-22 22:23:24 -07:00
2026-07-22 04:39:20 -07:00
2026-07-23 07:33:25 -07:00
2026-07-22 16:51:01 -04:00
2026-07-22 03:20:45 -07:00
2026-07-23 08:07:00 -07:00
2026-07-21 12:40:48 -07:00
2026-07-05 13:42:46 -07:00
2026-07-23 08:34:06 -07:00
2026-07-23 08:19:14 -07:00
2026-07-22 21:14:44 -07:00
2026-07-03 14:27:34 +10:00
2026-07-06 03:28:30 -07:00
2026-07-01 16:21:39 +05:30
2026-07-22 04:40:07 -07:00
2026-07-23 07:24:46 -07:00
2026-06-24 04:16:54 +05:30
2026-07-22 04:39:28 -07:00
2026-07-05 00:44:15 -07:00
2026-07-14 03:58:54 +05:30
2026-06-21 12:09:16 -07:00
2026-06-14 00:27:59 -04:00
2026-07-15 00:10:31 -07:00
2026-07-22 03:20:25 -07:00
2026-07-06 04:58:07 -07:00
2026-07-22 04:39:17 -07:00
2026-06-28 15:38:39 -07:00
2026-07-22 10:35:04 -07:00
2026-07-20 05:39:09 -07:00
2026-06-27 15:59:00 -07:00
2026-07-18 00:34:54 -04:00
2026-07-05 11:44:53 +05:30
2026-07-17 20:55:24 +00:00
2026-07-23 17:32:38 +05:30
2026-07-23 08:08:48 -07:00
2026-07-16 12:48:48 -07:00
2026-07-17 20:55:24 +00:00
2026-07-18 19:18:03 +05:30
2026-06-30 20:11:01 +07:00
2026-06-25 23:49:11 -07:00
2026-07-18 18:40:59 -04:00
2026-06-18 22:11:35 +05:30
2026-07-07 21:17:34 +07:00
2026-06-23 21:33:08 -07:00
2026-06-18 16:26:34 +07:00
2026-07-05 19:35:30 -07:00
2026-06-28 03:58:01 -07:00
2026-06-18 14:14:41 +10:00
2026-06-26 20:10:20 +05:30
2026-06-25 23:49:11 -07:00
2026-06-24 23:51:31 +05:30
2026-07-21 12:15:46 +05:30
2026-07-05 14:01:03 -07:00
2026-07-05 14:51:49 -07:00
2026-06-28 22:52:59 -07:00
2026-07-22 03:19:32 -07:00
2026-07-01 03:17:48 -07:00
2026-07-22 16:51:01 -04:00
2026-07-22 16:51:01 -04:00
2026-06-30 15:30:06 -07:00
2026-07-22 16:51:01 -04:00
2026-07-16 19:48:47 -04:00
2026-07-07 15:15:37 -07:00
2026-07-07 11:57:01 +05:30
2026-07-17 20:55:24 +00:00
2026-07-22 07:56:47 -07:00
2026-07-12 05:07:52 -04:00
2026-07-22 21:14:44 -07:00
2026-07-18 04:15:13 -07:00
2026-07-23 17:32:38 +05:30
2026-06-24 04:16:54 +05:30
2026-07-22 04:42:50 -07:00
2026-06-14 03:20:21 -07:00
2026-07-14 21:25:44 -07:00
2026-07-18 01:11:03 -07:00
2026-07-05 13:40:21 -07:00
2026-07-21 12:43:27 -07:00
2026-06-28 02:35:01 -07:00
2026-07-22 21:53:56 -04:00
2026-07-23 08:19:14 -07:00
2026-07-23 05:02:45 +00:00
2026-06-18 05:41:23 -07:00
2026-07-15 04:55:46 -07:00
2026-07-16 15:23:32 -04:00
2026-07-16 14:43:14 +02:00
2026-07-23 07:33:28 -07:00
2026-06-25 23:27:44 +05:30
2026-07-08 08:05:45 -07:00
2026-07-05 00:41:34 -07:00