Claude→OpenAI translation was emitting a literal </think> into
delta.content for ordinary Chat Completions clients. Reasoning already
ships as reasoning_content, so default to suppress and keep
x-omniroute-thinking-marker: on as the #4633 opt-in.
* fix(cpa): isolate credential pool failures
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(cpa): forward transport through the chatCore key-health wrapper
The local recordKeyHealthStatus wrapper in handleChatCore only declared
(status, creds), so the transport argument added for CPA credential-pool
isolation was silently dropped at the call site (TS2554 "Expected 2
arguments, but got 3" once chatCore.ts is typechecked with tsc directly —
this file is not in tsconfig.typecheck-core.json's file list, so `npm run
typecheck:core` did not surface it). The CPA isolation guard in
keyHealth.ts never received `transport`, so it never fired.
Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
---------
Co-authored-by: Ravi Tharuma <RaviTharuma@users.noreply.github.com>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
- Created a comparison table SVG illustrating the capabilities of OmniRoute versus competitors (9router, OpenRouter, CLIProxyAPI, LiteLLM) across 13 features.
- Added a zero-config installation SVG demonstrating the ease of setting up OmniRoute with three simple steps: installation, pointing to the tool, and receiving instant replies.
- Added Sweden flag (se.svg)
- Added Slovakia flag (sk.svg)
- Added Thailand flag (th.svg)
- Added Turkey flag (tr.svg)
- Added Taiwan flag (tw.svg)
- Added Tanzania flag (tz.svg)
- Added Ukraine flag (ua.svg)
- Added United States flag (us.svg)
- Added Vietnam flag (vn.svg)
Node/undici fetch is rejected by Notion's edge with HTTP 200
temporarily-unavailable and empty assistant text (messages appear in the
thread, UI shows 502 No response from Notion AI). The same cookie and body
succeed via curl/Schannel and a browser Chrome JA3 handshake.
Route inference through tls-client-node (chrome_146), matching Claude/
Perplexity web providers. Also detect nested patch-start error objects so
operators see temporarily-unavailable instead of a misleading empty-body
502, and treat that subtype as retryable.
Verified live: notion-web/fable-5, hyperagent/fable, and
promptql/vertex-claude-fable-5 all return PONG through the packaged
backend; unit tests 83/83.
Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
* fix(bifrost): send v-prefixed transport version, not bare semver
bifrost.ts resolveSpawnArgs() set BIFROST_TRANSPORT_VERSION straight from
getInstalledVersionSync(), which reads the raw "version" field out of
node_modules/@maximhq/bifrost/package.json - always bare semver per npm
convention (e.g. "1.6.3").
@maximhq/bifrost's own bin.js validates that env var against
/^v\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/ or the literal "latest" and rejects
anything else with "Invalid transport version format", exiting immediately.
Every embedded Bifrost instance failed to start as a result.
Adds formatTransportVersion() to normalize at the call site that owns the
env var, so bifrost.ts and the upstream @maximhq/bifrost package both stay
exactly as designed - no changes needed to bifrost itself.
Strengthens the existing resolveSpawnArgs test to assert the actual v-prefix
format (it previously only checked for a non-empty string, the same gap
#6877 called out for cliproxy's pre-existing test), and adds a dedicated
regression test file covering the pure formatTransportVersion() helper plus
a real-filesystem resolveSpawnArgs() integration check.
Found and fixed while self-hosting OmniRoute and diagnosing why bifrost
kept crash-looping on startup.
* fix(bifrost): resolve install dir lazily so version read honors runtime DATA_DIR
Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
---------
Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
Co-authored-by: seanford <seanford@users.noreply.github.com>
* feat(chaos+ponytail): parallel chaos-mode dispatch + ponytail output style (rebased on v3.8.49)
- Chaos mode: new auto/chaos variant fans the prompt out to the top-N
stable models in parallel and returns a single merged SSE stream.
- Progressive streaming: each panel model's answer is enqueued as it
lands (omni-chaos-part event), instead of awaiting the whole panel.
- withTimeout now aborts the underlying request (modelAbortSignal) on
timeout so the connection is released, not leaked.
- concatSseText parses both OpenAI and Anthropic SSE wire formats.
- autoPrefix/modePacks add the chaos-mode weight pack; virtualFactory
materializes auto/chaos with fusion strategy + chaos config flag.
- Ponytail (lazy-senior-dev mode) integrated into the existing
OUTPUT_STYLE_CATALOG registry (id 'ponytail') so it rides the production
output-style injector, instead of a bespoke duplicate module. Dev-only
scripts and the duplicate ponytail/ module are removed.
- Tests: chaosEngine/chaosVirtualCombo cover panel dispatch, progressive
broadcast, timeout abort, and Anthropic parsing; autoCombo pack count
updated to 6.
Rebased onto release/v3.8.49 (no provider-registry or validation changes —
those are split out per review).
* optimize(chaos+ponytail): i18n ponytail, dedupl chaos dispatch, provider diversity
- Ponytail: add vi/ja/pt-BR/id i18n with lite/full/ultra levels
- chaosEngine: extract dispatchOnePanelModel (shared), add onResult for
progressive SSE streaming, fix withTimeout anti-pattern
- virtualFactory: deduplicate chaos panel by provider, add tuning overrides
- dispatchChaosFromCombo: accept ChaosTuning, enforce minPanel
- Add/port 8 node-runner tests for ponytail i18n + catalog integrity
- Add muse-spark-web.ts to KNOWN_MISSING_ERROR_HELPER (pre-existing)
* fix(8264): use HandleSingleModel type in chaosEngine dispatch (base-drift)
---------
Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
* chore(ci): add .mergify.yml to main — Mergify only reads config from the default branch (#7168)
* fix(ci): add the auto-enqueue pull_request_rule to the Mergify config (queue_conditions alone are eligibility-only) (#7179)
* fix(ci): migrate Mergify auto-enqueue to merge_protections_settings.auto_merge_conditions (rules-based path is EOL 2026-07-16) (#7216)
* fix(ci): drop Mergify batch settings (batching is a paid-tier feature; free plan queue is serial) (#7220)
* fix(ci): merge queue tolerates the advisory dast-smoke failure (its GH-hosted build hang dequeued every attempt) (#7225)
* fix(usage): correct token/request counting for 30D/90D/YTD/ALL ranges
Two bugs caused incorrect usage statistics for date ranges beyond the
raw data retention window:
1. Cutoff mismatch: the analytics route computed rawCutoffDate from
aggregation.rawDataRetentionDays (migration 046 seeds =7) while
cleanupUsageHistory rolls up and deletes at retention.usageHistory
(=30). The window [day-30, day-7) existed in usage_history but was
excluded from BOTH UNION legs — raw leg floored at day-7, aggregated
leg ended at day-7 — producing undercounted token sums for 30D,
90D, YTD, and ALL ranges.
Fix: use dbSettings.retention.usageHistory for the raw cutoff in
both route.ts and getRawDataCutoffDate() (aggregateHistory.ts),
matching the actual cleanup boundary.
2. Request undercount: COUNT(*) on the unified source counted each
daily_usage_summary row as 1, not total_requests. A day with 50
rolled-up requests counted as 1.
Fix: add a 'requests' column to both UNION legs (raw: 1, aggregated:
total_requests), change COUNT(*) to SUM(requests) in 6 query
functions, and change successfulRequests from
SUM(CASE WHEN success=1 THEN 1 ELSE 0 END) to
SUM(CASE WHEN success=1 THEN requests ELSE 0 END). Also set
agg leg latency_ms to NULL so AVG(latency_ms) is not skewed.
Tests: 33/33 source-level tests pass (db-usageanalytics-split.test.ts),
verifying 'requests' column presence and SUM(requests) usage in all
affected queries. DB-level integration test added to
usage-analytics.test.ts (requires node + better-sqlite3).
* fix(ci): green CI reds on #7300 — file-size ratchet, stale test fixture, shallow-checkout selfref test
- src/app/api/usage/analytics/route.ts: trim the new comment to keep the file
at the frozen file-size baseline (942 lines) after the retention.usageHistory
cutoff fix — no logic change.
- tests/unit/usage-analytics-route.test.ts: the pre-existing "does not
double-count raw and aggregated rows" test hardcoded a 30-day cutoff that
matched the OLD (buggy) aggregation.rawDataRetentionDays default. Now that
the raw/aggregated boundary correctly uses retention.usageHistory (365 days
by default, matching cleanupUsageHistory's actual rollup/delete boundary),
the fixture's synthetic "old" row was within the raw window and got
excluded from the aggregated leg. Read the real retention setting instead
of hardcoding 30 so the fixture reflects the corrected boundary. Same
assertions (still expects no double-counting, totalRequests=2,
totalTokens=185) — only the fixture dates change.
- tests/unit/check-test-masking-selfref-6634.test.ts: tolerate the shallow/
single-ref checkout used by GitHub-hosted Unit Tests runners (no local
origin/main ref) by fetching it on demand and skipping (never failing) when
unreachable offline. Matches the fix already applied on another branch
(2e42b8efc/#7174) for the same root cause, not yet on main.
Co-authored-by: diegosouzapw <diegosouza.pw@gmail.com>
* test(ci): make the #6634 selfref test checkout-independent (read the real file, no git ref)
The previous on-demand `git fetch origin main` + t.skip() fallback cleared the
shallow-checkout failure but tripped the PR Test Policy's test-masking gate
(a new .skip counts as a silenced assert — correctly so).
Drop the git dependency entirely instead: read the REAL current source of
tests/unit/check-test-masking.test.ts from disk (so the actual #6404 fixture
literals stay under test) and model the pre-#6404 state with an empty base,
which maximizes headTaut - baseTaut — the strictest input for the exclusion
this test asserts. No skip, no weakened assertion, same deepEqual guarantee.
Verified non-vacuous: neutralizing SELF_TEST_FIXTURE_RE in
scripts/check/check-test-masking.mjs makes this test fail; restoring it makes
it pass.
Co-authored-by: diegosouzapw <diegosouza.pw@gmail.com>
* test(ci): make the #6634 selfref guard hermetic — main's copy hard-fails every PR (#7341)
main's copy of this test still does git I/O inside a unit test:
const baseSrc = git(['show', 'origin/main:' + FILE]);
Runners check out a shallow single ref, so origin/main does not resolve and the
test dies with 'fatal: invalid object name origin/main'. Every PR into main
fails Unit Tests (7/8) on it — today that is #7313, #7315, #7316, #7334, #7336
and #7337, six PRs red on a defect none of them introduced. #7313 has no other
red at all.
release/v3.8.49 already carries a fix (2e42b8efc, #7174: try/catch, fetch
origin/main on demand, t.skip() when unreachable), but it only reaches main at
release time — so main stays broken for the whole cycle. Cherry-picking it would
also import a new problem: PR Test Policy classifies t.skip() as a silenced
assertion, which we watched it correctly catch on #7300 today.
This is the hermetic version instead (ported from #7327, which does the same for
the release branch): read the file straight off disk, compare against an empty
base so baseTaut/baseExtTaut are 0 — the strictest possible comparison point —
and call evaluateMasking() directly. No git ref, no fetch, no skip, nothing the
runner's checkout depth can break.
The #6634 regression stays covered: the guard's logic lives in
SELF_TEST_FIXTURE_RE (check-test-masking.mjs:337), not in the test. Proven both
ways on main before committing — neutralise SELF_TEST_FIXTURE_RE to /$^/ and
the test FAILS; restore it and it passes 2/2, with check-test-masking.mjs left
byte-identical.
Co-authored-by: growab <nekron@icloud.com>
* chore(quality): tighten main's coverage baseline to the CI's real numbers (#7347)
main's ratchet had been failing --require-tighten on every PR: 11 metrics
improved but the baseline was never tightened. Same class as the #6634
selfref guard — an infra fix that lands only on the release branch leaves
main red for the whole cycle, and every PR into main pays for it.
Values are the merged-coverage numbers from a run on main itself (a local
run measures ~68% vs CI's ~80%; the baseline's own note warns about that
gap). Only the 11 coverage values change — gitleaks and semgrepFindings
keep main's own state.
No changelog fragment: #7326 carries it on release/v3.8.49, and a second
one here would double the entry at release time.
---------
Co-authored-by: Diego Rodrigues de Sa e Souza <8016841+diegosouzapw@users.noreply.github.com>
Co-authored-by: diegosouzapw <diegosouza.pw@gmail.com>
sanitizeStreamingChunk() only stripped zero-width characters (U+200B,
U+200C, U+200D, U+FEFF) from OpenAI-format choices[].delta.content.
Anthropic-native content_block_delta events with text_delta or
thinking_delta payloads bypassed that path entirely, leaking U+200D
to clients on the Messages API streaming route.
Add a content_block_delta branch that strips zero-width characters
from delta.text and delta.thinking before returning the event,
matching the existing OpenAI path behavior from #5857.
Co-authored-by: Austin Liu <austinliu@Austins-MacBook-Air-3.local>
Background token health check sweep was probing connections with
terminal statuses (credits_exhausted / banned / expired) on every
cycle, wasting CPU and network. These connections can never self-heal
via token refresh — they need manual re-auth or credit top-up.
Add a terminal status guard in checkConnection() that mirrors the
existing isTerminalConnectionStatus() in auth.ts and
TERMINAL_CONNECTION_STATUSES in connectionRecovery.ts.
Verified by reporter: after manually disabling 11 credits_exhausted
connections, CPU dropped from ~53% to ~2.7%. This fix automates that
skip so the sweep never touches terminal connections in the first place.
Co-authored-by: Austin Liu <austinliu@Austins-MacBook-Air-3.local>
spawn('claude') without shell:true cannot resolve the .cmd shim
that npm installs on Windows, causing ENOENT and a misleading
'not found in PATH' error. Use claude.cmd + shell:true + windowsHide
on win32, matching the pattern already used in launch-codex.mjs.
Co-authored-by: Austin Liu <austinliu@Austins-MacBook-Air-3.local>
#8232 correctly targeted OAuth auto-refresh for legacy stored Gemini CLI connections, but exceeded that compatibility goal by recreating a complete routable and UI-visible provider with an Antigravity model catalog.
Preserve legacy refresh by mapping gemini-cli rows to the existing Gemini OAuth credentials. Remove the public provider registry, OAuth preset, model routing snapshot, and canonical-provider tests while keeping Gemini API and Antigravity unchanged.
#2101 still hard-stopped model-not-supported failures when upstream
wrapped them as invalid_request_error / Bad Request. Keep models in the
combo and try the next target (#8251, residual of #5249).
- export MODEL_ACCESS_DENIED_PATTERNS + broaden does-not-support shapes
- add isModelScoped400() and exempt it from the body-specific stop guard
- regression tests for wrapper forms; body-specific stop still intact
Co-authored-by: Ravi Tharuma <RaviTharuma@users.noreply.github.com>
Regenerated the [3.8.49] CHANGELOG from the full cycle range (bump 2c62333b0..tip):
added 289 previously-uncovered merged PRs as categorized bullets with per-PR author
attribution, then re-injected the 🙌 Contributors hall (83 external contributors).
Closed-PR credit audit: clean — the 3 closed-not-merged authors not in the hall
(#8178 AI Council 'opened by mistake, stays on fork', #8076 Rust fetch 'closing at my
request', dependabot bot) had no landed work, so no missing credit. Synced 41 i18n
CHANGELOG mirrors.
Sync the hand-authored readme-hero.svg / promise-pillars.svg provider count
(number + accessibility desc) to 290, matching the catalog + the README/AGENTS/CLAUDE
text updated in the prior commit.
The auto-generated catalog now resolves 290 providers (grew from the tier-1/2/3
provider additions this cycle); README/AGENTS/CLAUDE still carried 278/283. Updated
all provider-count mentions + the TOC anchor/heading to 290 so check-docs-counts-sync
exits 0. Note: readme-hero.svg / promise-pillars.svg still render the old number and
need a re-render on the site-deploy machine (image render is out of gate scope).
* feat(settings): configurable model catalog cache TTL
Add modelCatalogCacheTtlMs to DatabaseSettings with default 1500ms.
Extend cache-config API route to accept the new field.
Replace hardcoded catalog cache TTL with dynamic settings value.
Add 'Cache' settings tab at /dashboard/settings/cache with sidebar entry,
i18n keys, header description, and legacy route redirect.
* feat(combo): add model connection filter toggle to ModelSelectModal
Adds a 'Show configured only' checkbox below the search bar in
ModelSelectModal that filters each provider group's models through
hasEligibleConnectionForModel. Toggle state persists in localStorage.
- Import hasEligibleConnectionForModel from domain/connectionModelRules
- showConfiguredOnly state + localStorage persistence
- connectionFilteredGroups memo layered on filteredGroups
- Renders both provider section and empty state from connectionFilteredGroups
* test(combo): add connection filter toggle tests for ModelSelectModal
Three test cases: (1) hide excluded models when toggle on,
(2) show empty state when all models excluded,
(3) drop provider group when all its models excluded.
All 3 tests pass.
* fix(settings): correct cache-config route import + add route/tab coverage
The cache-config route imported get/update helpers from a nonexistent
module (@/lib/localDb/databaseSettings) and called an undefined
updateSettings() in PUT, crashing every request. Import the real
databaseSettings module (matching the sibling database/route.ts
convention) and call updateDatabaseSettings(); idempotencyWindowMs is
routed through the flat @/lib/db/settings module instead, since that is
where it is actually read at runtime (idempotencyLayer.ts,
runtimeSettings.ts) — it was never part of the databaseSettings "cache"
section type.
Also fixes a dashboard-typecheck regression in ModelSelectModal.tsx: the
new connection-filter toggle called hasEligibleConnectionForModel() with
activeProviders entries typed too narrowly to include
providerSpecificData, which real connection objects carry at runtime.
Adds:
- tests/unit/cache-config-route-8219.test.ts: GET/PUT resolve without
crashing, modelCatalogCacheTtlMs and idempotencyWindowMs round-trip.
- tests/unit/ui/cache-settings-tab-bounds-8219.test.tsx: CacheSettingsTab
min/max TTL bounds (100ms/60000ms) gate the Save button and surface a
validation message; in-bounds values PUT correctly.
Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
* chore(quality): rebaseline sections.ts for #8219 own-growth
---------
Co-authored-by: oyi77 <oyi77@users.noreply.github.com>
Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
* docs(i18n): full Russian README rewrite for native readers
Rewrite docs/i18n/ru/README.md from an outdated English dump into a proper Russian manual aligned with the modern product README (v3.8.x structure, free-tier budget, combos, compression, CLI/MCP). Fix relative screenshot/doc links for the i18n path.
* fix(8217): changelog fragment bullet prefix
---------
Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
* feat(providers): add Typhoon and Inception Mercury API-key providers
Two OpenAI-compatible API-key providers, each verified against a live
endpoint smoke test with a negative control before registration: an
unknown route answers 404 while /v1/chat/completions answers 401, which
rules out gateways that reply identically to every path.
- typhoon (SCB 10X, Thailand): first Thai-first provider in the catalog.
/v1/models answers 200 unauthenticated and serves exactly one chat
model, typhoon-v2.5-30b-a3b-instruct (128K ctx). The docs also list
typhoon-v2.1-12b-instruct, but the live endpoint no longer serves it,
so it is deliberately not registered. The typhoon-ocr* and typhoon-asr*
entries are OCR and speech models, not chat, and are omitted.
- inception (Inception Labs): first diffusion LLM (dLLM) in the catalog.
mercury-2 has a 128K context, 50K max output, and supports tools,
json_mode and structured outputs. The mercury-coder models advertised
on the vendor blog are no longer served by the live endpoint and are
therefore not registered.
Both expose a working /v1/models catalog, so they are added to
NAMED_OPENAI_STYLE_PROVIDERS for discovery and key validation.
Free-tier metadata is claimed only where it is documented and durable:
Typhoon issues a free API key rate-limited to 5 req/s and 200 req/m, and
Inception grants 10M tokens on signup with no card, so both are
registered with hasFree: true.
Provider count moves from 280 to 282; README/AGENTS/CLAUDE counters were
stale at 278 and are resynced against docs/reference/PROVIDER_REFERENCE.md.
* fix(8170): union frontier-labs Inception+Writer, regen ref+golden
* fix(8170): close inception object + regen ref/golden
---------
Co-authored-by: Álvaro Ángel Molina <alvaretto@users.noreply.github.com>
Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
* feat(providers): add Sarvam AI, Writer Palmyra and PLaMo API-key providers
Three OpenAI-compatible API-key providers, each verified against a live
endpoint smoke test before registration:
- sarvam (India): /v1/models answers 200 unauthenticated and lists
sarvam-105b (128K ctx) and sarvam-30b (64K ctx). The older sarvam-m is
discontinued upstream and is deliberately not registered.
- writer (Palmyra): api.writer.com exposes the OpenAI alias
/v1/chat/completions alongside its native /v1/chat — confirmed with a
negative control, since an unknown route answers 404 'endpoint not
available via API gateway' while /v1/chat/completions answers 401.
Registers palmyra-x5 (1M ctx) and palmyra-x4 (128K ctx); the
medical/financial/creative/vision variants are deprecated upstream and
are omitted.
- plamo (Preferred Networks, Japan): only plamo-3.0-prime (262K ctx) is
registered. plamo-3.0-prime-beta is discontinued on 2026-07-31 and
plamo-2.2-prime on 2026-09-30, so neither is worth wiring up.
Free-tier metadata is claimed only where it is documented and durable:
Sarvam ships a permanent signup credit, while PLaMo's 10M-token grant is
a campaign that expires on 2026-07-31 and Writer documents no free tier,
so both are registered with hasFree: false.
* regen golden+ref
---------
Co-authored-by: Álvaro Ángel Molina <alvaretto@users.noreply.github.com>
Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
* feat(providers): add CLOVA Studio, InternLM and Ant Ling API-key providers
Adds three OpenAI-compatible frontier-lab providers, closing regional gaps
in the catalog (Korea had none; the Shanghai AI Lab and Ant Group families
were both missing).
- clova-studio: Naver HyperCLOVA X (HCX-007 reasoning, HCX-005 multimodal)
on the current clovastudio.stream.ntruss.com host. The legacy
clovastudio.apigw.ntruss.com endpoint is being deprecated and is not used.
- internlm: Shanghai AI Lab Intern-S1 family (intern-s1-pro is a 1T MoE).
Ships a free monthly quota, so it is flagged hasFree.
- ant-ling: Ant Group / inclusionAI Ling-2.6-1T and Ring-2.6-1T.
All three endpoints were smoke-tested: each returns HTTP 401 on <baseUrl>/models
(endpoint live, awaiting auth) and resolves against public DNS. All three are
registered for live model discovery, so their catalogs refresh from upstream.
Known limitation: the ant-ling model ids are best-effort from public docs and
are NOT verified against a live /v1/models response, which requires an API key.
This is recorded in the registry comment and in the provider authHint so it is
visible to operators rather than silently assumed. Its baseUrl is likewise not
published in the public docs and was found by smoke test.
Two AI SUTRA was evaluated for this batch and deliberately excluded: its
documented endpoint api.two.ai does not resolve in public DNS (ENOTFOUND
against 1.1.1.1 and 8.8.8.8, with www.two.ai resolving as control).
The translate-path golden snapshot is regenerated; the change is additive only
(209 -> 212 keys, exactly the three new providers, none removed or altered).
* feat(providers): verify ant-ling against official docs, add Ling-2.6-flash and free tier
The ant-ling entry was added with model ids marked best-effort because they
could not be checked without an API key. Ant Ling's own documentation turns
out to publish enough to verify them, so the uncertainty is now resolved:
- The quickstart sample uses base_url "https://api.ant-ling.com/v1" with
model "Ling-2.6-1T", confirming both the endpoint and the exact casing.
- The pricing page bills exactly three models over the API, so Ling-2.6-flash
was missing from the catalog and is added.
- Each account gets 500,000 free tokens per day (resets 02:00 UTC+8, no
rollover), so the provider is flagged hasFree with a freeNote.
The Ming family (Ming-Flash-Omni, Ming-Light) is deliberately left out: it is
documented as open-source / Ling Studio only and does not appear on the
pricing page, so it is not served over this chat-completions API. That
reasoning is recorded in the registry so it is not re-litigated later.
The authHint no longer claims the ids are unverified, and now points at the
API console (https://chat.ant-ling.com/open) where keys are actually created.
Same correction applied to the en, pt-BR and vi message catalogs.
* docs: sync provider counts to 283 and regenerate the provider reference
---------
Co-authored-by: Álvaro Ángel Molina <alvaretto@users.noreply.github.com>
Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
* fix(ci): resolve upstream-inherited check failures
* fix(docs): align INPUT_SANITIZER_ENABLED default to true across all docs
Code defaults INPUT_SANITIZER_ENABLED to enabled (any value that is
not exactly 'false'). Updated .env.example and 41 i18n translations
of ENVIRONMENT.md to match this default instead of showing false.
Fixes#8093
---------
Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
* fix(ci): resolve upstream-inherited check failures
* fix(streamHandler): log trackPendingRequest decrement failures instead of swallowing
The clearPendingRequest function had an empty catch block around the
trackPendingRequest decrement call. If it threw, the pending request
counter stayed incremented — causing drift, false-positive rate limiting,
and masked overload conditions.
Now logs the error with context for observability.
Fixes#8141
---------
Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
* fix(ci): resolve upstream-inherited check failures
* fix(compression): make memo key model-independent for non-vision engines (#8137)
The compression result memo included `model` and `supportsVision` in the
cache key for ALL deterministic modes. This was correct for the `lite` engine
(which strips data:image URLs based on vision support) but unnecessary for
model-independent engines like `rtk`, `caveman`, and stacked pipelines
without a `lite` step.
In the combo retry loop, the body and config are identical across targets —
only the model changes each attempt. Including model in the key forced a fresh
cache miss on every retry, re-running the full compression pipeline 5-8x per
request instead of serving the cached result.
Fix: `makeMemoKey` now only includes model + supportsVision when the
compression pipeline actually uses a vision-dependent engine (lite, standard,
or stacked containing lite). All other deterministic engines use a
model-independent key.
- Add `usesVisionDependentEngine()` helper to classify modes
- `makeMemoKey` conditionally includes model/vision fields
- 5 new tests covering rtk, caveman, stacked-with-lite, stacked-without-lite
Closes#8137
---------
Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
* fix(ci): resolve upstream-inherited check failures
* fix(combo): skip remaining same-provider targets on 401/403 auth failure (#8133)
When a provider returns 401/403 (auth failure), every remaining model behind
the same provider will fail identically. Previously the combo engine continued
trying sibling models on the dead connection, wasting attempts.
Now auth-level failures (401, 403) are classified as provider-level exhaustion,
marking exhaustedProviders so subsequent same-provider targets are skipped via
the existing exhaustion-skip mechanism.
Tests: 4 new cases in combo-target-exhaustion.test.ts covering 401, 403,
unknown-provider guard, and per-model-quota provider (auth is provider-wide).
* fix(combo): connection-level exhaustion on 401/403, not whole-provider (#8137)
Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
---------
Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
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.
Use getEmbeddingDimension() in resolveEmbeddingSource so sqlite-vec can
create vec_memories before the first upsert, and abort reindex batches
when ensureReady returns ready=false instead of wasting embed credits.