Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
35f4bab
fix(ci): drain the release/v3.8.51 base-reds — auggie/projectCombo ty…
diegosouzapw Sep 22, 2026
dedf1df
Merge remote-tracking branch 'origin/release/v3.8.51' into fix/releas…
diegosouzapw Sep 22, 2026
d5af54f
fix(sse): keep executor-consumed passthrough markers past the egress …
diegosouzapw Sep 22, 2026
1d4b3ca
test: select the DeepSeek Responses path explicitly and align the quo…
diegosouzapw Sep 22, 2026
11a9df1
test: align the quota-threshold and qwen-window guards with their new…
diegosouzapw Sep 22, 2026
a968955
Merge remote-tracking branch 'origin/release/v3.8.51' into fix/releas…
diegosouzapw Sep 22, 2026
62901a1
Merge remote-tracking branch 'origin/release/v3.8.51' into fix/releas…
diegosouzapw Sep 24, 2026
a016d7f
chore(quality): register nine covering tests the tip left out of stry…
diegosouzapw Sep 24, 2026
e1a7926
test: select DeepSeek's Responses alternate by targetFormat and follo…
diegosouzapw Sep 24, 2026
d316465
docs: document DEEP_HEALTH_CHECK_ENABLED (7d5292fc added the opt-in w…
diegosouzapw Sep 24, 2026
0a1bf1d
Merge remote-tracking branch 'origin/release/v3.8.51' into fix/releas…
diegosouzapw Sep 24, 2026
274e204
fix(compression): keep the effective-pipeline preview on the runtime'…
diegosouzapw Sep 24, 2026
4dd84c6
Merge remote-tracking branch 'origin/release/v3.8.51' into fix/releas…
diegosouzapw Sep 24, 2026
c32bb8a
fix(cliproxy): default the account-health probe host to 127.0.0.1 whe…
diegosouzapw Sep 24, 2026
9b68b80
chore(test): keep the tip's stryker order for the #14486 test entry
diegosouzapw Sep 24, 2026
55d641e
fix(ci): drain the next base-red wave — migration count 183, suno ret…
diegosouzapw Sep 24, 2026
0cd0dc0
Merge remote-tracking branch 'origin/release/v3.8.51' into fix/releas…
diegosouzapw Sep 24, 2026
a8550be
test(quality): allow the empty vitest-exclusions inventory #14493 rea…
diegosouzapw Sep 24, 2026
791775d
test(guardrails): isolate the subtitle-runtime fixtures in a per-run …
diegosouzapw Sep 24, 2026
5dd0f25
test: fold the DeepSeek Responses credentials into one fixture; short…
diegosouzapw Sep 24, 2026
62f113d
test: follow #14572's keepalive frame shape and #14421's Home setting…
diegosouzapw Sep 24, 2026
761f31e
Merge remote-tracking branch 'origin/release/v3.8.51' into fix/releas…
diegosouzapw Sep 24, 2026
1e2656a
chore(quality): absorb the 2026-09-23/24 merge-wave drift — file-size…
diegosouzapw Sep 24, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,11 @@ OMNIROUTE_USE_TURBOPACK=1
# Used by: src/lib/credentialHealth/scheduler.ts
# OMNIROUTE_DISABLE_CREDENTIAL_HEALTH_CHECK=false

# DEEP_HEALTH_CHECK_ENABLED: set to 1 to let an authenticated caller append ?deep=1 to
# /api/monitoring/health and sample the completions surface (cached per TTL). Off by default;
# anonymous callers never trigger a probe.
# DEEP_HEALTH_CHECK_ENABLED=0

# Set to "true" to emit `[ProxyFetch]` debug logs from the Vercel relay path
# in open-sse/utils/proxyFetch.ts. Off by default to avoid leaking routing
# hints in production logs.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
- **Build:** `open-sse/executors/auggie.ts` compiles again — the spawn-options helper constrained its `stdio` generic to `readonly string[]`, which matches no `spawn()` overload, and the broken overload cascaded into eight "possibly null" diagnostics on the child's streams. `src/app/api/v1/combos/projectCombo.ts` also imported three combo types from `comboStructure.ts`, which only uses them internally; they come from the combo type module.
- **Responses passthrough (regression from #14252):** the shared pre-executor strip removed `_nativeCodexPassthrough` and its siblings before the executor could read them, so every Responses-native Codex/xAI request was silently downgraded to the translated path and lost client fields (`metadata`) to the #2608 allowlist. Executor-consumed markers now survive to their reader and are still stripped at serialization, so #14252's leak fix is untouched.
- **Compression preview (regression from #14529):** the Settings-page "Effective pipeline" preview kept showing the configured lossy plan (e.g. `rtk → caveman`) while header-less requests had started running the safe `session-dedup → lite` pair, reopening #12063. The preview now goes through the same lossy-request policy as the runtime, so it shows what an ordinary request actually runs.
- **CLIProxyAPI account health (regression from #14544):** with only `CLIPROXYAPI_MANAGEMENT_KEY` set, the health probe targeted `http://undefined:<port>` and reported a correctly configured local CLIProxyAPI as unreachable (also the `typecheck:core` TS2322 on the release tip). It now falls back to the documented `127.0.0.1`.
4 changes: 3 additions & 1 deletion config/quality/dependency-allowlist.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
"@testing-library/user-event": "Utilitario oficial do ecossistema testing-library para testes de UI (adicionada no PR #11224); Refs #9985.",
"babel-plugin-react-compiler": "Official React Compiler Babel plugin (facebook/react, MIT). Required peer of Next.js 16 `reactCompiler: true`; Next declares it optional (`*`) and does not auto-install. Added by PR #11783 / issue #67.",
"eslint-plugin-react-hooks": "React Hooks lint rules (set-state-in-effect, immutability, refs, purity) pinned at 7.0.1 by the release/v3.8.51 cycle; the 224 findings it raised are tracked in #11924. Refs #11924.",
"vite": ""
"vite": "",
"@opencode/plugin": "Stable OpenCode 2.x plugin contract (npm maintainer thdxr = OpenCode author; successor of the beta @opencode-ai/plugin). Dev + peer dep of @omniroute/opencode-plugin-v2, added by PR #14370 without an allowlist entry; verified on npm 2026-09-23. Refs #14496."
},
"allowed": [
"@atjsh/llmlingua-2",
Expand All @@ -22,6 +23,7 @@
"@monaco-editor/react",
"@ngrok/ngrok",
"@opencode-ai/plugin",
"@opencode/plugin",
"@playwright/test",
"@size-limit/file",
"@stryker-mutator/core",
Expand Down
2 changes: 1 addition & 1 deletion config/quality/eslint-suppressions.json
Original file line number Diff line number Diff line change
Expand Up @@ -3297,7 +3297,7 @@
},
"tests/unit/compression/adaptive-select-plan-wiring.test.ts": {
"@typescript-eslint/no-explicit-any": {
"count": 3
"count": 2
}
},
"tests/unit/compression/caveman-engine.test.ts": {
Expand Down
24 changes: 14 additions & 10 deletions config/quality/file-size-baseline.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
{
"_rebaseline_2026_09_24_release_tip_merge_wave_drift": "Release-tip drift from the 2026-09-23/24 merge waves (fast-gates PR->release do not run check:file-size, so the tip crossed eight frozen ceilings with no offending branch left to fix in place). Measured on origin/release/v3.8.51 @7d23bcf8 with split(\"\\n\").length; most recent growth per file: src/app/(dashboard)/dashboard/settings/components/RoutingTab.tsx 1607->1618 (#14674); src/lib/db/apiKeys.ts 1671->1718 (#14597, #13861); src/shared/constants/providers/apikey/gateways.ts 1535->1544 (#14336); src/sse/handlers/chat.ts 2561->2563 (#14555, #14465); src/sse/services/auth.ts 3592->3595 (#14675, #14555); open-sse/executors/codex.ts 1570->1584 (#14677, #14636, #14572); open-sse/services/autoCombo/virtualFactory.ts 1230->1258 (#14584); open-sse/utils/stream.ts 3239->3262 (#14598). Structural shrink stays tracked in #3501.",
"_rebaseline_2026_09_24_14551_auto_clarity_integration": "Release-tip drift: #14551 (fix(compression): honor the Auto-Clarity toggle on the output-styles path, 8fc648b5) added 92 lines of Auto-Clarity coverage to tests/integration/chatcore-compression-integration.test.ts, taking the previously uncapped file to 1214 lines (> testCap 1200). Its merge note deferred the file-size follow-up; frozen here at the measured size so the tip goes green. Structural split stays tracked in #3501.",
"_rebaseline_2026_09_24_14511_basered_drain_tests": "PR #14511 (base-red drain #14496) test growth, measured after the pre-commit Prettier pass with split(\"\\n\").length: tests/unit/chatcore-translation-paths.test.ts 3546->3558 (+12: the DeepSeek Responses cases select the registry alternate through one shared credentials fixture after #14316 moved DeepSeek to Chat by default); tests/unit/account-fallback-service.test.ts 2072->2086 (+14: +3 own for #14530's connection-scoped breaker realignment, +11 from lint-staged Prettier reflowing two unformatted checkFallbackError calls the tip carried). Test-only; no production file grows.",
"_rebaseline_2026_09_23_applied_proxy_shared_context": "Own growth: open-sse/utils/proxyFetch.ts 1287->1294 (+7 = the shared-store key + store type + lazy getter, plus four one-line mechanical swaps at the existing call sites). Irreducible plumbing at the single store-identity chokepoint: every duplicated module copy must resolve the same AsyncLocalStorage instance so the fetch patch installed by one copy reads the capture sink opened by another; the store itself lives in the same file, no new module needed for 7 lines. Covered by tests/unit/proxy-fetch-applied-context.test.ts (3/3: single-copy trap, two-copy capture, sequential isolation) plus the neighbor suites proxyfetch-upstream-status-capture (9/9), proxy-fetch (9/9) and proxy-logs-upstream-status (4/4).",
"_rebaseline_2026_09_22_14069_model_not_in_catalog": "PR #14069 (@RaviTharuma) own growth: a live-catalog miss is now recorded as the model_not_in_catalog skip reason instead of collapsing into the generic availability bucket, so an unknown alias stops being reported as \"no credentials available\" (#14068). Measured on the tree reconciled with release/v3.8.51 @ea3c1226: src/sse/handlers/chat.ts 2559->2560 (+1 = the single modelInfo.errorType === \"model_not_found\" early return inside the existing isModelAvailable callback) and open-sse/services/combo/roundRobinCombo.ts 1261->1263 (+2 = the strict `available !== true` pre-check plus the sticky-target expression, which Prettier printWidth 100 reflows over three lines once it becomes `(await isModelAvailable(...)) === true`). Both files were already frozen exactly at their measured size with zero headroom (chat.ts was tightened to 2559 by #14223 on 2026-09-20), so the growth cannot be absorbed. These are call-site lines threading the new model_not_in_catalog skip reason through the two availability chokepoints and nothing else; the reason itself lives outside the frozen files, all under cap: the ModelAvailabilityResult union and modelAvailabilitySkipReason in open-sse/services/combo/types.ts, the COMBO_SKIP_REASONS entry in decisionTrace.ts and the threading in executeTargetGates.ts. Irreducible. Covered by tests/unit/combo/combo-skipped-targets-summary.test.ts. Structural shrink of both god-files stays tracked in #3501.",
"_rebaseline_2026_09_22_11725_cpa_auth_index": "PR for #11725 own growth: open-sse/handlers/chatCore.ts 6400->6402 (+2). Prettier printWidth 100 keeps the failure-usage cpaAuthIndex property and the readCpaAuthIndex import on their own lines; the streaming and non-streaming call sites stay on the existing endpoint line. The parser, stamp, and label join live in open-sse/handlers/chatCore/cpaTraceAuthIndex.ts (under cap). Covered by tests/unit/cpa-trace-auth-index.test.ts, tests/unit/cpa-auth-index-usage.test.ts, and tests/unit/db/migration-185-cpa-auth-index.test.ts.",
Expand Down Expand Up @@ -267,10 +270,11 @@
"_rebaseline_2026_09_04_12737_codex_ws_premature_close_tests": "PR #12737 own test growth: executor-codex.test.ts 1465->1620 (+155, entirely this PR's diff — regression coverage for the premature WebSocket close fix: emits terminal response.failed with code upstream_websocket_closed when the socket closes before any terminal event, and proves no second terminal event fires after a normal post-response.completed close).",
"_rebaseline_pr4613_compatible_provider_groups": "Reconcile #4613 already-merged growth: providers-page-utils.test.ts 1004->1052 (+48, buildCompatibleProviderGroups partition unit test). Fast-gate PR->release does not run check:file-size, so this surfaced post-merge.",
"tests/integration/chat-pipeline.test.ts": 1756,
"tests/unit/account-fallback-service.test.ts": 2072,
"tests/integration/chatcore-compression-integration.test.ts": 1214,
"tests/unit/account-fallback-service.test.ts": 2086,
"tests/unit/batch_api.test.ts": 1353,
"tests/unit/cc-compatible-provider.test.ts": 1225,
"tests/unit/chatcore-translation-paths.test.ts": 3546,
"tests/unit/chatcore-translation-paths.test.ts": 3558,
"tests/unit/chatgpt-web.test.ts": 4911,
"tests/unit/combo-routing-engine.test.ts": 3625,
"tests/unit/db-migration-runner.test.ts": 1509,
Expand Down Expand Up @@ -483,7 +487,7 @@
"open-sse/executors/antigravity.ts": 1717,
"open-sse/executors/base.ts": 1754,
"open-sse/executors/chatgpt-web.ts": 5056,
"open-sse/executors/codex.ts": 1570,
"open-sse/executors/codex.ts": 1584,
"open-sse/executors/cursor.ts": 1868,
"open-sse/executors/muse-spark-web.ts": 1405,
"open-sse/handlers/chatCore.ts": 6402,
Expand All @@ -498,7 +502,7 @@
"open-sse/translator/response/openai-responses.ts": 1518,
"open-sse/utils/cursorAgentProtobuf.ts": 1588,
"open-sse/utils/proxyFetch.ts": 1294,
"open-sse/utils/stream.ts": 3239,
"open-sse/utils/stream.ts": 3262,
"open-sse/vendor/codex-chatgpt-web/adapters/chatgpt-web/browser-worker.ts": 4398,
"open-sse/vendor/codex-chatgpt-web/bridge.ts": 1335,
"src/app/(dashboard)/dashboard/HomePageClient.tsx": 1344,
Expand All @@ -511,26 +515,26 @@
"src/app/(dashboard)/dashboard/runtime/RuntimePageClient.tsx": 1222,
"src/app/(dashboard)/dashboard/settings/components/ProxyRegistryManager.tsx": 1479,
"src/app/(dashboard)/dashboard/settings/components/ResilienceTab.tsx": 1271,
"src/app/(dashboard)/dashboard/settings/components/RoutingTab.tsx": 1607,
"src/app/(dashboard)/dashboard/settings/components/RoutingTab.tsx": 1618,
"src/app/(dashboard)/dashboard/settings/components/SystemStorageTab.tsx": 1598,
"src/app/(dashboard)/dashboard/usage/components/EvalsTab.tsx": 2152,
"src/app/api/providers/[id]/models/route.ts": 2432,
"src/app/api/providers/[id]/test/route.ts": 1252,
"src/app/api/v1/models/catalog.ts": 2127,
"src/app/docs/lib/openapi.generated.ts": 1347,
"src/lib/db/apiKeys.ts": 1671,
"src/lib/db/apiKeys.ts": 1718,
"src/lib/db/core.ts": 1800,
"src/lib/db/migrationRunner.ts": 1206,
"src/lib/tailscaleTunnel.ts": 1208,
"src/lib/tokenHealthCheck.ts": 1254,
"src/shared/components/RequestLoggerV2.tsx": 1748,
"src/shared/constants/providers/apikey/gateways.ts": 1535,
"src/shared/constants/providers/apikey/gateways.ts": 1544,
"src/shared/services/cliRuntime.ts": 1296,
"src/sse/handlers/chat.ts": 2561,
"src/sse/services/auth.ts": 3592,
"src/sse/handlers/chat.ts": 2563,
"src/sse/services/auth.ts": 3595,
"tests/unit/account-fallback-service.test.ts": 2453,
"tests/unit/provider-validation-specialty.test.ts": 4656,
"open-sse/services/autoCombo/virtualFactory.ts": 1230,
"open-sse/services/autoCombo/virtualFactory.ts": 1258,
"open-sse/services/combo/roundRobinCombo.ts": 1263,
"src/shared/components/RequestLoggerDetail.tsx": 1210,
"src/shared/middleware/chatBodyAdmission.ts": 1206,
Expand Down
1 change: 1 addition & 0 deletions docs/reference/ENVIRONMENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ OmniRoute uses **SQLite** (via `better-sqlite3`) for all persistence. These vari
| `CREDENTIAL_HEALTH_CHECK_INTERVAL` | `300000` | `open-sse/config/constants.ts` / `src/lib/credentialHealth/scheduler.ts` | Interval (ms) for the background credential health check scheduler. Minimum: 10000 (10s). |
| `CREDENTIAL_HEALTH_CACHE_TTL` | `300000` | `open-sse/config/constants.ts` / `src/lib/credentialHealth/cache.ts` | TTL (ms) for cached credential health status. |
| `OMNIROUTE_DISABLE_CREDENTIAL_HEALTH_CHECK` | `false` | `src/lib/credentialHealth/scheduler.ts` | Set to `1` or `true` to disable background periodic testing of provider connections. Search providers (SEARCH_VALIDATOR_CONFIGS in `src/lib/providers/validation/searchProviders.ts`, e.g. `tavily-search`) are always excluded from the sweep — their "validation" is a real billed upstream query, so they are never health-checked on a timer (#9970). |
| `DEEP_HEALTH_CHECK_ENABLED` | `0` | `src/app/api/monitoring/health/route.ts` | Set to `1` to allow an authenticated caller to request `/api/monitoring/health?deep=1`, which samples the completions surface once per TTL. Anonymous callers never trigger the probe. |
| `HOST` | `0.0.0.0` | `scripts/dev/run-next.mjs` | Bind address for the Next.js dev/start server. Overrides the default `0.0.0.0` when set. |
| `HOSTNAME` | `127.0.0.1` | `scripts/dev/run-next-playwright.mjs` | Bind address used by the Playwright runner when launching Next.js. Defaults to `127.0.0.1` for hermetic tests. **Do not use for `omniroute serve`** — use `OMNIROUTE_SERVER_HOST` instead (POSIX shells auto-set `HOSTNAME` to the machine name; `.env` cannot override it). |
| `OMNIROUTE_SERVER_HOST` | `0.0.0.0` | `bin/cli/commands/serve.mjs` | Bind address for `omniroute serve`. Avoids collision with the POSIX shell `HOSTNAME` variable (always set to the machine name by bash/zsh). Falls back to `0.0.0.0` when unset. (#6194) |
Expand Down
22 changes: 18 additions & 4 deletions open-sse/config/cliFingerprints.ts
Original file line number Diff line number Diff line change
Expand Up @@ -265,13 +265,22 @@ export function orderHeaders(
* Internal request-body markers that are NOT `_omniroute*`-prefixed and must be
* removed key-by-key. Everything else is caught by INTERNAL_BODY_FIELD_PREFIX.
*/
const INTERNAL_BODY_FIELDS: readonly string[] = [
/**
* Markers consumed by the EXECUTOR, not by routing: `codex.ts` and `xai.ts` read
* them to decide native passthrough and delete them right after. They must survive
* the shared pre-executor boundary (#14252) — stripping them there silently turns a
* Responses-native request into a translated one, which then loses client fields to
* the #2608 allowlist. They are still removed at serialization by applyFingerprint().
*/
export const EXECUTOR_CONSUMED_BODY_FIELDS: readonly string[] = [
"_claudeCodeRequiresLowercaseToolNames",
"_nativeCodexPassthrough",
"_nativeXaiResponsesPassthrough",
"_nativeOpenAICompatibleResponsesPassthrough",
];

const INTERNAL_BODY_FIELDS: readonly string[] = [...EXECUTOR_CONSUMED_BODY_FIELDS];

/**
* Every omniroute-owned internal marker uses this prefix, so the strip is
* prefix-based rather than an allowlist. An allowlist silently leaks each newly
Expand All @@ -290,12 +299,17 @@ const INTERNAL_BODY_FIELD_PREFIX = "_omniroute";
* Remove omniroute-internal markers from a request body before it is serialized
* for an upstream. Mutates and returns the same object.
*/
export function stripInternalBodyFields(body: unknown): unknown {
export function stripInternalBodyFields(
body: unknown,
options: { keepExecutorMarkers?: boolean } = {}
): unknown {
if (!body || typeof body !== "object" || Array.isArray(body)) return body;

const record = body as Record<string, unknown>;
for (const field of INTERNAL_BODY_FIELDS) {
delete record[field];
if (!options.keepExecutorMarkers) {
for (const field of INTERNAL_BODY_FIELDS) {
delete record[field];
}
}
for (const key of Object.keys(record)) {
if (key.startsWith(INTERNAL_BODY_FIELD_PREFIX)) {
Expand Down
8 changes: 6 additions & 2 deletions open-sse/executors/auggie.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
* 5. ~/.auggie/bin/auggie (alternate installer layout)
*/

import { spawn } from "node:child_process";
import { spawn, type StdioOptions } from "node:child_process";
import path from "node:path";
import os from "node:os";
import fs from "node:fs";
Expand Down Expand Up @@ -213,7 +213,11 @@ function buildAuggieArgs(model: string): string[] {
* elements to the shell, it does not concatenate them into a single
* command line.
*/
export function buildAuggieSpawnOptions<S extends readonly string[]>(
// #14496: `S extends readonly string[]` does not satisfy any `spawn()` overload
// (TS2769), and once the overload fails the returned ChildProcess is inferred
// without its stdio streams, which is where the TS18047 "possibly null" pile came
// from. Constraining to StdioOptions keeps the literal tuple AND matches spawn().
export function buildAuggieSpawnOptions<S extends StdioOptions>(
stdio: S
): {
env: NodeJS.ProcessEnv;
Expand Down
5 changes: 4 additions & 1 deletion open-sse/handlers/chatCore/upstreamBody.ts
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,10 @@ function normalizeAttemptBody(opts: PrepareUpstreamBodyOptions): Body {
// All models, including universal/context-handoff summary models, pass through
// this shared pre-executor boundary. Remove OmniRoute-only routing markers here
// so custom executors that serialize their own request bodies cannot leak them.
stripInternalBodyFields(bodyToSend);
// keepExecutorMarkers: `_native*Passthrough` is read by the executor further down
// (codex.ts/xai.ts) and deleted there; applyFingerprint() strips it at
// serialization. Removing it here would disable native passthrough (#14496).
stripInternalBodyFields(bodyToSend, { keepExecutorMarkers: true });
return bodyToSend;
}

Expand Down
Loading
Loading