mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-12 18:22:48 +03:00
2129e918479cd48cefd9a2266172f6b3fbf0c630
406 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
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> |
||
|
|
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> |
||
|
|
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.
|
||
|
|
0a1127be35 |
fix(ci): tighten unit suite ceiling from 100min to 80min (#9532) (#9678)
Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com> |
||
|
|
995618d27a |
feat(quality): detect forgotten sibling tests in PRs (#9530) (#10009)
Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com> |
||
|
|
9105220242 |
fix: resolve hollow external package directory crashes and implement duckduckgo search fallback (#9913)
Co-authored-by: SupremeNexas <SupremeNexas@users.noreply.github.com> Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com> |
||
|
|
b80afbb74f |
fix(proxy): isolate TLS sessions by account (#9837)
Co-authored-by: Antigravity Agent (via Agisota) <agisota@users.noreply.github.com> |
||
|
|
ab8f3e83b7 |
fix(ci): allow test-masking to finish in release preflight (#9964)
Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com> |
||
|
|
181828625b | fix: clear release unit and quality regressions | ||
|
|
754ba0fa86 | fix(release): repair post-sweep base regressions | ||
|
|
d8967efc6c |
cherry-pick(pr-9605): ci(test): route orphaned Vitest tests through blocking CI (#9875)
* 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: MohitRawat017 <rawatmohit17906@gmail.com> Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com> |
||
|
|
bc38965088 |
maint: follow-up cherry-pick fix-in-place #9712 (conflict-resolved fallback) (#9892)
* fix(build): colocateLlmlinguaOptionals skip-check treated a Next-traced stub as fully copied Debugging the omniroute-beta Docker rebuild: `npm run build` (and the Dockerfile's own post-build verification) failed with `Cannot find module '.../node_modules/@atjsh/llmlingua-2/dist/index.js'`. Root cause, reproduced directly (both against a live Docker builder image and in a unit test): Next.js's own standalone trace creates a stub directory for `@atjsh/llmlingua-2` containing only `package.json` — it references the package (a dynamically-imported optional dependency) but can't fully bundle it. colocateLlmlinguaOptionals's skip checks (both the closure-level early return and the per-package loop) only tested `existsSync(dest)`, so that stub was indistinguishable from "already fully co-located" — the function skipped copying the real `dist/` output entirely, silently shipping a package with a manifest but no code. Fix: check for the package's declared `main` entry file when it has one (the real-world case for every actual SLM optional). Packages with no `main` field fall back to comparing the destination's top-level entries against the source's — correct both for genuinely multi-file packages and for a metadata-only source (package.json is then its complete, faithfully- copied contents), which the existing idempotency test exercises. Covered by tests/unit/colocate-optionals.test.ts's new stub-reproduction case (fails against the pre-fix code, passes after — confirmed directly) plus the 6 pre-existing cases, all still green. (cherry picked from commit |
||
|
|
a448b146bf |
cherry-pick(pr-9744): test(integration): add general live-test tool for the real "default" combo + rootless wire capture (#9862)
* test(integration): add general live-test tool for the real "default" combo Temporary WIP commit on this deferred branch — lands in its own separate PR once the bug-fix extraction batch is done (never bundled into a bug-fix PR). Unlike liveGeminiShared.ts (provisions its own narrow 2-model Gemini-only combo), this reads the REAL "default" combo currently configured on the target instance directly from the DB and exercises every provider/model step in it directly, bypassing combo routing, so live-test coverage always matches whatever is actually configured instead of a hardcoded snapshot. Live-verified against omniroute-beta (seeded with the real 18-model, 5-provider default combo): 14/18 models pass consistently across non-streaming + streaming Chat Completions and streaming Responses API. The 4 consistent failures are real external state (cerebras credits_exhausted, one deprecated openrouter free-tier model), not code regressions. (cherry picked from commit c40b13a48fd897259c56f5122e9e57a3dc7654ba) * test(integration): add rootless wire-capture correlation to the live-test tool Temporary WIP commit on this deferred branch — lands in the same final live-test-tool PR as the general default-combo suite, never bundled into a bug-fix PR. liveContainerHarness.ts spins up a dedicated, throwaway podman container (same runner-base image target as the operator's local dev/beta containers) so wire-capture tests are fully self-contained: builds the image if missing, starts the container with a persistent data dir, waits for health, seeds the real "default" combo + provider connections from the operator's local omniroute-dev instance (idempotent — only runs once per data dir), and provisions API keys via the running instance's own auth flow. wireCapture.ts captures the container's actual network traffic via `podman unshare nsenter --net=<container netns> -- tcpdump` — no root needed, verified working live (this generalizes the root-requiring `sudo nsenter -t $PID` command scripts/sre/tcp-close-analyzer.py already documented for the same rootless-Podman netns problem; that script's docstring now documents both). Capture and analysis needed two real fixes found only by running the pipeline live: `-U` (unbuffered tcpdump writes) plus a `pkill -f <pcap path>` fallback, since `podman unshare -> nsenter -> tcpdump` is a 3-level subprocess chain and SIGTERM to the top-level process doesn't reach the tcpdump grandchild, leaving an orphaned process and a truncated/unreadable pcap; and filtering on the container's internal listening port (20128) rather than the dynamically-assigned host port, since capture happens inside the container's own network namespace where only the internal port is meaningful. live-default-combo-wire-capture.test.ts (gated on RUN_LIVE_WIRE_CAPTURE=1) ties it together: sends a small representative sample of requests through the real default combo, then cross-checks each one's app-level JSON status against the actual HTTP status line observed on the wire via scripts/sre/tcp-close-analyzer.py's stream reassembly — catching bugs where the app layer claims success but the wire shows a truncated/reset stream, not just what liveDefaultComboShared.ts's existing breadth suite already covers. Live-verified end-to-end: 4/4 sampled requests correlated correctly across 8 captured TCP streams, container + capture process fully torn down afterward (verified no orphaned podman container or tcpdump process left running). sendModelRequest/filterActiveModelTargets (liveDefaultComboShared.ts) gain optional baseUrl/apiKey overrides, defaulting to the existing module-level omniroute-beta target, so the wire-capture suite can point the same request-sending logic at its own dedicated container instead. (cherry picked from commit 914a7e42cbe914f257db9f72eedc902ee1532083) --------- Co-authored-by: Markus Hartung <mail@hartmark.se> |
||
|
|
aae408f585 |
Merge pull request #9296 from artickc/fix/adobe-firefly-model-capabilities
fix(adobe-firefly): sync discovered models and capabilities |
||
|
|
2e12ee89f7 |
Merge remote-tracking branch 'origin/release/v3.8.50' into fix/merge-pr-9296
# Conflicts: # open-sse/config/imageRegistry.ts # open-sse/handlers/imageGeneration/providers/adobeFirefly.ts # open-sse/services/adobeFireflyClient.ts # tests/unit/adobe-firefly.test.ts |
||
|
|
e0ce95c592 |
fix(ci): close remaining release-green gaps (#9835)
Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com> |
||
|
|
77cce62357 |
fix(ci): restore current release test integrity (#9819)
* fix(ci): restore base test integrity * fix(quality): clear inherited fast gate drift * fix(ci): clear inherited unit test reds * fix(i18n): preserve Vietnamese catalog parity * fix(i18n): preserve Portuguese catalog parity --------- Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com> |
||
|
|
6c95e2b354 |
fix(build): include better-sqlite3 prebuilds in standalone bun bundle (#8847)
Refs: base-red #9737 |
||
|
|
63cf354129 |
fix(docker): complete partially traced packages in standalone co-location (#9615)
* fix(docker): complete partially traced packages in standalone co-location Publish-to-Docker-Hub has failed on every release/v3.8.50 push since #9151 enabled publishing from active release branches: the post-build guard dies with "Cannot find module .../@atjsh/llmlingua-2/dist/index.js" while the co-location step right above it reports 100 packages copied. Root cause: Next's file tracing materializes @atjsh/llmlingua-2 PARTIALLY in the standalone (package.json lands, the dist/ payload its main points at does not). colocateOptionals' no-clobber checked existsSync on the package DIRECTORY, so the partial shell counted as present and the one package that mattered was skipped forever (#9185 added the closure walk but kept the directory-level check). Fix: presence is now judged by entrypoint integrity — the package resolves from inside the target tree (same contract as the Dockerfile guard). Partial directories are completed with a file-level no-clobber merge (cpSync force:false), so files the trace did materialize are never overwritten and pinned instances (dist transformers 3.5.2) keep their protection. Validation (TDD): 2 new tests in docker-llmlingua-optionals-9166.test.ts reproduce the CI failure (partial package skipped; closure-wide early-exit firing while a member is partial) — red on the old code, 5/5 green after. * fix: update colocate test mock packages to match isPackageIntact entrypoint resolution The PR's isPackageIntact check uses require.resolve to validate that co-located packages have a usable entrypoint inside the target tree. The pre-existing test's mock packages lacked main fields and index files, so require.resolve failed and the idempotency assertion broke. Update buildRoot() to give every closure package a resolvable entry (main + index.js), mirroring what real npm packages ship. Refs #9615 * docs(changelog): fragment for #9615 * fix(yuanbao-web): accept content field in SSE text events (upstream format change) (#8739) Closes #8739 * fix(errorClassifier): classify ChatGPT Web SENTINEL_BLOCKED 403 as FORBIDDEN, enabling combo fallback (#8813) Closes #8813 * fix(vertex): route Claude models to native rawPredict and respect targetFormat overrides (#8994) Closes #8994 * fix(cursor): preserve tool context across multi-turn conversations when client lacks conversation_id (#9029) Closes #9029 * fix(sse): move Antigravity client system content to first user message to avoid upstream 429 (#9030) Closes #9030 * fix(combo): distinguish pre-dispatch skips from genuine failures to prevent false 503 ALL_ACCOUNTS_INACTIVE (#9630) Closes #9630 * fix: repair stray brace in combo.ts and fix no-explicit-any types in repro-9630 test --------- Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com> |
||
|
|
36abd86929 |
fix(ci): clear the 08-08 base-red layers — dead-code, prod crash in chat.ts, Responses payload regression, born-red stdio test, gate drifts (#9757)
* fix(ci): drop unused RadarReferrals type export — dead-code ratchet back to 227 baseline The radar referral-links feature (#9697) exported the inferred type RadarReferrals from feedSchema.ts but nothing imports it (the singular RadarReferral is the consumed type). knip counts it as a new dead export, pushing the dead-code ratchet to 228 > 227 and failing Fast Quality Gates on every PR born after the merge. RadarReferralsSchema itself stays — it is used by RadarFeedSchema. Refs #9737 * fix(ci): clear the 08-08 base-red layer — prod crash in chat.ts, Responses API payload regression, born-red stdio test, gate drifts Six independent base-reds from the 08-07 evening merge batch, each verified against the pure release/v3.8.50 tip: - src/sse/handlers/chat.ts: #9467's squash carried a refactor hunk that renamed the all-rate-limited breaker guard to an UNDEFINED variable (isAllRateLimited) — a production ReferenceError on the all-accounts-429 path (chat.ts is outside typecheck:core scope, so only tests caught it). Restore credentials?.allRateLimited. Guard: chat-rate-limit-body-lock (2/2), also un-breaks batch_api and chat-combo-live-test. - open-sse/utils/stream.ts: #9315 switched providerPayload summaries to the accumulated responseBody, but in passthrough paths that body is synthesized in chat-completion shape — Responses API lost its `response` object in the dashboard payload. Keep the events-derived summary for OPENAI_RESPONSES only. Guard: stream-utils + stream-collector-9315 suites (51/51). - tests/unit/mcp-stdio-json-purity.test.ts: born red — the full CLI chain takes ~10s (2x tsx import + DB init) and the test slept a fixed 4s. Poll for the first stdout line with a 60s deadline instead. - tests/unit/plugins-route-error-sanitization.test.ts: register #9445's new marketplace/install route in PLUGIN_ROUTES (route already sanitizes) (33/33). - tests/unit/provider-models-route-codex.test.ts: realign pinned GPT-5.6 input limit to #9432's deliberate 272000→922000 bump (7/7). - lint: fix 11 no-explicit-any errors in repro-9630 + specialty-9293 tests, prune 1 orphaned suppression, allowlist the opencode-ai devDependency (#8869, publisher-verified), and reword a doc line the fabricated-docs gate misread as an env var. Gates re-verified locally: lint:json --max-warnings 0 exit 0, dead-code 227, typecheck:core clean, check:deps OK, check:fabricated-docs OK. Refs #9737 * fix(ci): clear the third 08-08 base-red layer — invalid ru rule pack, stale event pin, orphaned UI repro test, pack/mutation/file-size drifts Follow-up to the previous layer: the serial fast-gates chain unmasked one more stratum after file-size/dead-code went green, all verified against the merged release/v3.8.50 tip: - compression rules ru/ultra.json (#9581): two rules shipped minIntensity "notes", which is not a valid CavemanIntensity (lite|full|ultra) — loading ANY language pack list threw and killed the rtk-loader suite. Mapped both to "ultra" (they are the most aggressive punctuation/case rules, matching the en pack tiers). 2/2. - plugins-welcome-banner-e2e: #9668 added the onStreamComplete builtin event (real emission path via runOnStreamCompleteHooks) and missed this pinned-list sibling. 35/35. - tests/unit/free-pool-frontend-repro (#9046): landed as .tsx with node:test semantics — no runner collects tests/unit/*.tsx, so it NEVER ran (test-discovery NEW-orphan). It contains zero JSX; renamed to .test.ts so the unit runner's existing glob collects it. 5/5 (first real run). - pack-policy: allow + require bin/mcpStdioConsoleGuard.mjs (#9281) — it is preloaded via node --import by bin/mcp-server.mjs, so a published artifact without it crashes 'omniroute --mcp' at startup. - stryker.conf.json: add 5 covering unit tests from the batch (#8779/#9204/ #9330/#9630/openrouter-passthrough) to tap.testFiles (--strict drift). - file-size-baseline: consolidate the base-drift rebaseline for the 12 files grown by the 08-06..08-08 batches (#9616's entries never reached the base; measured on this branch's tree — this PR's own source edits add zero lines to any frozen file). Local battery: file-size/deps/test-discovery/mutation/pack-policy/dead-code/ duplication/docs-all/secrets/vuln/workflows ratchets all exit 0; full lint gate --max-warnings 0 exit 0. Refs #9737 * fix(types): clear the 3 uncovered open-sse-typecheck regressions + realign combo skip-code siblings Fourth base-red layer unmasked by the serial gates. The other 4 typecheck regressions (codex.ts, kiro.ts, tierResolver.test.ts, translator/index.ts) already have dedicated open [TS7] PRs (#9748/#9753/#9742/#9747) — not duplicated here. This commit covers only what no open PR owns: - devin-agentic/serializer.ts TS2367: drop the dead 'role === "system"' branch — the guard above already narrows role to user|assistant (system throws unsupported_role). Devin suites 104/104. - raycast.ts TS2416: the buildHeaders 'override' never matched the base signature (2nd param is the signed payload string, not the stream boolean) — renamed to a private buildRaycastRequestHeaders helper so a polymorphic buildHeaders(credentials, true) call can never bind here. - modelMetadataRegistry.ts TS2352: PricingByProvider → nested-record cast now goes through unknown (shape is runtime-guarded by findInsensitive). - combo-routing-engine.test.ts: realign 2 pre-dispatch-skip expectations to #9630's deliberate ALL_TARGETS_SKIPPED contract (87/87). Refs #9737 * fix(ci): clear the fifth 08-08 base-red layer — reasoning-placeholder contract sweep, GPT-5.6 limits sweep, vi key parity The 08-08 merges (#9610 reasoning replay, #9432 GPT-5.6 limits, #9630 combo skip codes, #9336 provider key links) each changed a contract and left sibling tests pinning the old one. Full grep sweep per contract, not just the shard that happened to go red: - reasoning placeholder (#9573/#9610): the fix DELIBERATELY removed NON_ANTHROPIC_THINKING_PLACEHOLDER injection on cache miss — the model echoed the placeholder as its own reasoning (empty stop) and re-poisoned cache + client history; DeepSeek's 400 is specific to an EMPTY STRING, not an absent field. Realigned reasoning-cache (2 cases, renamed to describe omission) + tool-request-sanitization (1 case + dead import). 60/60. - GPT-5.6 Codex limits (#9432, 272000 -> 1050000 ctx / 922000 input): realigned vscode-token-routes-gpt56 (2) + vscode-token-routes (3). 43/43 together with t23-t24. - combo skip codes (#9630): t23-t24-fallback-resilience T24 now expects ALL_TARGETS_SKIPPED like the combo-routing-engine siblings. - vi.json key parity: #9336 added providers.getApiKey/getApiKeyDescription to en.json without syncing vi (the only locale with a parity gate). Translated both; providers block reordered to match en key order. 5/5. - pack-artifact-policy.test.ts: sibling of this PR's own required-paths change (bin/mcpStdioConsoleGuard.mjs). 10/10. - combo-routing-engine.test.ts: dropped the 6 comment lines added in the previous commit so the frozen test file-size stays at its baseline (the rationale lives in that commit message, not the test body). Gates: file-size, test-discovery, mutation-test-coverage, pack-policy, open-sse-typecheck, dead-code all exit 0. Refs #9737 * fix(translator): keep the reasoning_content placeholder for Xiaomi MiMo — #9610 traded one live 400 for another The xiaomi-mimo replay test (9router#1321) went red on the base after #9610 removed the NON_ANTHROPIC_THINKING_PLACEHOLDER injection globally. That test is NOT stale — it guards a documented upstream 400 ('Param Incorrect: The reasoning_content in the thinking mode must be passed back to the API'), so realigning it would have masked a reintroduced production bug. Two real bugs conflict here: - #9573: forwarding the placeholder makes the model continue its chain of thought FROM that text (echo -> empty stop) and re-poisons cache/history. - 9router#1321/#1337: omitting reasoning_content on a plain replay turn makes Xiaomi MiMo reject the request outright. #9610's evidence for omitting is provider-specific — it verified that deepseek-v4-flash accepts an ABSENT field. It does not extend to MiMo. So the omission stays for every provider #9610 covered, and the placeholder survives the cache miss only for xiaomi-mimo (new requiresReasoningContentPresence predicate next to isReasoningOnlyReplayTarget). The echo that comes back is still stripped on the way in by isInternalReasoningPlaceholder(), so #9573's cache/history poisoning stays fixed for MiMo too. Both contracts now hold simultaneously: xiaomi-mimo replay + reasoning-cache + tool-request-sanitization 61/61; placeholder-strip/responses/translator/combo regression sweep 168/168. Gates: file-size, open-sse-typecheck, dead-code, mutation-test-coverage exit 0; typecheck:core clean. A live check on the VPS (Hard Rule #18 path 2) is the only way to confirm the DeepSeek half of #9610's empirical claim; flagging it in the PR rather than widening this fix on speculation. Refs #9737 * test(translator): pin the reasoning-placeholder provider scope so neither half of the conflict can silently re-break #9610 removed the placeholder globally on the strength of ONE provider's observed behavior (deepseek-v4-flash accepting an absent reasoning_content), which re-opened the MiMo 400 (9router#1321). The previous commit scoped the placeholder to xiaomi-mimo; this pins BOTH directions in one test so the next global edit fails loudly instead of trading the bugs again: - xiaomi-mimo plain replay turn, cache miss -> reasoning_content present (narrowing the scope away from MiMo re-opens 9router#1321) - deepseek plain replay turn, cache miss -> reasoning_content absent (widening it back to DeepSeek re-opens the #9573 echo bug) Guard verified by mutation: forcing requiresReasoningContentPresence() to return true makes the DeepSeek half fail (1 pass / 1 fail), and the file was restored from the pre-probe copy before committing. Also checked kimi-coding/kimi-coding-apikey, the other strict-contract entries in REASONING_REPLAY_PROVIDERS: their originating PR (#7673) fixes capture and replay of REAL reasoning and documents no 400 on an absent field, so they stay out of the placeholder scope — evidence-scoped, not speculatively widened. Reasoning suites together: 87/87. Gates: file-size, test-discovery, mutation-test-coverage, dead-code exit 0; eslint clean. Refs #9737 --------- Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com> |
||
|
|
8da0aa5ba8 |
fix(standalone): don't await the WebDAV check before Next's listener (#9580)
Merge-train validated (tip 6ce4effef8). Vitest failures confirmed as base-red (#9679). |
||
|
|
d22839626b |
chore(db): raise sqlite cache_size/mmap_size defaults (#9467)
Merge-train validated (tip 6ce4effef8). Vitest failures confirmed as base-red (#9679). |
||
|
|
48b17ff2b7 |
fix(build): remove misleading open-sse/package.json facade and add workspace typecheck gate (#8781)
Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com> |
||
|
|
c40d4b17ee |
fix(ci): clear the NEW base-reds from the 08-06 merge batch (migration collision #2 + broken import) (#9688)
* test(base): realign six suites with contracts that #9100/#8990/#9009 deliberately changed Continuing the base-red drain — every one of these reproduces on the pure tip. - tests/snapshots/provider/translate-path.json: regenerated via UPDATE_GOLDEN=1. The diff is ADDITION-ONLY — the unorouter block from #9009; no existing provider entry changed. 3/3. - tests/unit/provider-models-route.test.ts: |
||
|
|
0e1f40ed1f |
feat(oauth): add Raycast Pro provider with local auto-import (#8895)
Validated in post-merge-train sweep (boards clean on release/v3.8.50 tip) |
||
|
|
2a94cbfe14 |
feat(executors): add isolated Claude Code bridge over Devin ACP (#8914)
Validated in post-merge-train sweep (boards clean on release/v3.8.50 tip) |
||
|
|
f2e36ad0ce |
fix(ci): clear base-reds on release/v3.8.50 (migration collision + 4 masked gates) (#9600)
Validated in local merge-train (diegosouzapw batch) |
||
|
|
2ddbbc61a6 |
[v3.8.50] feat(memory): MemoryBackend provider pattern with generic HTTP connector (#8752)
Validated in local merge-train T7 (ungrouped batch 2) |
||
|
|
e7f6b1d130 |
feat(radar): flag-gated signed free-model catalog overlay (#9515)
* feat(dashboard): add RADAR_ENABLED flag (default off) * feat(db): radar feed cache + settings with encrypted supporter key * feat(radar): signed feed sync with pinned key and version floor - feedSchema.ts: Zod v4 schema mirroring the server feed format (discriminated union on budget.kind, enum constraints, etc.) - pinnedKeys.ts: Ed25519 SPKI-DER pinned key + env override for forks - verify.ts: signature verification over exact wire bytes, never throws - sync.ts: full download/verify/validate/cache pipeline with injectable deps, feature-flag gate, opt-in gate, version floor (numeric compare), and sanitized error reasons (no stack traces) - 40 tests covering: contract hash, key handling, sig verification, schema validation, version compare, all sync paths (disabled, opt_out, invalid_signature, invalid_schema, stale, updated, error), auth header injection, and cache-untouched assertions for every failure mode * feat(radar): read-time overlay merge rules over the free catalog Pure function applyFeed() merges the cached Radar feed over the static baseline catalog at read time, honoring 4 rules: 1. Feed never overwrites a local override field. 2. enabled:false disables the entry with disabledBy:"radar" provenance. 3. User-added entry NOT in the feed survives untouched. 4. User deletion tombstone prevents feed resurrection. getRadarCatalog() accessor in index.ts: flag off / no cache / corrupt payload all fall back to baseline. Valid cache applies the overlay and returns feed metadata (version, tier, fetchedAt). TDD: 19 tests (4 rules + dedup + origin + accessor flag/cache/corrupt/ valid/bad-feed + baselineToMergedEntries converter). * feat(dashboard): radar catalog and guided setup screens - API routes: GET /api/radar/catalog, POST /api/radar/sync, POST /api/radar/settings - All gated on RADAR_ENABLED flag (404 when off) - Error responses via buildErrorBody(), never raw stack/message - Settings never echoes clear supporter key (masked omr_****<last4>) - Sync delegates to syncRadar() server-side, never proxies feed URL - Dashboard pages: - /dashboard/radar: 4 states (flag off, opt-in pending, empty, populated) - /dashboard/radar/setup?provider=X: guided setup with steps, key URL, test connection - Uses existing Card component and next-intl patterns - Sidebar: radar entry in costs group with icon - i18n: pt-BR and en keys for radarPage and radarSetupPage namespaces - Tests: - radar-api-routes.test.ts: 11 tests (flag-off 404, flag-on shape, error sanitization) - radar-page-state.test.ts: 5 tests (pure state logic) - All 90 radar tests pass (including prior 74) * docs(radar): module doc and flag-off inertia test Add docs/frameworks/RADAR.md covering the flag gate, the separate data-sync opt-in and privacy promise, the Ed25519 signature/pinned-key security model, tiers, the read-time overlay merge rules, and the self-hosting env vars — plus index entries in CLAUDE.md/AGENTS.md/docs/README.md/REPOSITORY_MAP.md. Document RADAR_FEED_URL and RADAR_FEED_PUBKEY in .env.example and docs/reference/ENVIRONMENT.md to satisfy check:env-doc-sync, which was failing on this branch since the sync.ts commit added the reads. Add tests/unit/radar-inertia.test.ts as the single canonical place asserting the "RADAR_ENABLED off => zero behavioral delta" claim end to end: the three /api/radar/* routes 404, the flag resolves to the definition default with no override, getRadarCatalog() returns exactly the baseline without touching the cache, and computeFreeModelTotals() keeps its pinned values with the Radar module imported alongside it. * fix(db): renumber radar migration to 135 after collision with 134 The base branch introduced 134_proxy_logs_egress_ip while this branch carried 134_radar_cache_settings; the migration runner rejects duplicate numeric prefixes. This migration has never been applied to a real database (the PR is unmerged), so no retroactive isSchemaAlreadyApplied guard is needed. * i18n(radar): translate radar catalog and setup strings to all locales The UI-coverage ratchet measures (present - placeholder) / total_en, so the __MISSING__ sentinels that i18n:sync-ui writes do not count as covered — only real translations restore the metric. Scoped to this PR's namespaces (radarPage, radarSetupPage, sidebar.radar*) instead of a bulk sync, which would have pulled ~978 unrelated pending keys into this diff. Placeholders and code identifiers verified preserved across all 1682 strings. * fix(radar): trust the served-tier header instead of the signed body field The signed feed body always carries tier:"live" by design (one signed artifact per version — rewriting the field server-side per request would break the exact-bytes Ed25519 signature). The server now returns the tier ACTUALLY served via the x-omniroute-feed-tier response header, so free users on a delayed community snapshot no longer see "Ao vivo (tempo real)" in the UI. sync.ts now reads and validates that header (falling back to the body's tier only when the header is absent or holds an unrecognized value) and stores the served tier in the cache; index.ts already surfaces cache.tier to the UI unchanged. * test(combo): shorten an assert message that exceeded the line limit The assertion added by #9507 was 104 chars, so prettier reformatted it into five lines on the next commit that touched the file, pushing it past its frozen size (3449) and failing check:file-size. The message is shortened (the issue reference stays in the comment directly above); the assertion itself is unchanged, and the file is back to 3448 lines and prettier-clean. * i18n(radar): use the canonical zh-TW glossary terms The machine translation produced retired renderings the glossary gate blocks: 供應商 for provider (canonical 提供者) and 文檔 for documentation (canonical 文件). Fixed across the 11 affected radar strings; tests/unit/i18n-glossary-consistency-check.test.ts is back to 17/17. * fix(radar): point the default feed URL at the domain that exists radar.omniroute.dev was a placeholder for a domain that was never registered, so an out-of-the-box sync would fail DNS resolution for every user. The live feed is served from radar.omniroute.online (the subdomain the design always specified), now behind Cloudflare TLS. Forks still override it via RADAR_FEED_URL. --------- Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com> |
||
|
|
04683029a6 |
fix(build): exec native esbuild binary directly in prepublish (dast-smoke base-red) (#9558)
* fix(build): exec native tool binaries directly in runBuildTool #8858 routed every resolved local bin through process.execPath to avoid Windows .cmd shims — but esbuild >=0.25 ships bin/esbuild as the NATIVE platform executable (ELF on Linux), so Node parsed machine code as JS and build:cli died with 'SyntaxError: Invalid or unexpected token', turning dast-smoke red for every PR. runBuildTool now sniffs the entry's magic bytes (ELF / Mach-O / PE) and execs native binaries directly; JS entries keep going through this Node binary (the .cmd-shim avoidance #8858 wanted). Validation (RED->GREEN on this box): - RED: node node_modules/esbuild/bin/esbuild --version -> SyntaxError (ELF) - GREEN: the exact failing CI step reproduced via the new logic bundles open-sse/mcp-server/server.ts successfully (4.2MB output, 1.3s). * fix(docs): add MDX frontmatter to the 20 remaining docs without it Same failure class as AGENTROUTER_WAF (#9503) and DOCKER_RELEASE_CHANNELS (this run's dast-smoke red): any doc without frontmatter breaks the fumadocs MDX loader during next build, killing build:cli/dast-smoke for every PR. Swept ALL of docs/ (i18n mirrors excluded) in one pass so this class cannot recur one file at a time. * docs(env): document OMNIROUTE_INTERNAL_SERVICE_TOKEN(+_FILE), OPENROUTER_PROVIDER_STATS_* and embedded-Redis binding vars Pre-existing env/docs contract drift from recently merged features made check:env-doc-sync red for any docs-touching PR. Values and defaults read from the defining modules (internalServiceAuth.ts, openrouterProviderStats.ts). * fix(build): resolve bundled npm-cli.js in the standard Unix layout + safe npm fallback off-Windows The opencode-plugin step hard-failed on GitHub runners because resolveBundledNpmEntry only looked next to the node binary (Windows zip layout); hostedtoolcache Node keeps npm at <prefix>/lib/node_modules/npm. Added that candidate, and when neither exists on non-Windows the step now falls back to plain 'npm' — the .cmd-shim hazard #8858 avoids is Windows-only. * test(mutation): register xai-agent-tools-passthrough.test.ts in stryker tap.testFiles The test landed on release/v3.8.50 covering open-sse/handlers/chatCore/passthroughHelpers.ts without the stryker registration, so Fast Quality Gates' drift detection reds any PR that carries it. Mechanical registration so its mutant kills count. --------- Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com> |
||
|
|
e12d2d546b |
fix(build): resolve npm-cli.js on POSIX layouts in the shim-free prepublish resolver (#9553)
* fix(build): resolve npm-cli.js on POSIX layouts in the shim-free prepublish resolver The #8858 resolver only tried <dir(node)>/node_modules/npm/bin — the Windows layout. On POSIX (GitHub hosted runners, nvm, system installs) npm lives at <prefix>/lib/node_modules/npm while node is <prefix>/bin/ node, so resolveBundledNpmEntry returned null and npm run build:cli died installing @omniroute/opencode-plugin deps on every fresh checkout ('npm-cli.js not found next to the running Node binary') — redding Fast Production Build and dast-smoke for the whole PR queue. Extract the resolver to scripts/build/resolveNpmEntry.ts with injectable seams and try, in order: npm_execpath (exported by npm run itself), the Windows beside-the-binary layout, the POSIX <prefix>/lib layout. TDD: tests/unit/build/resolve-npm-entry.test.ts — the POSIX-layout and npm_execpath cases plus a live regression guard fail against the old single-candidate logic (2/5) and pass with the fix (5/5). * docs(env): register the 7 env vars orphaned by the 08-05 merge batch The Docs Gates env/docs contract went red on the release tip: #9260 added OMNIROUTE_INTERNAL_SERVICE_TOKEN(_FILE) and #9324 added OPENROUTER_PROVIDER_STATS_ENABLED/_TTL_MS without .env.example entries, and the #9286 Redis sidecar vars (REDIS_BIND_HOST, REDIS_PORT, OMNIROUTE_REDIS_BIND_HOST) never reached ENVIRONMENT.md. Inherited base-red on every open PR. Defaults and descriptions taken from the consuming source files. --------- Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com> |
||
|
|
9751821338 |
chore(quality): add an RTL layout ratchet (#8828)
Validated in local merge-train T5 (base49+contributors+pacocartones) |
||
|
|
ad82c81c38 |
fix(build): support npm v11 allowScripts for optional native deps (#8877)
Validated in local merge-train T5 (base49+contributors+pacocartones) |
||
|
|
d2f3c1abf5 |
fix(docker): bundle LLMLingua optional dependencies (#9185)
Validated in local merge-train T4 (HouMinXi+Zartharas+Andrian+artickc) |
||
|
|
1b2a72ebc8 |
feat(docker): publish next from active release branches (#9181)
Validated in local merge-train T4 (HouMinXi+Zartharas+Andrian+artickc) |
||
|
|
8180b49ce1 |
fix(quality): 2 production bugs + 24 unit base-reds + measured gate ceilings (#9529)
* fix(quality): resolve net-new lint errors and allowlist #9343 assert rewrite Two `no-explicit-any` errors landed with #9407 and #9320 after the suppressions inventory was generated. Project policy is to fix new violations rather than freeze them, so both are typed instead: - #9407: `executor as unknown as Record<string, unknown>` - #9320: `(k: { name?: string })` Also allowlists the net-assert reduction in web-tools-translation-2820 (39->35). #9343 inverted the contract — bare JSON must no longer be promoted to tool_calls without an explicit <tool> envelope — so the tests were rewritten to assert non-promotion, which costs fewer asserts than validating a promoted object. More restrictive, not weaker. * fix(quality): raise integration ceiling to 40min and unpin codex-cli version in test The integration gate's 20min ceiling killed a healthy run: measured 22m08s hermetic on an idle 16-core box (935 tests across 112 files, strictly serial at --test-concurrency=1 because ~16 of them bind a port or share a DB). The "~3-10min" estimate in the code was stale by ~3x. 40min keeps the ceiling's real purpose — turning a genuine hang into a visible failure — without failing a long-but-healthy suite. Also fixes a base-red in chat-pipeline: |
||
|
|
103bab99d5 |
fix(cli): prefer IPv4 DNS for spawned servers (#9209)
Validated in local merge-train (devbox-vm-06-dev002) @ combined-tip (FAST gates — only pre-existing audit.test.ts flake). |
||
|
|
34251a1c37 |
chore(dev): bump better-sqlite3 and add DB query scripts for provider_connections (Anthropic/Claude debugging) (#9325)
Validated in local merge-train (devbox-vm-06-dev002) @ combined-tip (FAST gates green: static + changed tests + vitest — only pre-existing audit.test.ts flake). Evidence: /home/diegosouzapw/dev/proxys/OmniRoute/.claude/worktrees/merge-train-20260805-213228-suite.log |
||
|
|
19181567d4 |
fix(docker): move entrypoint script to /app to avoid tmpfs masking (#8999)
Validated in local merge-train (devbox-vm-06-dev002) @ combined-tip (FAST gates green: static + changed tests + vitest — only pre-existing audit.test.ts flake). Evidence: /home/diegosouzapw/dev/proxys/OmniRoute/.claude/worktrees/merge-train-20260805-213228-suite.log |
||
|
|
8b6dbe2a67 |
fix: add Termux/Android support for playwright-core and better-sqlite3 (#8922)
Validated in local merge-train (devbox-vm-06-dev002) @ combined-tip (FAST gates green: static + changed tests + vitest — only pre-existing audit.test.ts flake). Evidence: /home/diegosouzapw/dev/proxys/OmniRoute/.claude/worktrees/merge-train-20260805-213228-suite.log |
||
|
|
035512585e |
[v3.8.50] fix(build): prepublish no longer spawns .cmd shims on Windows (#8858)
Validated in local merge-train (devbox-vm-06-dev002) @ combined-tip (FAST gates green: static + changed tests + vitest — only pre-existing audit.test.ts flake). Evidence: /home/diegosouzapw/dev/proxys/OmniRoute/.claude/worktrees/merge-train-20260805-213228-suite.log |
||
|
|
1efb94b102 |
docs: centralize agent instructions in AGENTS.md (CLAUDE/GEMINI point to it) (#9508)
* docs: centralize agent instructions in AGENTS.md; CLAUDE/GEMINI point to it - AGENTS.md becomes the single source of truth: full CLAUDE.md content (main data) merged with the AGENTS.md-only sections (documentation accuracy, repository map, review focus, upstream contributions) and the GEMINI.md-only file-placement/root-hygiene and local-access rules. Adds the base-green check section (PRs must not be born red) and fixes the stale _tasks/release-flow path in Hard Rule 21. - CLAUDE.md: @AGENTS.md pointer + Claude-Code-only operational deltas (EnterWorktree, subagent stash-ban replication, superpowers path overrides, base-green/sweep-reds pointers). - GEMINI.md: pointer + Gemini-only notes; the stale 10-item hard-rule mirror is removed (source is the 22-rule list in AGENTS.md). - ci(release-green): label the not-green tracking issue with base-red. * docs: retarget docs-sync provider/MCP claims to AGENTS.md and fix test placeholder --------- Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com> |
||
|
|
51efc71af5 |
fix(docker): ship MITM _internal/ shims and selfsigned package in standalone bundle (#9451)
Closes #9451 |
||
|
|
7d5e8235da |
fix(quality): add base-relative file-size check so inherited drift does not red innocent PRs (#8522) (#9355)
Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com> |
||
|
|
6b0e11e378 |
refactor: update quality baseline and test masking allowlist
- Updated the quality baseline to set eslintWarnings value to 5000, reflecting the migration to TypeScript 7 and the new warning thresholds. - Modified the test masking allowlist to account for removed tests and sources, ensuring proper tracking of deprecated features. - Enhanced ESLint configuration to ignore additional directories containing non-source files. - Removed the .npmignore file as its contents are now managed in package.json. - Adjusted KimiWeb model configuration to correctly map K3 to the K2D5 scenario, reflecting changes in the underlying logic. - Updated artifact packing policy to prevent nested node_modules from being published, ensuring a leaner package size. - Added tests to verify the exclusion of node_modules from published artifacts and to ensure the integrity of the package.json files array. |
||
|
|
712910612b |
fix(db): bundle and verify the sql.js fallback (#9044)
Co-authored-by: nguyenha935 <208228297+nguyenha935@users.noreply.github.com> |
||
|
|
2e5854906d | docs: slim AGENTS.md (#8839) | ||
|
|
723ce0b166 | fix(adobe-firefly): sync models and media capabilities | ||
|
|
b38f3a4c02 |
feat(test:scoped): add TIA-based local test runner (#8084 D1) (#9143)
- npm run test:scoped: runs only tests impacted by your changes - npm run test:scoped:staged: for staged changes (pre-commit) - Uses select-impacted-tests.mjs with impact map when available - Falls back to heuristic (changed test files) when no map - Hub file changes suggest full suite - 7 unit tests for the selection logic Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com> |
||
|
|
0ef50886ef |
feat(g1): rewrite combo-strategy check to runtime-import approach (#9131)
G1 (v3.8.51): section (2) of check-known-symbols no longer regex-scans strategy === "..." literals from combo source. The handled set now comes from a runtime-imported dispatch registry (open-sse/services/combo/ strategyDispatch.ts) that imports the real ordering functions and enumerates which strategies they implement. This keeps the canonical-not-handled gate correct under the upcoming R0.3 registry dispatch, which removes the strategy === branches the regex relied on. - Adds HANDLED_COMBO_STRATEGIES registry (all 20 canonical strategies) + binds the real dispatch leaves (applyStrategyOrdering, resolveAutoStrategyOrder, tryFusionDispatch, tryPipelineDispatch, resolveComboTargetPipeline). - main() imports the registry instead of reading/sourcing combo files. - extractHandledStrategies + diffComboStrategies stay exported (pure, tested). - New TDD test proves the runtime enumeration covers canonical exactly. Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com> |