* fix(providers): preserve openrouter/ prefix for native models (#12924)
OpenRouter-native models like 'openrouter/aurora-alpha' need the full
'openrouter/<name>' as the model ID in API requests. The existing
parseModelRef() stripped the prefix, sending just 'aurora-alpha'
which OpenRouter rejects with 400.
Fix: normalizeProviderModelId() now re-adds the 'openrouter/' prefix
for models without a slash (native models), while passing through
external provider models (e.g. 'anthropic/claude-sonnet-4-5') as-is.
Closes#12924
* Changelog: add OpenRouter note for #12942
---------
Co-authored-by: Luna AI <luna@coredirection.ai>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
* fix: preserve stored provider in resolveSessionModelRef for vendor-prefixed models
When an OpenRouter model with a vendor prefix (e.g. "anthropic/claude-haiku-4.5")
was successfully used and persisted to the session entry, the next call to
resolveSessionModelRef would re-parse the model string through parseModelRef,
which splits on the first slash and incorrectly extracts "anthropic" as the
provider — discarding the stored "openrouter" provider entirely. This caused
subsequent requests to attempt direct Anthropic API calls with an OpenRouter
API key, producing "credit balance too low" billing errors.
The fix trusts the explicitly stored modelProvider on the session entry and
skips parseModelRef re-parsing when a provider is already recorded. parseModelRef
is still used as a fallback when no provider is stored on the entry.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Changelog: add OpenRouter note for #22753
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
* fix(agents): skip bootstrap files with undefined path
buildBootstrapContextFiles() called file.path.replace() without checking
that path was defined. If a hook pushed a bootstrap file using 'filePath'
instead of 'path', the function threw TypeError and crashed every agent
session — not just the misconfigured hook.
Fix: add a null-guard before the path.replace() call. Files with undefined
path are skipped with a warning so one bad hook can't take down all agents.
Also adds a test covering the undefined-path case.
Fixes#22693
* fix: harden bootstrap path validation and report guards (#22698) (thanks @arosstale)
---------
Co-authored-by: Peter Steinberger <steipete@gmail.com>
When the backoff saturates at 60 min and retries fire every 30 min
(e.g. cron jobs), each failed request was resetting cooldownUntil to
now+60m. Because now+60m < existing deadline, the window kept getting
renewed and the profile never recovered without manually clearing
usageStats in auth-profiles.json.
Fix: only write a new cooldownUntil (or disabledUntil for billing) when
the new deadline is strictly later than the existing one. This lets the
original window expire naturally while still allowing genuine backoff
extension when error counts climb further.
Fixes#23516
[AI-assisted]