Commit Graph

6624 Commits

Author SHA1 Message Date
Mohit Rawat
2944eba82f ci(test): route orphaned Vitest tests through blocking CI (#9605)
* ci(test): route orphaned Vitest tests through blocking CI

* docs: fix advisory status in AGENTS.md and refresh baseline note

* fix(changelog): fix fragment format for #9415

* fix(changelog): preserve upstream fragment format

---------

Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com>
2026-08-11 07:36:39 -03:00
Diego Rodrigues de Sa e Souza
aa36742378 fix: restore unorouter api and catalog metadata (#9594)
Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com>
2026-08-11 07:34:43 -03:00
Bob.Hou
c3dc0352ac fix(providers): reject the dashboard password as a connection API key (#9572)
* fix(providers): refuse to store the dashboard password as a connection API key

A browser autofilled the management password into a connection's API-key field.
The resulting credential authenticates against nothing, so every request routed
through that connection came back 401, and because the field looks like any
other password input the same autofill fired again while the connection was
being repaired by hand.

The refusal belongs on the write path rather than in the form. Twenty routes
create or update connections and all of them funnel through
createProviderConnection and updateProviderConnection, so one check there covers
every entry point including a future one. The two other places that write
api_key are left alone on purpose: one re-encrypts rows that already exist and
the other is the one-time db.json import, and neither takes a value an operator
just typed.

Update checks the incoming value, never the merged one. A connection that
already holds the password has to stay editable or the operator cannot repair
the exact state this prevents, and re-checking the merged value would spend a
bcrypt round on every unrelated field edit.

Only a real match blocks the write. An unreadable settings row or a throwing
bcrypt call logs and allows, because a guard against one specific mistake must
not turn into a way to lock out every connection write.

Signed-off-by: Minxi Hou <houminxi@gmail.com>

* fix(providers): compare the untrimmed credential, and cover the guard's branches

The guard trimmed the incoming value before comparing it, which catches a paste
carrying whitespace the password does not have. It missed the mirror case:
neither the login route nor the set-password route trims, so a dashboard
password may itself begin or end with a space, and an autofill reproducing it
exactly was trimmed into a value that no longer matched the stored hash. The
write then went through, which is the state this guard exists to prevent. Both
forms are compared now, the second only when the first fails on a string that
differs, so an ordinary key still costs a single bcrypt round.

Two branches carried no coverage and both are load-bearing. The catch that logs
and allows is the only path that lets a write through; a stored hash bcrypt
cannot parse reaches it without needing a mock, since the shape check accepts an
impossible cost factor that the comparison then rejects. The early return is
what keeps a token renewal -- a write carrying tokens but no apiKey -- from
paying for a settings read and a bcrypt round every time it fires, and the same
unparseable hash makes that path observable, so an absent warning is proof the
return happened.

The narrower scope is deliberate and now says so in the code: the OAuth tokens
arrive from a provider's token endpoint rather than from a form, so extending
the comparison to them would charge every renewal for a field no autofill can
reach.

Signed-off-by: Minxi Hou <houminxi@gmail.com>

---------

Signed-off-by: Minxi Hou <houminxi@gmail.com>
2026-08-11 07:27:27 -03:00
Diego Rodrigues de Sa e Souza
c61cdc30aa fix(providers): switch minimax from claude to openai format so images work (#9463)
* fix(providers): switch minimax from claude to openai format so images work

The Anthropic-compatible /anthropic/v1/messages endpoint rejects image
input with 403. MiniMax's OpenAI-compatible /v1/chat/completions endpoint
supports image_url natively for MiniMax-M3.

- minimax + minimax-cn: format claude→openai, baseUrl→/v1/chat/completions
- Remove Anthropic-Version header + ?beta=true suffix (not needed for openai)
- Remove minimax/minimax-cn from ?beta=true executor case
- Update cache-control tests (openai format uses different caching path)
- Fix reasoning-split test names (no longer claude format)

TDD: 2 registry tests assert format=openai (red→green).
Refs: Hermes Agent #15715, MiniMax OpenAI-compatible API docs.

* fix(sse): re-align stream-readiness-policy tests with minimax's openai format

PR #9463 switched minimax/minimax-cn from claude to openai format so images
work. The stream-readiness bump for Claude-format replicas is keyed off the
registry's format field (single source of truth), so minimax legitimately
falls out of that group now. Swap the "Claude-format replica" test fixtures
to agentrouter (still format: "claude") and add explicit coverage that
minimax no longer gets the claude_format_heavy_reasoning bump.

---------

Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com>
2026-08-11 07:25:28 -03:00
Diego Rodrigues de Sa e Souza
31fce91fbd feat(providers): add Naga.ac and ChatAnywhere aggregator providers (#6674) (#9421)
Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com>
2026-08-11 07:23:31 -03:00
AbdullahFageeh
98962b0b30 docs: clarify free-provider model refresh outcomes (#9087)
* docs: document provider model refresh fix

Document the verified live-model refresh path for stale provider catalogs,
record the current Pollinations anonymous-access limitation, and sync the
provider-count references after regenerating the provider reference.

Co-Authored-By: Oz <oz-agent@warp.dev>

* docs: note codex local env and mac path

Co-Authored-By: Oz <oz-agent@warp.dev>

---------

Co-authored-by: Oz <oz-agent@warp.dev>
2026-08-11 07:21:28 -03:00
backryun
668ed4813f refactor(providers): remove retired GitHub Models (#9023) 2026-08-11 07:19:32 -03:00
TengSivtean
ed2f3cd067 docs: fix stale tool count (105 -> 104) in MCP server docs (#10002)
The doc's own breakdown at line 11 (42+3+4+3+6+8+8+6+22+2) sums to
104, matching the two existing '104 unique tools' mentions. The
'105 tools' mentions in the intro and cardinality-reduction section
were stale and inconsistent with the documented source of truth.
2026-08-11 07:16:11 -03:00
ikelvingo
f0d976c341 [v3.8.50] fix: passthrough non-standard cache token fields for DeepSeek / MiniMax / Bedrock across streaming, non-streaming, and Dashboard paths (#8591)
* fix(#8171): map DeepSeek prompt_cache_hit_tokens into prompt_tokens_details.cached_tokens

DeepSeek native API returns cache stats in flat top-level fields
(prompt_cache_hit_tokens / prompt_cache_miss_tokens) instead of
the standard prompt_tokens_details.cached_tokens. The usage
sanitizer (sanitizeUsage / sanitizeResponsesUsage) was stripping
these non-standard fields, so clients never received real cache
hit counts even when the upstream served cached responses.

Changes:
- sanitizeUsage(): map prompt_cache_hit_tokens into
  prompt_tokens_details.cached_tokens when the latter is unset
- sanitizeResponsesUsage(): same mapping for input_tokens_details
- filterUsageForFormat(): add prompt_cache_hit_tokens and
  prompt_cache_miss_tokens to the default format allow list
  so they survive field-level filtering

* fix: passthrough non-standard cache token fields for DeepSeek / MiniMax / Bedrock across streaming, non-streaming, and Dashboard paths

* fix(sse): shrink cache-hit token passthrough to fit file-size gate

PR #8591 added a DeepSeek/MiniMax/Bedrock flat cache-hit-token ->
nested prompt_tokens_details.cached_tokens mapping (#8171) that grew
responseSanitizer.ts and stream.ts past their frozen file-size
baselines.

- Extract the chat-completions/Responses-API mapping logic into a new
  leaf module (responseSanitizer/cacheHitTokens.ts).
- Move the streaming-path rebuild into filterUsageForFormat()
  (usageTracking.ts), the single conversion chokepoint both stream.ts
  call sites already used, eliminating the duplicated stream.ts patch
  entirely.
- Rebaseline responseSanitizer.ts by the 2 lines that remain
  irreducible (the mandatory ES import for the extracted helper).

Behavior verified unchanged via the existing response-sanitizer and
stream-handler unit suites.

Co-authored-by: ikelvingo <ikelvingo@users.noreply.github.com>

---------

Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com>
Co-authored-by: ikelvingo <ikelvingo@users.noreply.github.com>
2026-08-11 07:15:08 -03:00
jhordanjw123
b4fc835d25 [v3.8.50] feat(providers): add support for TinyCMS Web (#8736)
* feat(providers): add support for TinyCMS Web including WASM-based cryptographic signing and Proof-of-Work emulation

* feat(providers): add unit tests, ESLint suppressions, and fix hardcoded userid for TinyCMS Web

- Add unit tests for WASM init, UUID validation, challenge flow (15 tests)
- Add WASM source comment explaining binary origin
- Replace hardcoded userid with dynamic provider-specific data
- Add ESLint suppressions for no-explicit-any in WASM bridge code
- Add explanatory comments for DOM shim (runtime WASM-bindgen, not test mocks)

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>

* refactor(providers): extract TinyCMS DOM shims into an explicit setup function

tinycmsSigner.ts installed its window/document/HTMLCanvasElement/
CanvasRenderingContext2D shims for the wasm-bindgen glue as a module-load
side effect. That meant merely importing the module (even transitively,
e.g. through the provider registry from an unrelated test) mutated
global state for the rest of the test process.

Extract the shim installation into setupDomMocks(), which returns a
restore callback:
- initTinyCmsWasm() calls it once before instantiating the WASM module
  (production path — unchanged behavior, still automatic).
- tests/unit/provider-tinycms-web.test.ts now calls it explicitly in a
  `before` hook and restores the previous globals in `after`, so the
  shims never leak into other test files.

As a side effect, replacing five separate `as any` casts with a single
typed `global as Record<string, any>` handle drops the file's
no-explicit-any count from 5 to 1; eslint-suppressions.json updated to
match.

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>

* docs(providers): regenerate PROVIDER_REFERENCE.md for tinycms-web

Mechanical `npm run gen:provider-reference` run after merging release/
v3.8.50 into this branch — the generated table was stale for both the
new tinycms-web entry this PR adds and the release's own cheaperinference
addition. Total providers 290 -> 292, Web Cookie Providers 31 -> 32.

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>

---------

Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com>
Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
2026-08-11 04:45:34 -03:00
Xiangzhe
9ad1558126 fix(settings): use provider prefixes in model overrides (#9569) 2026-08-11 04:43:23 -03:00
Ke Jin
79387156d4 fix(translator): preserve Kimi K3 Responses reasoning (#9556)
* fix(translator): preserve Kimi K3 Responses reasoning

* fix(translator): make K3 reasoning preservation model-driven

* fix(translator): replay cached Kimi reasoning before fallback

* fix(translator): keep authentic K3 reasoning through cleanup

* refactor(reasoning): use replay policy for K3
2026-08-11 04:37:30 -03:00
NOXX - Commiter
5257d02447 fix(adobe-firefly): harden CDP warm, risk session, and browser sign-in (#9549)
* fix(adobe-firefly): open browser sign-in and resolve provider slug in /login

POST /api/providers/[id]/login passed the connection DB id to
inAppLoginService.startLogin, but TOKEN_EXTRACTION_CONFIGS is keyed by
provider slug — so browser login never launched for web-cookie providers.

Adobe Firefly also cannot use cookie extraction: the IMS JWT only appears
on Authorization headers to firefly-3p.ff.adobe.io. Add a dedicated
Playwright interceptor and persist credentials with camelCase keys that
updateProviderConnection actually reads.

* fix(adobe-firefly): use system Chrome/Edge CDP for browser sign-in

Playwright is not available inside the pkg-packaged VibeProxyServices.exe,
so import('playwright') always failed with 'Playwright not installed' and
never opened a window. Launch Chrome/Edge with --remote-debugging-port and
capture the firefly-3p Authorization Bearer via pure CDP WebSocket instead.

* fix(adobe-firefly): live x-arp-session-id / Arkose wire (stop 408 under load)

Browser generate-async requires x-arp-session-id as base64({sid,ark,ftr}) with a
real Arkose blob (sherlockToken). JWT alone frequently returns colligo HTTP 408
system under load while credits still work.

- Match live ftr magic __UDF43-m4_31ck + Arkose pk in synthetic ARP fallback
- Ranked extract of sherlockToken / x-arp from Cookie, HAR, fetch() paste, and
  space-joined JWT+ARP (PasswordBox newline collapse)
- Reuse one ARP for storage upload + generate-async
- Clearer 408 errors when browser ARP is missing vs stale
- Unit suite 42/42

* fix(adobe-firefly): durable session ARP rebuild and aux_sid false-positive

Rebuild x-arp-session-id from forterToken/arkose/ff_session_guid instead of
ranking long Cookie pairs (e.g. aux_sid=…) as opaque ARP, which caused colligo
HTTP 408. Cache IMS JWT + cookie sessions, rotate ARP on 408 retries, and keep
Playwright warm-up opt-in only (headless Forter is rejected).

Also expand synthetic ARP shape with bfp/fpjs to match live successful captures.

* fix(adobe-firefly): renew sessions through durable CDP

* fix(adobe-firefly): isolate browser sessions per account

* fix(adobe-firefly): make account login fresh and deterministic

* docs(adobe-firefly): document renewal controls

* fix(adobe-firefly): harden CDP warm, risk session, and browser sign-in

Stop colligo 408 thrash from stale Forter and frozen Google login during
Sign in with browser:

- CDP warm: clear Firefly origin storage + risk cookies (keep SSO); require
  forter age under 10 minutes on loop and timeout paths; dual CDP queues;
  await Runtime.runIfWaitingForDebugger; profile-lock launch retries
- Session: connectionId fingerprint; write-back JWT+Cookie; warm-fail
  cooldown; fail closed risk_session_stale when forter is known-stale
- Client: submit gate around generate-async; max 2 attempts when forter
  known-stale; poll 401 one refresh; pass sessionBrowserKey through handlers
- Login route: pure system Chrome/Edge CDP only; camelCase credential persist
- Unit: browser-login + firefly suites green (60)

* fix(adobe-firefly): dedupe CDP session hardening blocks after rebase

Remove duplicated guard blocks and test bodies introduced when rebasing
the CDP session hardening work onto release/v3.8.50, which already
carries the hardened implementation.

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>

---------

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
2026-08-11 04:35:59 -03:00
LeonG606
565b3e0356 fix(sse): preserve client cache boundaries when hoisting system roles (#9457)
Hoisting a mid-conversation `system`/`developer` message into the top-level
`system` field carried its `cache_control` marker along. Anthropic assembles the
cache prefix as tools -> system -> messages, so the marker ended the cached
prefix at the system block and left the accumulated conversation without a
breakpoint: that turn was billed as fresh input and the next one rebuilt the
cache.

`relocateHoistedCacheBoundary` moves the marker to the nearest preceding block
that can carry a breakpoint, skipping thinking blocks, empty text and anything
the upstream normalisation discards or empties out. If that block already
carries the client's own marker, both are kept - unless the hoisted one, now
ahead of the target in `system[]`, would put a 5m breakpoint before a 1h one,
which Anthropic rejects; it is dropped in that case. Either way the breakpoint
count never grows.

normalizeClaudeUpstreamMessages rewrites tool_result and inlined file/document
blocks into plain text after the hoist, which silently discarded any marker on
them - including a relocated one. The replacement block now inherits it.

Both hoisting implementations share the helper; a fix touching only
claudeSystemRole.ts would leave extractSystemMessagesToBody broken, and the
native Claude path reaches the former through normalizeClaudeUpstreamMessages.
Capability-gated hoisting for strict providers (#7293) is unaffected.

Fixes #9436

Co-authored-by: LeonG606 <leongudat01@gmail.com>
Co-authored-by: Diego Rodrigues de Sa e Souza <diegosouza.pw@gmail.com>
2026-08-11 04:35:49 -03:00
Will Gordon
e856fe3941 ci: re-trigger checks after GitHub Actions incident (2026-08-07, resolved) (#9441) 2026-08-11 04:35:39 -03:00
Kittisak Tangsiri
b13c3cd202 fix(translator): normalize streamed optional tool arguments (#9423)
* fix: preserve Codex cache usage for Claude suggestions

Co-Authored-By: Claude <noreply@anthropic.com>

* fix: normalize streamed optional tool arguments

Co-Authored-By: Claude <noreply@anthropic.com>

---------

Co-authored-by: Kittisak Tangsiri <kittisak@users.noreply.github.com>
Co-authored-by: Claude <noreply@anthropic.com>
2026-08-11 04:35:30 -03:00
Dizzle
0cbdc95023 feat(sse): server-side template expansion for combo system prompts (#5501) (#9414)
* feat(sse): server-side template expansion for combo system prompts (#5501)

* fix(quality-gates): register combo-system-prompt-templates-5501 test in stryker tap.testFiles

check:mutation-test-coverage --strict flagged tests/unit/combo-system-prompt-templates-5501.test.ts
as covering src/shared/utils/circuitBreaker.ts without being listed in stryker.conf.json
tap.testFiles, so its mutant kills wouldn't count.

Co-authored-by: maxmad64bis <maxmad64bis@users.noreply.github.com>

---------

Co-authored-by: Max <maxmad64@gmail.com>
Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com>
Co-authored-by: maxmad64bis <maxmad64bis@users.noreply.github.com>
2026-08-11 04:35:20 -03:00
Chewji
e58c5ee060 fix(command-code): preserve literal max effort for command-code provider (#9257)
* fix(command-code): preserve literal max effort for command-code provider

* test(command-code): type the new sanitizeReasoningEffortForProvider assertions

The 3 new command-code reasoning-effort test cases cast the function's
unknown return value with `as any`, which pushes the file's frozen
no-explicit-any suppression count (48) to 51 and trips the "No new
ESLint warnings" gate. Use a minimal EffortCarrierResult shape instead
of any, matching the fields the assertions actually read.

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>

* test(v1-models): type the API key lookup in the #9320 auth-leak regression test

The release-tip test file added by #9320 used `(k: any)` in an Array.find
callback, which is not covered by config/quality/eslint-suppressions.json
(the file was added after the suppressions snapshot was frozen). That
leaves the "No new ESLint warnings" gate red for any branch that merges
this exact release/v3.8.50 tip, unrelated to this PR's own diff. Fixing
it here with a minimal derived type (Awaited<ReturnType<typeof
getApiKeys>>[number]) unblocks the gate without touching the frozen
suppressions baseline.

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>

---------

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
2026-08-11 04:34:46 -03:00
Bob.Hou
f10dca4318 fix(combo): recover provider circuit breaker from HALF_OPEN on success (#9207)
The combo success path called recordProviderSuccess (cooldown-only)
without notifying the circuit breaker. When a provider breaker entered
HALF_OPEN after repeated failures, successful probe requests never
transitioned it back to CLOSED -- the breaker stayed stuck indefinitely.

Production evidence: agy breaker HALF_OPEN with 699 requests at 98%
success rate, never recovering.

Root cause: combo.ts calls recordProviderSuccess from
providerCooldownTracker.ts (resets cooldown failureCount only) but
never calls breaker._onSuccess(). The failure path in accountFallback.ts
calls breaker._onFailure(), creating an asymmetry.

Fix: add recordProviderSuccess to accountFallback.ts as the symmetric
counterpart of recordProviderFailure. Uses getProviderBreaker (not
configureProviderBreaker) to avoid overwriting the breaker's resetTimeout
with default profile values. Calls breaker._onSuccess() for all non-OPEN
states (CLOSED/DEGRADED/HALF_OPEN), matching execute()'s behavior.
2026-08-11 04:34:23 -03:00
Dizzle
66845d2e37 fix(dashboard): make connection Default Model editable and optional (#9172) (#9179)
* fix(dashboard): make connection Default Model editable and optional

* docs(changelog): retitle fragment with PR number

---------

Co-authored-by: Diego Rodrigues de Sa e Souza <diegosouza.pw@gmail.com>
2026-08-11 04:31:35 -03:00
Will Gordon
57744aeb14 feat(cursor): proactively renews Cursor sessions and fixes manual refresh (#9173)
* refactor(cursor): extracts token extraction into shared lib

Moves tryIdeAuth/tryAgentAuth and supporting helpers out of the
auto-import route into src/lib/cursor/tokenExtractor.ts, and adds
an agent-cli-state.json fallback candidate path to tryAgentAuth
(alongside the existing auth.json candidate) so the extraction
logic can be reused by the upcoming renewal orchestrator.

* feat(cursor): adds cursor-agent-backed token renewal orchestrator

Builds the renewal orchestrator in src/lib/cursor/renewal.ts: a
bounded, unattended-safe --list-models nudge, a side-effect-free
status availability check, an in-flight spawn lock keyed by
command, and renewCursorConnection() which nudges cursor-agent
then independently re-scrapes the IDE and cursor-agent credential
sources to detect whichever refreshed. Extends cursorAgent.ts's
binary resolution and spawn helper with fixed-paths-only mode and
a SIGKILL follow-up for background use. Adds a generic keyed-mutex
utility (src/shared/utils/keyedMutex.ts) for serializing a
connection's renew-then-persist cycle, and forwards a busy-timeout
through driverFactory's node:sqlite fallback path.

* feat(cursor): proactively renews Cursor sessions in the sweep

Adds src/lib/tokenHealthCheckCursor.ts, sweep-side glue that calls
the renewal orchestrator and persists the result, wired into
tokenHealthCheck.ts's checkConnection() via a new Cursor-specific
branch placed ahead of the generic no-refresh-token fallthrough.
Carves out a non-terminal exception for a Cursor connection that
already landed at testStatus "expired" via the request-time 401
path, excluding permanently-dead account_deactivated connections.
Extends buildRefreshFailureUpdate() with an overrides param so
Cursor's failure path can use a distinct, non-terminal errorCode
instead of the generic refresh_failed/expired taxonomy.

* feat(cursor): adds local-only manual refresh route

Adds POST /api/providers/[id]/refresh-cursor, a dedicated
loopback-only route that calls the renewal orchestrator on demand
for a single Cursor connection, bounded by a 30s per-connection
cooldown. Classifies the new route in LOCAL_ONLY_API_PATTERNS and
closes the manage-scope-bypass gap for dynamic-segment spawn-capable
routes under /api/providers/ via a new SPAWN_CAPABLE_PATTERNS /
SPAWN_CAPABLE_PATTERN_ANCESTORS mechanism, which also retroactively
covers the pre-existing /login route. The existing shared
/api/providers/[id]/refresh route is untouched and stays
remote-reachable for every other provider.

* feat(cursor): surfaces a dismissible cursor-agent nudge

Adds GET /api/providers/cursor/agent-availability, a credential-free
LOCAL_ONLY route returning only { cursorAgentAvailable: boolean },
backed by a 5-minute cached wrapper around the renewal orchestrator's
existing availability check. Surfaces a dismissible dashboard banner
on the Cursor provider page suggesting cursor-agent installation
when it isn't detected, following the existing dismissible-banner
convention. Also fixes a pre-existing bracket character in a
routeGuard.ts comment that was silently truncating
check-openapi-security-tiers.mjs's view of LOCAL_ONLY_API_PREFIXES.

* fix(cursor): wires manual refresh button to the new route

Branches handleRefreshToken to call the dedicated Cursor refresh
route instead of the generic /refresh route, which silently 502s
for Cursor connections today since they carry no refresh token.
Every other provider's refresh behavior is unaffected. Adds the
cursorSessionUnchanged i18n key and syncs it (plus a pre-existing,
unrelated 28-key backlog) across all 42 locale files.

* fix(cursor): addresses Phase 4/4.5 review findings

Restores the legacy stdout/stderr auth-pattern fallback in
checkCursorAgentAvailability() that the plan's Task 2 Step 4
required but the implementation had dropped. Threads an optional
deps parameter through checkCursorConnectionIfNeeded() so its
error branch is reachable in tests, and switches both it and the
manual-refresh route to exhaustive switch statements over the
renewal result. Adds a short-lived host-keyed dedup cache around
tryIdeAuth() so multiple due Cursor connections sharing a host
don't each open the same state.vscdb file in one sweep tick.
Adds opportunistic eviction to the manual-refresh cooldown map,
an outer try/catch to the availability route for defense-in-depth
consistency with the plan's other routes, and corrects a stale
JSDoc claim about the /login route's auth check. Documents the
now-empirically-confirmed agent-cli-state.json schema mismatch
found while validating against a real cursor-agent install.

* docs(cursor): adds changelog fragments for the renewal plan

Adds one fragment per user-facing outcome per changelog.d/README.md's
convention for a PR that both fixes and adds. PR number placeholder
to be filled in once the PR is opened.

* fix(i18n): translates the new Cursor keys into Vietnamese

The i18n:sync-ui run in an earlier commit left __MISSING__
sentinels for the 4 new Cursor keys in every locale, but
Vietnamese has a dedicated completeness test requiring zero
internal missing markers. Provides real translations for
cursorSessionUnchanged, cursorAgentNudgeTitle,
cursorAgentNudgeBody, and cursorAgentNudgeDismiss.

* fix(cursor): addresses quality-gate Layer 1.5 findings

Restores a comment that misrepresented execFile's actual argv shape
after an earlier bracket-removal fix, this time avoiding literal
closing-bracket characters entirely so the openapi checker's naive
array parser can't be broken by either version. Bounds the sweep-
and manual-route-triggered tryIdeAuth() busy-timeout to 250ms
(down from the interactive auto-import path's 2000ms), since both
share the main event loop with all other in-flight requests and
should fail fast on a WAL-lock collision rather than block the
whole instance for up to ~4s. Has the manual refresh route bypass
the sweep's IDE-auth dedup cache so a click always sees a fresh
read, consistent with this plan's existing "manual actions never
see stale cached data" convention. Documents the previously-missing
agent-availability route in ROUTE_GUARD_TIERS.md's spawn-capable
table.

* fix(cursor): adds SIGKILL follow-up to the status-check spawn

Matches the nudge spawn's existing SIGTERM+SIGKILL pattern so an
unresponsive cursor-agent status check can't leak a lingering
process if it ignores SIGTERM.

* docs(cursor): fills in the PR number for changelog fragments

Renames the 3 changelog.d fragments to their PR-numbered filenames and replaces the (#PR) placeholder with #9173, now that the PR exists.

* fix(cursor): corrects changelog fragments to reference PR #9173

The prior commit only staged the git mv rename — a git add invocation with a stale (pre-rename) pathspec aborted before the actual (#PR) -> (#9173) content edit was staged, so the rename landed without the fix it was meant to carry. This captures the actual content change.

* docs(cursor): regenerates the agent-skills catalog for the new route

check:agent-skills-sync (CI's Merge integrity gate) requires SKILL.md files to stay in sync with the live route catalog. Adding /api/providers/cursor/agent-availability in an earlier commit needed a regen this branch never ran.

* chore(quality): rebaselines file-size caps grown by agentrouter merges

Two already-merged agentrouter commits (564c204ef, ec150a006) on release/v3.8.50 grew open-sse/executors/base.ts, open-sse/handlers/chatCore.ts, and tests/unit/chatcore-translation-paths.test.ts past their frozen caps before this PR branched — unrelated to the Cursor renewal changes here. No PR branch is left to fix the growth in-place, so the caps are bumped to the current real sizes, following the existing release-green rebaseline precedent in this file.

* fix(sse): imports getModel helpers from db/models, not localDb

A recently-merged agentrouter commit added a @/lib/localDb import in chatCore.ts, violating the no-restricted-imports rule (Hard Rule #2 — never barrel-import from localDb.ts). Points the import at the owning module, src/lib/db/models.ts, where both functions are actually defined, and prunes the now-stale suppression entry.

* fix(sse): scopes CC-relay anthropic-beta to its own requestDefaults

Two already-merged agentrouter commits widened usesClaudeCodeProtocol()'s native-Claude system-transform block (billing header + selectBetaFlags-derived anthropic-beta) to also run for generic CC-compatible relay connections, not just real claude traffic and agentrouter's own wire-image mimicry. selectBetaFlags() has no visibility into a relay's own providerSpecificData.requestDefaults, so its header replacement silently wiped out an earlier context-1m append and force-included redact-thinking regardless of the relay's own opt-in. Restores both for plain CC-compatible relays only; real claude/agentrouter traffic is unaffected.

Also bumps four stale hardcoded Codex/Claude Code CLI version-string test assertions (0.144.1->0.146.0, 2.1.219->2.1.220) that drifted when the same two commits bumped the version constants without updating their tests, and rebaselines base.ts's frozen file-size cap for this fix's own +35 lines.

* fix(sse): preserves bare CC-relay native treatment and context-1m

The previous commit's fix was too broad in one direction: excluding ALL CC-compatible relays from the native-Claude header block broke two pre-existing tests (cc-compatible-provider.test.ts, v3.6.6) that rely on that treatment for a 'vanilla' relay with no providerSpecificData.requestDefaults configured.

Refines the gate to this whole native-Claude header-replacement block: replace headers for real claude traffic, agentrouter's wire-image mimicry, OR a CC-relay with no requestDefaults at all — only a relay with EXPLICIT requestDefaults (context1m/redactThinking/summarizeThinking) gets to keep buildHeaders()'s own correctly-computed header set. A redact-thinking-beta strip (unconditional, a no-op when native treatment didn't apply) covers the one remaining gap: selectBetaFlags() force-includes it for a bare relay's opaque client, which a bare relay never explicitly opted into.

Verified against all three previously-conflicting pre-existing tests simultaneously: executor-default-base.test.ts's '1M beta' test, both cc-compatible-provider.test.ts SSE-forcing tests, and provider-request-failure-pipeline.test.ts's 'keeps request beta headers' test (the last of which was already broken by the raw agentrouter merge, confirmed via direct comparison against that exact commit).

* fix(sse): fills in remaining stale CLI version literals

The same two agentrouter commits bumped Codex/Claude Code CLI version constants (0.144.1->0.146.0, 2.1.219->2.1.220) without updating every hardcoded test assertion. This round covers the ones the previous version-string commit missed: the anthropic-cache-fingerprint billing-version constant, a cc-bridge-transforms body assertion, the UI-mirror parity test's own snapshot plus its RoutingTab.tsx source of truth, an integration test's User-Agent assertion (inconsistent with its own dynamic Version assertion two lines up), and the translate-path golden snapshot. Also updates a stale doc comment referencing the old literal by value instead of by constant name.

* fix(cursor): imports from db/ modules, not the localDb barrel

Both files violated Hard Rule #2 (never barrel-import from localDb.ts) — a genuine lint error that had gone uncaught locally. refresh-cursor/route.ts imported getCachedProviderConnectionById from @/lib/localDb instead of its owning module, @/lib/db/readCache. tokenHealthCheckCursor.ts copied the same pattern from its sibling tokenHealthCheckCopilot.ts (an existing, already-suppressed violation) for updateProviderConnection; imports it from @/lib/db/providers instead, with no circular-import fallout (verified via the existing token-health-check-cursor and refresh-cursor-route test suites).

* fix(db): removes stale raw-SQL allowlist entry for cursor route

The cursor auto-import route no longer contains raw SQL — that query
now lives in src/lib/cursor/tokenExtractor.ts, outside the
route/handler scope check-db-rules scans. The allowlist entry was
stale, tripping the stale-enforcement gate.

* fix(test): registers cursor test files in stryker tap.testFiles

Three unit test files covering mutation-tested modules
(route-guard-cursor-agent-availability, route-guard-cursor-refresh,
cursor-renewal) were missing from stryker.conf.json's tap.testFiles,
tripping the mutation-test-coverage gate's drift detection.

* chore(ci): retriggers checks (stuck GH Actions runner on shard 2/4)

* fix(sse): restores CC-relay context1m/redact-thinking test coverage

Rebasing onto release/v3.8.50's new tip (35405be60, an unrelated
agentrouter protocol-inference commit) silently flipped two assertions
this branch's own earlier fix (687fbda62) depends on, in the same test
files that commit touched for other reasons:

- executor-default-base.test.ts: calls[0] (a bare CC-relay with no
  requestDefaults) expected redact-thinking-beta absent; flipped to
  present. calls[1] (context1m+redactThinking requestDefaults) expected
  the context-1m beta preserved; flipped to absent.
- provider-request-failure-pipeline.test.ts: expected Accept:
  text/event-stream and the context-1m beta present for a relay with
  explicit requestDefaults; flipped to application/json and absent.

35405be60 did not touch open-sse/executors/base.ts at all, so these
were test-only edits made without visibility into the still-unmerged
CC-relay header-preservation fix on this branch — they quietly matched
the assertions back to the pre-fix (buggy) behavior instead. Restores
the original, validated expectations; all three interdependent test
files (executor-default-base, cc-compatible-provider,
provider-request-failure-pipeline) verified passing together again.

* ci: re-trigger checks after GitHub Actions incident (2026-08-07, resolved)

* ci: re-trigger checks (previous push event was dropped)

* fix(quality): restore dropped vi.json cursor-renewal keys + rebaseline test growth

vi.json was missing 4 keys (cursorSessionUnchanged, cursorAgentNudgeTitle/Body/Dismiss) that this PR's own pre-merge branch had translated -- the original merge's 'git checkout --theirs' resolution for the 7 conflicted locale files discarded them since upstream's vi.json has no cursor-token-renewal feature. Restored from pre-merge tip a38003e30. Also rebaselines combo-routing-engine.test.ts (3457->3464) for the comment growth from the ALL_ACCOUNTS_INACTIVE fix, caught by CI's PR-mode check:file-size.

* chore(tests): drop explanatory comments on ALL_TARGETS_SKIPPED assertions

Kept the assertion value fix (ALL_ACCOUNTS_INACTIVE -> ALL_TARGETS_SKIPPED); the comments were unnecessary. Reverts the file-size baseline bump these comments caused (combo-routing-engine.test.ts back to its original 3457).
2026-08-11 04:31:24 -03:00
Gioxa
ea085a1517 test(mcp): guard Node 24 bundled MCP startup (#9162) 2026-08-11 04:31:06 -03:00
Aman
58fa99406a fix(translator): honor Chat targets for Responses clients (#9161)
Honor explicit Chat targets for Responses-shaped clients while preserving native Responses providers and selecting token fields from the outbound protocol.

Includes focused regression coverage and the required changelog fragment.
2026-08-11 04:30:56 -03:00
3g0r1ch
2e799b33a7 fix: skills & memory — tool-name encoding, schema normalization, warm-cache, combo id, Ponytail catalog (#9058)
* feat(skills): add Ponytail minimalism skill as external catalog entry

- Add 'external' SkillCategory + SkillArea
- Register ponytail (MIT, DietrichGebert/ponytail) in CURATED_SKILLS
- Generator: external skills carry content in custom block, no api/cli body
- Generate skills/ponytail/SKILL.md with original content preserved
- Update catalog test counts 45 -> 46

* fix(skills+memory): builtin handler fallback in executor, skip vector upsert for deleted memories

- skills: Next.js compiles SkillExecutor into multiple chunks (own singleton
  each); route chunk lacked builtin handlers registered at startup via
  instrumentation. execute() now falls back to builtinSkills registry, so
  POST /api/skills/executions works for file_read/web_fetch/etc.
- memory: scheduleVectorUpsert is fire-and-forget and embeddings are slow;
  health-check verify (create->delete test memory) left queued upserts
  failing with 'memory not found' every 30s. Check existence before embedding
  and skip quietly.

* fix(skills): encode tool names with @ and . for providers rejecting them

Skill tools were advertised as 'name@version' (e.g. test-fr2@1.0.0), but
DeepSeek/Groq/OpenAI reject function names not matching ^[a-zA-Z0-9_-]+$.
Names already valid are left untouched; invalid ones are reversibly encoded
as omr_skill_<base64url> and decoded in interception before registry lookup.

* fix(combos): include DB id column in combo records for dashboard links

getCombos() selected only data/sort_order/context_cache_protection, so
combos whose JSON blob lacked an id field returned id: undefined. The
dashboard then linked to /dashboard/combos/undefined and Combo Control
Center failed with 'Combo not found'. Merge the id column into parsed
rows (authoritative, only when the blob has no id).

* fix(skills): normalize flat skill schemas to object schema for Gemini/Claude

Stored skill schemas are flat property maps ({ text: { type: string } }),
which OpenAI-compatible providers tolerate but Gemini
(function_declarations[].parameters) rejects with 'Unknown name ... Cannot
find field'. Wrap bare maps into { type: 'object', properties: {...} } for
all three tool formats.

* fix(skills): warm registry cache before skill injection in chat path

injectSkills() lists the in-memory skillRegistry, which is empty after a
cold start until something calls loadFromDatabase(). The interception path
already warms the cache (#2815); the injection path did not, so skills
were silently skipped (no_enabled_skills) for the first requests after
restart. Warm the cache for the chat owner before injection.

---------

Co-authored-by: Egor <egorich-print@users.noreply.github.com>
2026-08-11 04:30:38 -03:00
Arthur Bodera
8bdd29f835 fix(resilience): recover idle-capacity limiter wedges early (#9041)
* fix(resilience): recover idle-capacity limiter wedges early

* docs(changelog): note limiter wedge recovery

* fix(resilience): harden limiter wedge recovery

* fix(resilience): close limiter recovery review gaps

* test(resilience): preserve scoped exhaustion guards

* docs(changelog): remove self-credit suffix

* test: include limiter regressions in mutation coverage

* chore(quality): reconcile v3.8.50 file-size baselines

* fix(docs): add WAF MDX title frontmatter

* fix(docs): complete WAF frontmatter metadata
2026-08-11 04:30:29 -03:00
QZ
0a7e2934e4 feat(i18n): complete zh-CN localization for compression engines and dashboard UI (#9038)
* feat(i18n): complete zh-CN localization for compression engines and dashboard UI

- Translate all compression engine names and descriptions (Caveman, Lite,
  Aggressive, Ultra, OmniGlyph, Headroom, Session Dedup, RTK, CCR, LLMLingua)
- Translate all __MISSING__ entries (50+ strings) across settings, cache,
  OAuth, compression exclusions, and provider onboarding
- Translate hardcoded dashboard UI strings (analytics tables, playground,
  cliproxy/9Router exposure cards, Qdrant config, OneProxy, forgot-password)
- Localize PWA manifest and A2A agent card (manifest.ts, agent.json route)
- Add missing translation keys (hermes roles, API protocol, embedded services,
  memory/Qdrant, Obsidian, Codex auto-ping, reasoning routing)

* fix(i18n): restore cliCommon.comparison.acp keys dropped in the release merge

The release merge kept only the author's translated `flow` value and dropped
`title`, `desc` and `examples`, which exist on every sibling entry
(code/agent). Restore the three from the release while keeping the author's
`flow` translation.

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>

---------

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
2026-08-11 04:30:19 -03:00
rinseaid
1f45cf885c fix(vision): preserve images for text-only routes (#9037)
* fix(vision): preserve images for text-only routes

* fix(i18n): complete Vietnamese vision bridge copy

* fix(ci): drain prerelease tag input

---------

Co-authored-by: rinseaid <rinseaid@rinseaid.net>
2026-08-11 04:30:10 -03:00
Prudhvi Vuda
835de9d749 fix(sse): preserve Claude Code tool-name casing via Gemini/Antigravity (#9008) (#9016)
Stop blindly lowercasing PascalCase tool_use names on the Gemini→Claude path so Claude Code no longer rejects Read/WebSearch as missing tools.
2026-08-11 04:29:52 -03:00
Joshim Uddin
2129e91847 feat(combos): let combo builders test providers and add only working models (#9011) 2026-08-11 04:29:43 -03:00
Jan Leon
32f8340719 Fix custom tool output pairing during context compression (#8933)
* Fix custom tool output pairing during compression (#8932)

* Bypass proxy compaction for native Codex context

* fix(sse): extract Codex tool-call output repair to leaf module for file-size gate

repairMissingCodexToolCallOutputs (added by #8932 for custom_tool_call
pairing) pushed codex.ts past the frozen file-size baseline. Extract it
to open-sse/executors/codex/toolCallRepair.ts, leaving only the wiring
call in codex.ts. Rebaseline the test file's genuine +41 line growth
from #8932's new custom_tool_call_output coverage.

Co-authored-by: JxnLexn <JxnLexn@users.noreply.github.com>

---------

Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com>
Co-authored-by: JxnLexn <JxnLexn@users.noreply.github.com>
2026-08-11 04:25:55 -03:00
Emmanuel Frimpong Asante
c13763012a fix(i18n): localize SubscriptionTab UI strings instead of hardcoded Chinese (#8930)
The proxy subscription tab (System -> Proxy -> Subscriptions) displayed
Chinese text regardless of the selected language. The component called
useTranslations("settings") but bypassed t() for all ~50 UI strings.

- Replace every hardcoded Chinese string in SubscriptionTab.tsx with
  t("proxySubscription.<key>") calls
- Add 53 new keys under settings.proxySubscription to en.json (English)
  and zh-CN.json (Chinese) with full manual translations
- Propagate to all 41 other locales via generate-multilang.mjs (Google
  Translate), per docs/guides/I18N.md workflow

All 42 locales at 100% i18n coverage with zero __MISSING__ markers.
2026-08-11 04:25:44 -03:00
Apostol Apostolov
59ddcab6a7 feat: improve provider quota layouts (#8916)
* feat: improve provider quota layouts (#8916)

Adds Full/Compact layout toggle for provider quota cards. Compact mode
shows condensed card grid with key metrics; Full mode shows expanded
detail. Toggle persists via localStorage.

Changes:
- ProviderLimits/index.tsx: layout mode state + toggle button
- QuotaCardGrid.tsx: compact/full card rendering
- ProviderQuotaWidget.tsx: compact/home view
- HomePageClient.tsx: minor wiring fix
- tests/unit/quota-card-grid-compact-layout-8916.test.ts: structural guard
- file-size-baseline.json: rebaseline for ProviderLimits/index.tsx (1163)

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>

* fix(ci): restore providerId contract + reorder grid source + rebaseline translator drift

- ProviderQuotaWidget.tsx: restore size={18} on non-compact ProviderIcon
  to satisfy base-branch test #3064 pinned contract.
- QuotaCardGrid.tsx: reorder branches so non-compact (default) layout
  renders first in source. Same runtime behavior; satisfies base tests
  #3520/#6815/#7072 that inspect the first div/grid-cols class.
- file-size-baseline.json: bump testFrozen translator-openai-to-gemini
  1619->1622 (+3 upstream drift absorbed in merge of release/v3.8.50).

Closes upstream CI: Unit Tests 2/4, 3/4, 4/4 + Fast Quality Gates.
codeql-ratchet is upstream repo-wide (not our code) — external.

---------

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
2026-08-11 04:25:33 -03:00
Andrew B.
21fd0a94f8 feat(alibaba): free-tier routing with live quota sync (#8893)
* feat(alibaba): add free-tier routing with console quota and builtin allowlist

Classify DashScope free vs paid models via console quota API, a hardcoded
operator allowlist fallback, and per-connection drained tracking. Wire wildcard
combo expansion, model refresh, combo exhaustion, and audit redaction for
Alibaba console credentials.

* fix(routing): reset forced connection pin and persist Alibaba free-tier drain

Drop session affinity pins when a forced connection is excluded after 429,
and record Alibaba free-tier exhaustion on upstream 403 so per-key drained
lists stay accurate without blocking sibling keys.

* fix(alibaba): prefer live quota sync over static free-tier allowlist

Stop unioning the builtin text allowlist when a console quota snapshot exists,
treat expired quotaValidityPeriod as not_capable, and add a dated JSON pack plus
sync-alibaba-allowlist script for operator refresh without code edits.

* docs(alibaba): document free-tier console path + allowlist env overrides

Adds the 4 ALIBABA_FREE_TIER_*_FE_PATH / ALIBABA_FREE_TIER_ALLOWLIST_PATH
env vars (referenced by alibabaFreeTierQuotaFetcher.ts and
alibabaFreeTierAllowlist.ts) to .env.example and
docs/reference/ENVIRONMENT.md so the env/docs contract check passes.

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>

* refactor(open-sse): split alibabaFreeTierQuotaFetcher.ts under file-size cap

Extract pure parsing/classification/eligibility-filtering logic into
alibabaFreeTierQuotaClassify.ts and shared types/primitives into
alibabaFreeTierQuotaTypes.ts, leaving the HTTP/console-fetch flow in the
original file. Public API is unchanged (re-exported), behavior is identical.

Co-authored-by: AndrianBalanescu <AndrianBalanescu@users.noreply.github.com>

* fix: resolve typecheck errors in alibaba-free-tier routing

---------

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com>
Co-authored-by: AndrianBalanescu <AndrianBalanescu@users.noreply.github.com>
Co-authored-by: AndrianBalanescu <andrian@balanescu.dev>
2026-08-11 04:25:23 -03:00
Andrew B.
9a99a39b33 fix(antigravity): quota-aware account selection and projectId persistence (#8891)
* fix(antigravity): per-model quota + 30min credits_exhausted reprobe

- accountFallback.ts: hasPerModelQuota() now treats antigravity/agy as
  per-model quota. A single-model 429 no longer cascades to all models
  in the provider.
- connectionRecovery.ts: credits_exhausted removed from terminal set;
  isCreditsExhaustedReprobeCandidate() with 30min default. Loads
  active+inactive rows so inactive credits_exhausted accounts can recover.
- tests/unit/quota-connection-recovery.test.ts: 6 cases covering pure
  helpers + tick wiring.

* fix(antigravity): persist projectId and prefer healthy accounts

Save Cloud Code projectId after runtime discovery, skip accounts missing
projectId when alternatives exist, and mark missing_project_id on 422.

* fix(antigravity): skip quota-exhausted models during account selection

Avoid repeatedly dispatching to Antigravity models that already report
exhausted quota, reducing wasted upstream calls and combo fallback latency.

---------

Co-authored-by: hermes <hermes@nous.local>
2026-08-11 04:25:13 -03:00
Erick Kinnee
75c6a18a9b [v3.8.50] fix(api): serve stale model catalog during refresh (#8728)
* fix(api): make model catalog refresh response-safe

* fix(api): invalidate model catalog mutation paths

* fix(db): preserve aliases backup import after catalog rebase

---------

Co-authored-by: Erick Kinnee <erick@ekinnee.dev>
2026-08-11 04:25:03 -03:00
Mohit Rawat
324e28f438 fix(test): revive orphaned vitest tests and fix CI routing (#8718) 2026-08-11 04:24:54 -03:00
WITALO ROCHA
016c3fdb77 fix(github): honor per-model targetFormat override for Copilot custom models (#8713)
GithubExecutor.buildUrl() only consulted the static PROVIDER_MODELS registry
via getModelTargetFormat("gh", model), so a custom Copilot model (e.g.
gpt-5.6-terra/gpt-5.6-luna) with its dashboard "Target Format" set to
OpenAI Responses API always still routed to /chat/completions and got
rejected upstream with "model ... is not accessible via the
/chat/completions endpoint" — the setting had no effect on real routing.

chatCore already resolves the correct per-request targetFormat (including
the custom-model override) via resolveChatCoreTargetFormat(), but that value
was never threaded past chatCore into the executor's own URL-building
decision. Mirrors the zai/glm-coding-apikey fix (#7364) for the identical
class of bug: chatCore/executionCredentials.ts now surfaces the resolved
override onto providerSpecificData.targetFormat when it resolves to
openai-responses for the github provider, and GithubExecutor.buildUrl()
prefers that value over the static registry lookup when present.

Verified: 6 new regression tests plus all 95 pre-existing github/executor
tests green.

Co-authored-by: Wital <wital@example.com>
2026-08-11 04:24:44 -03:00
NOXX - Commiter
0135815c31 [v3.8.50] fix(adobe-firefly): durable session, Chrome recovery, browser sign-in (#8578)
* fix(adobe-firefly): durable session, off-screen Chrome recovery, browser sign-in

Rebuild x-arp-session-id from Cookie pieces (sid/ark/forter) so aux_sid is never
sent as ARP. Sticky ARP + submit spacing reduce mid-batch colligo 408 thrash.

Add optional managed Chrome warm (off-screen headed by default; Forter rejects
headless) and POST /api/providers/{id}/login browser sign-in that returns JWT+Cookie
after a fresh SSO. Visible sign-in resets off-screen window placement and clears
prior Adobe session when adding another account.

* fix(adobe-firefly): cast Node Buffer to ArrayBuffer and harden chrome runtime null close

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>

* fix(docs): sync docs-counts gate and env var contract for adobe-firefly

Update executor/OAuth-provider counts in ARCHITECTURE.md and
CODEBASE_DOCUMENTATION.md to match the real code (89 executors, 21
OAuth providers), and document the Adobe Firefly Chrome-driven
session-refresh env vars in .env.example and ENVIRONMENT.md so the
env/docs contract tests pass.

Co-authored-by: artickc <artickc@users.noreply.github.com>

---------

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com>
Co-authored-by: artickc <artickc@users.noreply.github.com>
2026-08-11 04:24:35 -03:00
NOXX - Commiter
a32ba5d566 [v3.8.50] fix(adobe-firefly): live x-arp-session-id / Arkose wire (stop HTTP 408) (#8571)
* feat(adobe-firefly): reference image attach + /v1/images/edits (follow-up #8006)

Upload source images to Firefly storage (POST /v2/storage/image) and attach
them as referenceBlobs on generate-async, matching live firefly.adobe.com
captures (usage:general for nano multi-ref; usage:subject for gpt-image).

Also wire built-in adobe-firefly through OpenAI-compatible POST /v1/images/edits
(multipart or JSON data URLs, up to 4 refs) so Media edit-with-references
and Open WebUI image-edit hit the same path as image2image generate.

Unit suite: tests/unit/adobe-firefly.test.ts 41/41.

* test(api): add route-level coverage for Adobe Firefly /v1/images/edits + fix typecheck/file-size drift

Covers the referenceBlobs upload path, the 4-reference cap error, and the
credentials/rate-limit branches added to the /v1/images/edits route for
adobe-firefly (#8510). Also fixes a Buffer/BodyInit typecheck mismatch in
uploadAdobeFireflyImage and corrects the adobeFireflyClient.ts file-size
baseline entry to match the gate's actual LOC count (it counts the trailing
newline, so the frozen value is 2317, not 2316), plus a testFrozen entry for
adobe-firefly.test.ts's own +159 line growth from this PR. Moves the
handleAdobeFireflyImageGeneration re-export out of the middle of the import
block in imageGeneration.ts for readability.

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>

---------

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
2026-08-11 04:24:25 -03:00
Paijo
bf1ad62f6e [v3.8.50] feat: extract CloakBrowser/browser-pool into optional plugin package (#8299)
* fix: align three stub implementations with original code

- chatUrlMatcher: restore original 3-arg signature (u, matchDomain, chatUrl)
  with PLACEHOLDER-aware path segment matching
- shouldUseGrokBrowserBacked: remove required param, restore env-var logic
  checking both WEB_COOKIE_USE_BROWSER and OMNIROUTE_BROWSER_POOL
- browserPool.ts: add Turbopack rationale comment and join-trick helper
  to satisfy the optional-import test assertions
- browserBackedChat.ts: replace any types with typed BrowserPoolModule interface

Verification: 40/40 browser node:test pass, typecheck:core 0 errors

* fix: remove duplicate getMod/modPromise in browserBackedChat stub

Two copies of the module proxy got committed — the typed BrowserPoolModule
version at lines 50-56 and a stale any-typed duplicate at lines 64-71.
Removed the duplicate, keeping the typed version.

Verification:
- 40/40 browser tests pass (both previously-failing suites now green)
- typecheck:core: 0 errors
- env kill switch (OMNIROUTE_BROWSER_POOL=off): verified

* fix(pr-8299): address all 5 review issues

Issue #1: Add @omniroute/browser-pool path to root tsconfig.json paths
Issue #2: Fix tryBackedChat fallback — call browserBackedChat outside if(loaded) guard
Issue #3: Fix grokClearance stub signature (signal?: AbortSignal) → string|null
Issue #4: Add comment clarifying async __resetBrowserPoolMetricsForTest vs upstream sync
Issue #5: Add test case for package-absent fallback in tryBackedChat

All 25 browser tests pass across 4 suites. typecheck:core passes.

* chore: move sqlite-vec to optionalDependencies, fix js-tiktoken static import

Both changes ensure native binary dependencies are properly categorized as optional:

- sqlite-vec: moved from dependencies to optionalDependencies. Only used via
  lazy _require("sqlite-vec") in vectorStore.ts — zero static imports.
- js-tiktoken: already in optionalDependencies, import changed to createRequire
  pattern to avoid crash when package is not installed (same pattern as sqlite-vec
  in vectorStore.ts).

Resolves ScoutDeps findings from browser-pool pluginization audit.

* docs(issues): fix stale interfaces.ts path in browser-pool proposal

The proposal originally planned open-sse/interfaces/browserPool.ts for
the BrowserPoolProvider interface, but the shipped implementation puts
it in packages/browser-pool/src/interfaces.ts instead. Update the
references so the doc matches what was actually built — the stale
path was tripping check:fabricated-docs (--strict).

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>

* fix: sync package-lock.json with playwright 1.62.0

Co-authored-by: oyi77 <oyi77@users.noreply.github.com>

* test: keep browser warmup disabled in tryBackedChat unit tests

* fix(pr-8299): keep grokClearance on the evolved release implementation (rebase reconciliation)

---------

Co-authored-by: oyi77 <oyi77@users.noreply.github.com>
Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com>
2026-08-11 04:24:16 -03:00
Gsantos
dce79714a8 [v3.8.50] feat(ui): add global model search to Combo builder (#8285)
* Feat: Busca Global de Modelos no Combo Builder

* Fix: assembleStandalone src and dest equality check on Windows

* fix(ui): i18n global model search + drop pnpm-lock + extract search panel

- Drop pnpm-lock.yaml (repo is npm-workspaces; package-lock.json is canonical).
- i18n: replace hardcoded Portuguese strings in the new global model search
  UI (Combo Builder) with getI18nOrFallback()/t() EN-fallback calls; add the
  10 new keys (builderModeStep, builderModeGlobal, builderGlobal*) to en.json
  and propagate __MISSING__ placeholders to all 42 locales.
- Extract the mode-toggle + global-search panel JSX into a new
  GlobalModelSearchPanel component, and the allGlobalModels/
  filteredGlobalModels/add-step/add-all logic into pure, unit-tested helpers
  (buildGlobalModelList, filterGlobalModelList, addGlobalModelStep,
  addAllGlobalSearchMatches) in src/lib/combos/builderDraft.ts, keeping
  combos/page.tsx under its frozen file-size budget.
- Revert the unrelated local-tooling .source/dynamic.ts one-liner to match
  origin/release/v3.8.49.
- Add unit tests for the new builderDraft helpers.

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>

---------

Co-authored-by: Gleisson de Jesus Santos <T034183@embasanet.ba.gov.br>
Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
Co-authored-by: ikelvingo <im.kelvinwong@gmail.com>
Co-authored-by: Diego Rodrigues de Sa e Souza <diegosouza.pw@gmail.com>
Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com>
2026-08-11 04:24:05 -03:00
Diego Rodrigues de Sa e Souza
7cde6bfe8a test(tail): retire stale i18n __MISSING__ repro + fix qianfan website URL (#8263)
Base-red slice 6, rebased onto the advanced release/v3.8.49 (91fd5f9). The oauth
grok-cli #7610 guard was already fixed on the base by #8027 (it reads the warning
from grokCliAuthJson.ts) — dropped from this slice to avoid a conflicting duplicate.
Remaining two, still red on the current base:

- i18n #7258: the "focused repro" asserted zh-TW.json STILL carries raw __MISSING__:
  placeholders. That backlog was filled (the "no locale has a raw __MISSING__: leaf"
  invariant is the durable guard); retired the now-inverted repro.
- qianfan: Baidu renamed the product page (product/wenxinworkshop -> product-s/
  qianfan_home); updated the expected website URL.

Validated (clean env): i18n 4/0, qianfan 5/0; oauth-modal-grok 2/0 already green on base.

Co-authored-by: Probe Test <probe@example.com>
2026-08-11 04:23:55 -03:00
Michael YC JO
a687e2b7e3 [v3.8.50] feat(ci): extend i18n glossary-consistency gate to ko (#8244)
* fix(dashboard): correct machine-translated Korean UI strings in ko.json

Fix 527 mistranslated values in the Korean locale, all verified against
the en.json source:

- Restore protected product/protocol names garbled by machine translation
  (응록→ngrok, 인류/인류학→Anthropic, 쌍둥이자리→Gemini, 반중력→Antigravity,
  꼬리비늘 깔때기→Tailscale Funnel, 진공→VACUUM, 우편번호→ZIP)
- Fix wrong-sense homonym translations (달리기→실행 중 for Running,
  장애인→비활성화됨 for Disabled, 열쇠→키 for Key, 안타→적중 for Hits,
  유물→아티팩트 for Artifacts, 건강검진→상태 확인 for Healthcheck)
- Repair translated identifiers that broke literal values (양말5→socks5,
  볼록-세션-id→convex-session-id, 채팅/완료→chat/completions,
  메시지/보내기→message/send JSON-RPC methods)
- Replace key-name dumps shipped as values ("Table Name", "Overview
  Title", "Cli Tools Redirect Title" etc.) with real Korean translations
- Unify ngrok casing (Ngrok→ngrok) and trailing punctuation with the
  English source; align terminology across fixes (공급자, 폴백, 사용자 정의)

All {placeholder} tokens, markdown, and protected terms preserved
verbatim; i18n UI coverage and ko validation gates pass.

* feat(ci): extend i18n glossary-consistency gate to ko

Follow-up to #8224 (ko.json mistranslation cleanup): the glossary gate
only checked zh-CN, leaving the Korean catalog unguarded against the
next machine-translation run reintroducing the garbage it fixed.

- Add scripts/i18n/glossary/ko.json: 9 canonical concepts (provider,
  fallback, running/disabled states, key, export, healthcheck, port,
  artifacts) plus protectedTermMistranslations for 10 verified garbled
  renderings (응록→ngrok, 인류→Anthropic, 쌍둥이자리→Gemini,
  반중력→Antigravity, 꼬리비늘→Tailscale, 진공→VACUUM, 양말5→socks5,
  우편번호→ZIP, 클로드→Claude, 옴니루트→OmniRoute)
- Extend check-glossary-consistency.mjs to merge per-locale
  protectedTermMistranslations from the glossary file with the legacy
  zh-CN KNOWN_MISTRANSLATIONS map (behavior for zh-CN unchanged)
- Add ngrok/Anthropic/Claude/Gemini/Antigravity/Tailscale/VACUUM/
  socks5/ZIP to protected-terms.json
- Wire --locale=ko into the i18n-glossary CI job and add the
  i18n:check-glossary:ko npm script
- Tests: merge semantics (3 new unit tests), #8224 regression guards
  for src + bin/cli ko catalogs, and real-file pass assertions for ko

Every enforced synonym/mistranslation was verified to have zero
occurrences in both real ko catalogs; collision-prone candidates
(안타 ⊂ 안타깝게도, 배우 ⊂ 배우기) were deliberately excluded.
2026-08-11 04:23:46 -03:00
Austin Liu
d634a66933 feat: add RTL layout compatibility CSS (fixes #7680) (#7987)
Co-authored-by: Austin Liu <austinliu@Austins-MacBook-Air-3.local>
2026-08-11 04:23:36 -03:00
Diego Rodrigues de Sa e Souza
5fd2325be7 fix(ratelimit): add queue-wait timeout tests and update sequencing tests (#9533) (#9662)
* fix(ratelimit): add queue-wait timeout and update sequencing tests (#9533)

* fix(combo): distinguish pre-dispatch skips from genuine failures to prevent false 503 ALL_ACCOUNTS_INACTIVE (#9630)

Closes #9630

---------

Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com>
2026-08-10 20:10:48 -03:00
Diego Rodrigues de Sa e Souza
3acb74fe0a feat(providers): add Muse Code CLI provider preset (#9544) (#9670)
* feat(providers): add Muse Code CLI provider preset (#9544)

* fix(providers): register muse-code canonical provider + golden snapshot

- Add muse-code to APIKEY_PROVIDERS_FRONTIER so check:provider-consistency passes
- Regenerate translate-path golden snapshot to include the muse-code entry
  (20 additive lines, no other providers changed)

---------

Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com>
2026-08-10 20:10:42 -03:00
Diego Rodrigues de Sa e Souza
0a1127be35 fix(ci): tighten unit suite ceiling from 100min to 80min (#9532) (#9678)
Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com>
2026-08-10 20:10:38 -03:00
Diego Rodrigues de Sa e Souza
44069c5f54 feat(providers): add DeepAI as paid image provider (#6671) (#9443)
* feat(providers): add DeepAI as paid API-key image provider (#6671)

* fix(api): restore accidentally deleted agent-skills coverage route

Commit a5212536c2 (DeepAI provider feature) deleted
src/app/api/agent-skills/coverage/route.ts by mistake while touching
unrelated files, breaking tests/unit/agentSkills-routes.test.ts
(ERR_MODULE_NOT_FOUND) and the openapi-routes doc-sync gate, which
still documents GET /api/agent-skills/coverage.

---------

Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com>
2026-08-10 20:10:33 -03:00
Diego Rodrigues de Sa e Souza
41208fa398 feat(images): add full combo strategy execution for image generation (#9239) (#9499)
Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com>
2026-08-10 20:10:29 -03:00
Diego Rodrigues de Sa e Souza
3797bbcd82 feat(providers): warm catalog startup from disk snapshot, parallel refresh (opencode-plugin) (#9490) (#9540)
Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com>
2026-08-10 20:10:24 -03:00