Commit Graph

4572 Commits

Author SHA1 Message Date
KooshaPari
21d61c69d7 fix(integration): restore codex and memory pipeline contracts (#4474)
Thanks @KooshaPari! Rebased onto release/v3.8.32 (clean cherry-pick — coexists with #4467's specialty changes, 118/118 unit + 12/12 memory-pipeline integration). Codex fingerprint ordering + memory-search contract fixes land.
2026-06-21 08:58:49 -03:00
Abhishek Divekar
912239f46d feat(ui): expose targetFormat selector in custom-models form (#4475)
Thanks @adivekar-utexas! Rebuilt on release/v3.8.32 with just the UI commits (combo+command-code landed via #4472/#4473). Extracted a pure targetFormatBadgeI18nKey helper + added its unit test (Rule #18 gap) and reconciled the file-size baseline. targetFormat selector now ships.
2026-06-21 08:56:42 -03:00
Diego Rodrigues de Sa e Souza
fca66c6441 docs(changelog): reconcile v3.8.32 bullets for late cycle PRs (#4435/#4459/#4462/#4466/#4471/#4472/#4473/#4477/#4479/#4433) 2026-06-21 08:56:26 -03:00
Rahul sharma
620da16805 feat(models): add opt-in low-noise /v1/models catalog mode (#4427)
Thanks @Rahulsharma0810! Rebased onto release/v3.8.32. Opt-in MODELS_CATALOG_PREFIX_MODE (dual default = no change) ships; restored 4 incidental comments + reconciled catalog.ts file-size baseline (1478->1486) on review. 48/48.
2026-06-21 08:53:18 -03:00
NOXX - Commiter
404d9b327a perf(kiro): cut request-completion hot-path CPU + cap DB-lock event-loop block (#4459)
Thanks @artickc! Rebased onto release/v3.8.32. Added a regression guard for the terminal type-scan shortcut (the one change with correctness risk) — typed/event-line/OpenAI/[DONE] shapes all verified. CRC gate stays opt-in, busy_timeout is tuning, compact artifacts round-trip via JSON.parse. 4/4.
2026-06-21 08:50:06 -03:00
Tyler Ford
52e6a8b80f fix: model-aware supportsRedactedThinking for mixed-format providers (#4479)
Thanks @TF0rd! Rebased onto release/v3.8.32. Added the missing regression test for the model-aware redacted_thinking branch (Rule #18): minimax-m3 (claude format) gets redacted_thinking, glm-5.1 (openai) stays plain. 3/3.
2026-06-21 08:48:06 -03:00
janeza2
c3fd2b9aa1 feat(usage): support quota fetch for kimi-coding-apikey (#4435)
Thanks @janeza2! Rebased onto release/v3.8.32 and completed the end-to-end wiring on review: kimi-coding-apikey was missing from USAGE_SUPPORTED_PROVIDERS (dashboard 400) and USAGE_FETCHER_PROVIDERS (preflight) — added both + header-selection/wiring tests. Now fully routable.
2026-06-21 08:45:56 -03:00
Diego Rodrigues de Sa e Souza
66909a8b90 fix(cli): omniroute update revalidates npm cache with --prefer-online (#4376) (#4486) 2026-06-21 08:45:00 -03:00
KooshaPari
147b6a36a4 feat(cluster): add memory + bifrost opt-in profiles (#3932 follow-up) (#4433)
Thanks @KooshaPari! Rebased onto release/v3.8.32. Opt-in memory/bifrost compose profiles + BIFROST_ENABLED killswitch land (fixed the doc image to maximhq + frontmatter on review). qdrant-wiring 17/17.
2026-06-21 08:42:27 -03:00
KooshaPari
2f17be3286 perf(dashboard): lazy-load usage analytics charts (#4466)
Thanks @KooshaPari! Rebased onto release/v3.8.32. Recharts now lazy-loads (public analytics API preserved, source-guard test included).
2026-06-21 08:37:15 -03:00
Abhishek Divekar
3e980a0b2b fix(command-code): pass reasoning/thinking fields through to params (#4473)
Thanks @adivekar-utexas! Rebuilt on release/v3.8.32 with just the command-code commits (the combo half landed via #4472). reasoning/thinking passthrough + body.model rewrite now ship.
2026-06-21 08:36:25 -03:00
Abhishek Divekar
6c8c87dbb6 feat(combo): per-combo stickyRoundRobinLimit override on the combos page (#4472)
Thanks @adivekar-utexas! Rebased onto release/v3.8.32 (resolved the additive conflict with #3872's queueDepth). Per-combo stickyRoundRobinLimit override now ships.
2026-06-21 08:34:44 -03:00
CleanFix-Dev
131474d487 fix(usage): keep Kiro overage quotas routable (#4471)
Thanks @CleanDev-Fix! Rebased onto release/v3.8.32 and integrated. Kiro overage quotas now stay routable (verified the buildKiroUsageResult → isExhausted → auth filter chain). Ships in the upcoming release.
2026-06-21 08:32:41 -03:00
Diego Rodrigues de Sa e Souza
e95fab8bbe refactor(chatCore): extrai resolvers de service-tier do Codex para leaf puro (#3501) (#4477)
Integrated into release/v3.8.32
2026-06-21 08:30:20 -03:00
Diego Rodrigues de Sa e Souza
3b69960b3b fix(sse): unbiased crypto.randomInt for combo selection (follow-up to #4457) (#4462)
Integrated into release/v3.8.32
2026-06-21 08:30:17 -03:00
Diego Rodrigues de Sa e Souza
a7ebf0c2a0 fix(sse): don't bypass web-search fallback for Anthropic-compatible providers without server tools (#4481) (#4490) 2026-06-21 08:12:07 -03:00
diegosouzapw
f4ffbbb507 chore(quality): rebaseline deadExports 340->343 (v3.8.32 cycle drift) 2026-06-21 07:49:01 -03:00
diegosouzapw
1e2ef819b3 chore(release): v3.8.32 — 2026-06-21 2026-06-21 03:16:40 -03:00
Diego Rodrigues de Sa e Souza
0c47d13874 fix(dashboard): resume request-log auto-refresh by gating the ghost infinite-scroll load-more (#4269) (#4478)
* fix(dashboard): resume request-log auto-refresh by gating the ghost infinite-scroll load-more (#4269)

* chore(quality): rebaseline RequestLoggerV2.tsx file-size 1287->1316 (#4269 ghost-load-more fix)
2026-06-21 03:09:35 -03:00
Diego Rodrigues de Sa e Souza
b4dbf7b235 fix(executors): synthesize x-opencode-request for custom-named OpenCode providers (#4465) (#4476) 2026-06-21 02:43:04 -03:00
Diego Rodrigues de Sa e Souza
92afce6d09 fix(compression): RTK compresses Anthropic-shape tool_result blocks (#4468)
Integrated into release/v3.8.32
2026-06-21 02:41:08 -03:00
Diego Rodrigues de Sa e Souza
1e72643595 fix(providers): generic web-cookie validator must not shadow per-provider validators (#4467)
#4023 added validateWebCookieProvider (generic /models session ping -> AUTH_007
SESSION_EXPIRED on 401/403) and dispatched ALL web-cookie providers to it at the TOP
of validateProviderApiKey, BEFORE the SPECIALTY_VALIDATORS table. That shadowed the
rich per-provider validators (validateGrokWebProvider with #3474 IP-reputation/
Cloudflare guidance, validateChatGptWebProvider cf-mitigated, claude/gemini/copilot/
qwen/t3-web), which became dead code and broke all 41 web-cookie assertions in
provider-validation-specialty.test.ts (latent on release/v3.8.32; surfaced by a
__RUN_ALL__ unit run).

Move the generic dispatch to AFTER SPECIALTY_VALIDATORS so it is a FALLBACK only for
web-cookie providers without a dedicated validator. Rich validators run first
(provider-validation-specialty 112/112 restored); the generic + its AUTH_007
capability are preserved (web-cookie-auth007 stays 5/5, it calls the function directly).

Rebaselines validation.ts file-size 4518->4522 (+4, justified). Note: the sibling
pricing half of this restore-green already landed via #4447; this PR carries only the
stranded web-cookie validator fix.
2026-06-20 21:54:16 -03:00
Diego Rodrigues de Sa e Souza
12bfca6cec chore(quality): reconcile file-size + complexity baselines after /review-prs mine r2 (#4461)
Baseline reconcile for /review-prs mine r2 batch
2026-06-20 20:47:49 -03:00
Diego Rodrigues de Sa e Souza
8284650529 feat(routing): opt-in echo of requested alias/combo name in response model (#4450)
Integrated into release/v3.8.32
2026-06-20 20:37:37 -03:00
Diego Rodrigues de Sa e Souza
ee494d2c9a fix(antigravity): strip Anthropic-only output_config from Cloud Code envelope (port from 9router#1944) (#4431)
Integrated into release/v3.8.32
2026-06-20 20:35:41 -03:00
Diego Rodrigues de Sa e Souza
b0e9cd4f2b fix(combo): model lockout honors long upstream quota reset (#4429)
Integrated into release/v3.8.32
2026-06-20 20:33:44 -03:00
Diego Rodrigues de Sa e Souza
0d673f7c9e fix(translator): forward OpenAI audio input to Gemini/Antigravity (port from 9router#912) (#4426)
Integrated into release/v3.8.32
2026-06-20 20:27:04 -03:00
Diego Rodrigues de Sa e Souza
3025a2aa0a feat(oauth): import accounts from CLIProxyAPI auth files (port from 9router#1934) (#4458)
Integrated into release/v3.8.32
2026-06-20 20:26:53 -03:00
Diego Rodrigues de Sa e Souza
86fc1e4234 fix(sse): refactor stall detection to reduce false positives on slow but progressing streams (#4456)
Integrated into release/v3.8.32
2026-06-20 20:26:42 -03:00
Diego Rodrigues de Sa e Souza
7abace590d feat(translator): OpenAI SSE → Gemini SSE conversion for /v1beta/models route (#4453)
Integrated into release/v3.8.32
2026-06-20 20:26:19 -03:00
Diego Rodrigues de Sa e Souza
ce3909be86 fix(executors): sanitize Anthropic-shape content for Copilot /chat/completions (#4452)
Integrated into release/v3.8.32
2026-06-20 20:26:08 -03:00
Diego Rodrigues de Sa e Souza
9708feddc9 fix(translator): strip Claude output_config before MiniMax (#4448)
Integrated into release/v3.8.32
2026-06-20 20:25:50 -03:00
Diego Rodrigues de Sa e Souza
0403f29805 fix(executors): granular reasoning_effort handling for Claude models on Copilot (#4443)
Integrated into release/v3.8.32
2026-06-20 20:25:39 -03:00
Diego Rodrigues de Sa e Souza
53a3b597b2 fix(dashboard): surface manual config CTA when Claude CLI auto-detect fails (#4442)
Integrated into release/v3.8.32
2026-06-20 20:25:21 -03:00
Diego Rodrigues de Sa e Souza
3b25297110 fix(pricing): align Claude Code (cc) model pricing with Anthropic (#4440)
Integrated into release/v3.8.32
2026-06-20 20:25:11 -03:00
Diego Rodrigues de Sa e Souza
84fd18726d fix(usage): reuse Gemini CLI project ID for quota checks (#4454)
Integrated into release/v3.8.32
2026-06-20 20:25:00 -03:00
Diego Rodrigues de Sa e Souza
0225a0a02d fix(translator): sanitize Read tool args from non-Anthropic models (#4451)
Integrated into release/v3.8.32
2026-06-20 20:24:36 -03:00
Diego Rodrigues de Sa e Souza
bda88db555 fix(embeddings): forward output dimensions to Gemini (#4449)
Integrated into release/v3.8.32
2026-06-20 20:23:09 -03:00
Diego Rodrigues de Sa e Souza
9d7167094d fix(sse): use crypto-secure RNG for combo/deck load-balancing selection (CodeQL #665) (#4457)
Integrated into release/v3.8.32
2026-06-20 20:22:38 -03:00
Diego Rodrigues de Sa e Souza
7f62e50cba fix(catalog): add OpenAI gpt-4.1-mini/nano + o3-mini/o4-mini pricing rows (restore-green) (#4447)
Integrated into release/v3.8.32 (restore-green: OpenAI gpt-4.1-mini/nano + o3-mini/o4-mini pricing rows)
2026-06-20 20:17:52 -03:00
Diego Rodrigues de Sa e Souza
9052c5a783 fix(cli): non-interactive-safe prompts + singular context alias (#4439)
* fix(cli): non-interactive-safe prompts + singular `context` alias

Two CLI-polish follow-ups (the third — an async-warn refactor for #2807 — is moot:
#4373 replaced the Gemini remote-URL drop+warn with fileData pass-through, so no
async warn remains).

1) createPrompt (io.mjs) — the shared interactive helper used rl.question with no
   EOF guard, so a non-interactive stdin (pipe, CI, `< /dev/null`) left the await
   pending and Node warned about an 'unsettled top-level await' while the command
   hung. ask/askSecret now resolve on the readline `close` event (fired on EOF)
   with the default / empty string. A genuinely piped line still arrives via the
   question callback first, so `echo value | omniroute …` keeps working — only the
   no-input EOF case falls back. This fixes every command that prompts, centrally
   (mirrors the contexts `confirm()` fix from #4397).

2) `contexts` gains a singular `context` alias — the connect output and older docs
   said `omniroute context current`; the alias keeps that muscle-memory working.

Tests: cli-io.test.ts (ask default/empty + askSecret resolve on EOF, no hang) and a
cli-contexts.test.ts case asserting the `context` alias is registered. 11/11.

* test(cli): mock .alias() in the fake program for the contexts subcommand test

The existing 'registers a current subcommand' test uses a minimal fake commander
program; registerContexts now calls .alias("context"), so the fake needs an alias()
stub (returns this) or the chain throws. Add it. (Self-introduced by the alias in
this branch; my 4 new tests already pass in CI.)
2026-06-20 19:49:45 -03:00
Diego Rodrigues de Sa e Souza
95e6522720 feat(compression): unified config panel — single source for engine on/off + level (Phase 1) (#4432)
* docs(compression): design spec for the unified compression config panel

Engine-centric central panel (single source for master + per-engine on/off + level),
default pipeline derived from the engines map; Combos page owns named ordered pipelines +
active-profile selection; per-engine pages keep only detailed config. Phased: (1) core
consolidation + Model A migration, (2) named profiles + active selector, (3) per-request
x-omniroute-compression header.

* docs(compression): Phase 1 implementation plan for the unified config panel

12 TDD tasks: engine catalog, engines map + activeComboId, deriveDefaultPlan,
migration 102 + backfill, resolveCompressionPlan, runtime wiring, API, default-combo
shim, the engine-grid panel, consolidation, menu. Ends with a recap + the pending
follow-ups (Phase 2 named profiles/active selector, Phase 3 header, deferred items).

* feat(compression): engine catalog metadata (levels, single-mode, order)

* feat(compression): add engines map + activeComboId to CompressionConfig

* feat(compression): deriveDefaultPlan (engines map -> mode/pipeline)

Pure function that converts a per-engine EngineToggle map + masterEnabled
flag into a { mode, stackedPipeline } plan: off when master is off or no
engines on; single-mode when exactly one single-mode engine is enabled;
stacked (sorted by stackPriority) otherwise.

* feat(compression): persist+backfill engines map and activeComboId (migration 102)

* feat(compression): resolveCompressionPlan precedence resolver (header>override>active>default)

* feat(compression): selectCompressionStrategy uses resolveCompressionPlan

* feat(api): settings/compression carries engines map + activeComboId

Extends compressionSettingsUpdateSchema with engines (Record<string,{enabled:boolean,level?:string}>)
and activeComboId (string|null) so the PUT route accepts and persists these fields.
GET already returns the full getCompressionSettings() object which includes both fields.

TDD: added route round-trip tests (PUT+GET) for engines, activeComboId, null clear,
and schema rejection of invalid engines shape.

* refactor(compression): default-combo route is a read-only shim (default derived from engines)

* feat(dashboard): engine-grid compression panel (single source for on/off + level)

* refactor(dashboard): remove duplicate compression toggles; per-engine pages keep only detailed config

* feat(compression): unified panel menu order + derived-pipeline integration coverage

* fix(compression): import ENGINE_IDS via types re-export so it resolves under vitest

The bare "@omniroute/open-sse/.../engineCatalog.ts" specifier resolves under tsc/tsx
but not under vitest's MCP config: Vite externalizes a brand-new open-sse module to
Node, which can't load the .ts subpath. types.ts is already in Vite's graph, so route
ENGINE_IDS through its re-export. Fixes 3 failing MCP vitest suites (cacheTools,
dbHealthTool, essentialTools).

* fix(compression): engines map drives dispatch only when explicitly panel-saved

Code-review finding: the legacy seeded default combo (present on every install via
migration 042/043) was silently overriding a panel-configured engines map — the
default-combo block in chatCore set compressionComboApplied=true, skipping the
engines-map override, so an operator's panel toggles were ignored.

Gate the engines-map path on a new runtime-only CompressionConfig.enginesExplicit
(true when a stored engines row exists). Panel-saved installs: the engines map is
authoritative (deriveDefaultPlanFromConfig + new enginesMapDerivesStackedPipeline
guard the chatCore default-combo block). Legacy/backfilled installs: the map is
display-only and dispatch stays on the historical defaultMode/default-combo path —
zero behaviour change until the operator opts in via the panel.

Also documents why resolveCacheAwareConfig's getCacheAwareStrategy(config.defaultMode)
arg is safe (skipSystemPrompt is mode-independent).

* docs(compression): add MDX frontmatter + escape inline brace to fix fumadocs build

docs/compression/**/*.md is compiled as MDX by the Next build (fumadocs,
source.config.ts). The two planning docs lacked the required `title`
frontmatter (build error: 'title: expected string, received undefined') and the
design doc had a bare {rtk,caveman} that MDX parsed as a JSX expression. Adds
frontmatter matching the sibling docs and backticks the brace. Fixes the
dast-smoke build step.
2026-06-20 19:07:39 -03:00
Paijo
3ad2043327 feat(providers): web-cookie + no-auth provider validation with AUTH_007 (#4023) (#4023)
Integrated into release/v3.8.32 — web-cookie + no-auth provider validation (AUTH_007 SESSION_EXPIRED detection).
2026-06-20 18:27:33 -03:00
Diego Rodrigues de Sa e Souza
63095a55f6 docs(remote-mode): add a copy-paste end-to-end verification example (#4430)
Future-reference 'Quick end-to-end check' in REMOTE-MODE.md: connect -> mint scoped
token -> route a command -> switch back -> tear down, with a placeholder host. Makes
explicit (and verified live) that `contexts remove` is LOCAL-only — it drops the saved
credential but does NOT revoke the server-side token; use `tokens revoke <id>` to kill
access. Also documents that `--yes` is required for non-interactive removal and that
removing the active context falls back to default.
2026-06-20 18:26:45 -03:00
Paijo
7c56f47073 chore: rebase PR #3455 onto release/v3.8.32 (autonomous monitor cycle 1) (#3455)
Integrated into release/v3.8.32 — operational docs (usage/quota, open-sse architecture, database, monitoring).
2026-06-20 17:47:24 -03:00
Diego Rodrigues de Sa e Souza
285608c7e6 chore(quality): reconcile server.ts file-size baseline 1468->1509 (#3368 pool tools) (#4423) 2026-06-20 17:18:20 -03:00
Diego Rodrigues de Sa e Souza
d215079f66 fix(translator): inject placeholder message when Responses API input[] is empty (#4393)
A client (e.g. Fabric-AI) calling POST /v1/responses with `input: []`
used to be translated into `messages: []`, which every upstream Chat-
Completions provider rejects with `400: at least one message is required`
(surfaced to the client as a confusing 406).

Mirror the existing empty-string handling: when input[] is empty, inject
a single placeholder user message so the request is always valid. Touches
`openaiResponsesToOpenAIRequest` only (the same translator that already
covers the empty-string case at the top of the function), preserves any
caller-supplied `instructions` as a system message, and leaves every
non-empty input path byte-identical.

Adds a TDD test reproducing the empty input[] case (RED before fix, GREEN
after) and updates one pre-existing test that enshrined the broken
behavior (`assert.deepEqual(call.body.messages, [])`) to assert the new
correct shape.


Inspired-by: https://github.com/decolua/9router/pull/419

Co-authored-by: anuragg-saxenaa <anuragg.saxenaa@gmail.com>
2026-06-20 17:07:51 -03:00
Diego Rodrigues de Sa e Souza
13288e265a feat(providers): expand openai/gemini direct registries with first-class missing variants (#4394)
OmniRoute already references gpt-4.1-mini, gpt-4.1-nano, o3-mini, and o4-mini
throughout sibling subsystems (cost estimator, modelCapabilities, taskFitness,
free-model catalog, multiple aggregator registries) but the direct openai
provider entry exposes only o3/gpt-4.1. Symmetrically, the gemini entry has
gemini-2.0-flash and gemini-3.1-flash-lite-preview but not the lite/lite-preview
siblings that pair with them. Inspired by an upstream effort to refresh both
static lists; scope is intentionally minimal:

- ADD openai: gpt-4.1-mini, gpt-4.1-nano, o3-mini, o4-mini
  (o3-mini/o4-mini get REASONING_UNSUPPORTED, matching the o3 entry)
- ADD gemini: gemini-2.0-flash-lite, gemini-3-flash-lite-preview

SKIP (already present elsewhere — kept in their typed registries):
- TTS (tts-1, tts-1-hd, gpt-4o-mini-tts)            -> audioRegistry.ts
- OpenAI embeddings (text-embedding-3-small/-large/ada-002) -> embeddingRegistry.ts
- Gemini embeddings (text-embedding-00*, gemini-embedding-*) -> embeddingRegistry.ts
- gemini-3.1-flash-image-preview                   -> imageRegistry.ts

SKIP (deliberate OmniRoute curation):
- gpt-5/gpt-5-mini/gpt-5-nano/gpt-5.1/gpt-5.2 (superseded by gpt-5.4 series)
- o1, o1-mini (superseded by o3)
- gpt-4-turbo (legacy; gpt-4o is the canonical mid-tier)
- o3-pro (no references anywhere in OmniRoute)

TDD: tests/unit/provider-registry-openai-gemini-expanded-models.test.ts
asserts the new ids and pins the existing ids so a future refactor cannot
silently drop them.


Inspired-by: https://github.com/decolua/9router/pull/398

Co-authored-by: Ibrahim Ryan <ryan@nuevanext.com>
2026-06-20 17:05:11 -03:00
Diego Rodrigues de Sa e Souza
23f38630e3 fix(providers): serve api.airforce live /models catalog instead of stale seed (#4395)
api-airforce carries a real live https://api.airforce/v1/models catalog but was
left out of NAMED_OPENAI_STYLE_PROVIDERS, so the import route served its small
hardcoded seed (grok-3, grok-2-1212, claude-3.7-sonnet …) — models that no
longer exist upstream, so chat failed even though the connection test passed.

Add api-airforce to NAMED_OPENAI_STYLE_PROVIDERS (same shape as #4249/#4202/#3976
and the provider-model-sweep rows) so import does a live <baseUrl>/models fetch.
The registry seed stays as the offline fallback, so import never breaks if the
upstream is unreachable.

TDD: extends tests/unit/provider-sweep-live-discovery.test.ts (red proven: the
api-airforce case did not probe upstream and served local_catalog).
2026-06-20 17:04:09 -03:00
Diego Rodrigues de Sa e Souza
1a9d29a9bc fix(providers): register Firecrawl and Jina Reader API-key validators (#4401) (#4412) 2026-06-20 17:01:14 -03:00