Commit Graph

2566 Commits

Author SHA1 Message Date
Diego Rodrigues de Sa e Souza
92a083ab8c fix(resilience): honor dashboard quota snapshots in opencode-go preflight (#11234) (#11267)
The opencode-go quota preflight ignored the dashboard quota snapshots, so
priority combos kept selecting connections whose weekly window was already
drained. Two gaps, two fixes:

A) fetchOpencodeQuota only consulted the live upstream endpoint, which has
   no public quota API (404 — the module JSDoc already admits this). Every
   preflight therefore evaluated null and proceeded (fail-open) even with a
   connection at 0% weekly remaining in plain sight on the dashboard. The
   fetcher now synthesizes its triple-window QuotaInfo from the cached
   dashboard snapshots when the live endpoint yields nothing, mapping
   session→window_5h, weekly→window_weekly, mcp_monthly→window_monthly and
   mirroring getQuotaWindowStatus semantics (expired resetAt = window rolled
   over = must not count as exhausted; fractionReported=false = unknown,
   never exhaustion). Read-only via src/domain/quotaCache.ts accessors —
   never SQL, never a re-scrape on the hot path — and gated on the
   connection actually having dashboard scrape config, so unconfigured
   connections never touch the snapshot store. Fail-open is preserved:
   no snapshots → null, exactly as before. The quotaCache import is dynamic
   because a static edge would close an initialization cycle
   (fetcher → quotaCache → usage.ts → usage/opencode.ts → fetcher).

B) The sibling-selection latency gate in getProviderCredentialsWithQuotaPreflight
   never consulted resilience.quotaPreflight.enabled
   (QUOTA_PREFLIGHT_CUTOFF_ENABLED) — that flag only armed the auto-strategy
   candidate builder and the per-target cutoff for pinned connections, so a
   priority combo over sibling opencode-go connections (connectionId null at
   combo level) skipped preflight entirely. The flag now arms the gate as
   well; the default (flag off) is unchanged.

TDD (Hard Rule #18), tests/unit/quota-exhaustion-cutoff-opencode.test.ts:
- fetcher 404 + seeded snapshots weekly=0%/session=80% → cutoff blocks
  (RED before, GREEN after); also asserts the bridge is read-only (single
  upstream fetch, no re-scrape).
- weekly 0% with next_reset_at in the past → not blocked (window dropped).
- per-window threshold override resolves against the mapped window_weekly
  key (50% override blocks at 40% remaining; factory 2% does not).
- fail-open guard: configured dashboard with no snapshots still returns null.
- selector level: flag on, two opencode-go sisters, priority-1 exhausted →
  selection skips to the healthy one (RED before, GREEN after).

Sibling suites green: opencode-quota-fetcher (18), quota-preflight,
combo-priority-quota-exhaustion-cutoff-5923, issue-6686, 8431, throttle-6911,
sse-auth*, quota fetchers, combo strategies, snapshot/hydration tests
(~500 tests). eslint (with suppressions) and typecheck:core clean.

Closes #11234

Co-authored-by: Xiangzhe <bakryun0718@proton.me>
2026-08-23 14:28:19 -03:00
Diego Rodrigues de Sa e Souza
5cf16028fe fix(cli): real OpenRouter key validation + auth export argument wiring (#11226) (#11264)
Two defects exposed by #11226 (the 401 "User not found." itself is upstream
OpenRouter's response to a bad key — not an OmniRoute bug):

1. OpenRouter key validation was vacuous. Both the dashboard Check (via
   validateProviderApiKey -> validateOpenAILikeProvider) and 'omniroute
   providers test' (bin/cli/provider-test.mjs) probed /api/v1/models, which is
   PUBLIC and answers 200 to any key — so invalid keys were saved/marked valid
   and only failed on real chat traffic. OpenRouter's authenticated key-info
   endpoint (GET /api/v1/auth/key, 200 = valid / 401 = invalid) is now the
   probe: registered as testKeyModelsUrl on the openrouter registry entry
   (same mechanism as perplexity) and as keyCheckPath in the CLI test configs.
   No other provider's probe changes; error results keep using canned strings,
   never the raw upstream body (Hard Rule #12).

2. 'omniroute auth export' crashed with "cmd.optsWithGlobals is not a
   function". .command("auth export") does not register a two-word command:
   commander parses the bare word 'export' as a required positional argument,
   so the action received (exportArgValue, options, command) while expecting
   (options, command). Registered 'export' as a proper nested subcommand of
   'auth' — the documented CLI surface 'omniroute auth export [--force]
   [--id] [--format] [--out]' is unchanged, and unknown positionals
   (e.g. 'omniroute auth bogus') are now rejected instead of silently running
   the export.

TDD: tests/unit/openrouter-key-validation-auth-endpoint.test.ts (stub mimics
the real OpenRouter: /models public-200, /auth/key 401 'User not found.') and
tests/unit/cli-auth-export-wiring.test.ts (real commander wiring via
createProgram) were RED before the fix and are GREEN after.

Co-authored-by: Xiangzhe <bakryun0718@proton.me>
2026-08-23 14:26:08 -03:00
Paco Cartones
a55ee5dc05 feat(combo): make the global attempt budget operator-configurable (#11134) (#11239)
Validated on the combined 12-PR batch board: combo-max-global-attempts-config 4/4 plus the neighboring combo suites green, typecheck:core clean, gates within baseline. clampGlobalAttempts mirrors clampComboDepth with a 200 hard cap, so a bad config can never disable the budget. Closes the configurability item from #11134. Thank you @pacocartones!
2026-08-23 14:24:45 -03:00
Diego Rodrigues de Sa e Souza
158c6ec233 fix(embeddings): honor configured LM Studio connection URL via lm-studio alias (#11233) (#11260)
The dashboard stores LM Studio connections under the hyphenated provider id
"lm-studio", but the embedding registry keys the provider as "lmstudio"
with no alias. As a result, "lm-studio/<model>" embedding requests failed
with a 400 unknown-provider error, and "lmstudio/<model>" requests always
hit the hardcoded http://localhost:1234/v1/embeddings endpoint, ignoring the
baseUrl of the configured connection.

Mirror the ollama-local pattern from #2824/#9225:

- embeddingRegistry: add "lm-studio" -> "lmstudio" to
  EMBEDDING_PROVIDER_ALIASES (registry key unchanged so existing
  "lmstudio/<model>" clients keep working).
- embeddings service: extend the optional keyless-connection hydration to
  lmstudio; getProviderCredentials("lmstudio") already resolves the
  "lm-studio" connection via the provider search pool/alias, and a
  selection/rate-limit failure still proceeds without credentials.
- embeddings handler: apply the same baseUrl override + normalization
  (strip trailing slashes and /v1, /v1/chat/completions, /v1/embeddings
  suffixes, then rebuild <host>/v1/embeddings) to lmstudio, keeping the
  static localhost fallback when no connection or empty baseUrl.

TDD: tests/unit/lmstudio-connection-baseurl-11233.test.ts failed on the
alias, override and service-hydration asserts before the fix and passes
after; ollama-local (#2824) and lmstudio registry (#7601) sibling tests
remain green.

Co-authored-by: Xiangzhe <bakryun0718@proton.me>
2026-08-23 14:23:52 -03:00
Dizzle
a054ac408f feat(providers): allow per-connection maxWaitMs rate-limit override (#11251)
Validated on the combined 12-PR batch board: focused node:test suites green (incl. provider-rate-limit-overrides-schema + ratelimit-admission-control-6593 isolated 11/11 + the new EditConnectionModal vitest 3/3), typecheck:core clean, all static gates within baseline. Pushed one follow-up commit to your branch with the real Vietnamese translations for the two new keys (repo convention: vi never ships __MISSING__ placeholders). Per-connection maxWaitMs override lands, folding the zai-web exception into the general mechanism. Thank you @maxmad64bis!
2026-08-23 14:21:55 -03:00
Dizzle
7fdd2e0f2a fix(sse): learn accepted reasoning_effort sets and clamp downgrade-only (#11232)
Validated on the combined 12-PR batch board (worktree off origin/release/v3.8.50 @ 8f390eff): focused node:test suites 183/184 (the single red was a load-induced pollUntil flake — 11/11 when re-run isolated, this file included), typecheck:core clean, file-size/changelog/complexity/cognitive gates all within baseline, mutation-coverage gate no-drift. Learned effort sets now cost at most one 400 per provider+model. Thank you @maxmad64bis!
2026-08-23 14:21:27 -03:00
Armin Anton” ∴
8f390efffd feat(codex): self-contained codex app-server transport (executor + provider + sign-in) (#11205)
Merged after conflict resolution: the 5 conflicting test files were the base-red drains that #11201 already landed on the tip — kept the tip versions; the feature content is untouched. Validated on the combined batch board + this branch: codex-app-server + codex-gpt56-catalog 25/25, typecheck:core clean, docs-counts green (351 providers), provider-consistency 268/351/0. The opt-in codex-app-server transport (JSON-RPC-over-WS, turn/completed-awaited close, Responses SSE bridge) leaves the default codex path untouched. Thank you @arminanton — a 3.4k-line transport with the docs wave and tests to match!
2026-08-23 10:20:06 -03:00
adevwithpurpose
90ba281e7f fix(sse): default single-target incompatible reasoning to drop for agentic replay (#10959) (#11178)
Merged after conflict resolution onto the post-#10961 tip (verified no clobber of today's plaintext-wins work — the resolver functions were appended and the chatCore call-site swapped; a first --theirs attempt was caught reverting #10961 and redone hunk-by-hunk). resolveIncompatibleReasoningAction now defaults single-target incompatible reasoning to drop while combos keep their explicit strategy, with the x-omniroute-reasoning-fallback header override. 21/21 reasoning suites green, typecheck clean. Fixes #10959. Thank you @adevwithpurpose!
2026-08-23 10:00:17 -03:00
小妍儿 ✨
84bd382d94 fix(kie): map the Nano Banana 2 Market id to its KIE upstream id (#11225) (#11231)
Validated on the combined batch board: gates clean, typecheck clean, focused tests green.

Exactly one Market id rewritten at the createTask seam (google-imagen/nano-banana-2 → nano-banana-2); every other namespaced id forwards byte-identical — the contract is stated and tested precisely. Fixes #11225. Thank you @xiaoyaner0201!
2026-08-23 09:48:48 -03:00
Harvey Doan
3d8448b45e fix(sse): floor muse-spark output budget to prevent empty-content 502s (#11214)
Validated on the combined batch board over tip 0b41259f: static gates clean (changelog, file-size 160 frozen, complexity 2628<=2774, cognitive 1187<=1223, dead-code 408<=416, docs-counts green at 351 providers, provider-consistency 268/351/0), typecheck:core clean, 430+ focused tests green across 5 groups.

muse-spark's all-reasoning empty-answer payloads (41 failures in 2h captured live) now floor the output budget so the model can actually emit content — no more empty-content 502 churn. Thank you @linhdmn!
2026-08-23 09:47:10 -03:00
Harvey Doan
e66181b182 fix(sse): append synthetic user turn for GLM-family upstreams (400 [1214]) (#11209)
Validated on the combined batch board over tip 0b41259f: static gates clean (changelog, file-size 160 frozen, complexity 2628<=2774, cognitive 1187<=1223, dead-code 408<=416, docs-counts green at 351 providers, provider-consistency 268/351/0), typecheck:core clean, 430+ focused tests green across 5 groups.

GLM-family upstreams reject message arrays with no user turn (400 [1214], verified live 2026-08-23); the synthetic user turn keeps Claude Code sessions on opencode-go alive. Thank you @linhdmn!
2026-08-23 09:47:07 -03:00
Jonathan Bailey
7af14d2696 fix(codex): prefer max_context_window over context_window as the usable input limit (#11179)
Validated on the combined batch board over tip 0b41259f: static gates clean (changelog, file-size 160 frozen, complexity 2628<=2774, cognitive 1187<=1223, dead-code 408<=416, docs-counts green at 351 providers, provider-consistency 268/351/0), typecheck:core clean, 430+ focused tests green across 5 groups.

max_context_window now wins over the pricing-tier context_window in Codex catalog parsing — context-aware fallback stops demoting codex behind smaller targets. Live evidence (390K served past 272K) plus the live-shape regression test. Thank you @excessivechaos!
2026-08-23 09:47:03 -03:00
Webman
98289a8c99 fix(sse): stop keyless pollinations 401s from poisoning the noauth pool (#9827) (#11194)
Validated on the combined batch board over tip 8a42aeeb: static gates clean (changelog, file-size 159 frozen, complexity 2621<=2774, cognitive 1181<=1223, dead-code 408<=416), typecheck:core clean, 107 focused tests green.

Keyless pollinations 401s no longer poison the noauth pool — key health classification treats the now-required-key provider correctly after #11117. chatcore-key-health + executor-pollinations green. Fixes #9827. Thank you @jonlwheat2-gif!
2026-08-23 07:01:04 -03:00
Bob.Hou
1f6e781c4f feat(search): add context7 as a library-docs search and fetch provider (#11140)
Validated on the combined batch board + this branch: context7-provider 33/33 + search-registry 45/45 (propagated to 17 providers), docs-counts green (350 everywhere: PROVIDER_REFERENCE regenerated, SVGs, README, AGENTS.md, package.json, llm.txt + 42 mirrors synced), provider-consistency OK. Hardening reviewed: canonical isValidContext7LibraryId shared by normalizer+executor, byte-capped error bodies, validated baseUrl with public fallback, anonymous-tier quota sentinel, excluded from auto-select walks. Thank you @HouMinXi — 15 forge-review cycles show!
2026-08-23 02:24:01 -03:00
Paco Cartones
a966c7520b fix(routing): keep keyless custom-compatible connections in the auto/* pool (#11198)
Validated on the combined batch board over tip c92bd40b: static gates clean (changelog, file-size 158 frozen, complexity 2626<=2774, cognitive 1183<=1223, dead-code 409<=416), typecheck:core clean, 70 focused tests green (PR suites 49/49 + auth/combo neighbors 21/21).

Keyless custom-compatible connections stay in auto/* pools — the credential filter now recognizes a registry-free keyless endpoint instead of dropping the connection before pool construction. Fixes #11180. Thank you @pacocartones!
2026-08-23 01:24:25 -03:00
Paco Cartones
8c7338651c fix(routing): forward lkgpEnabled into RoutingContext so the LKGP toggle works (#11193)
Validated on the combined batch board over tip c92bd40b: static gates clean (changelog, file-size 158 frozen, complexity 2626<=2774, cognitive 1183<=1223, dead-code 409<=416), typecheck:core clean, 70 focused tests green (PR suites 49/49 + auth/combo neighbors 21/21).

lkgpEnabled finally reaches the RoutingContext literal — the Settings→Routing LKGP toggle was persisted but unreachable (context.lkgpEnabled always undefined). Scope discipline noted and appreciated: the applyStrategyOrdering dependency change stays out. Fixes #11181. Thank you @pacocartones!
2026-08-23 01:24:22 -03:00
Paco Cartones
376b49d8a5 fix(ratelimit): keep operator minTime floor when relaxing on headroom (#9763) (#11086)
Validated on the combined batch board over tip c92bd40b: static gates clean (changelog, file-size 158 frozen, complexity 2626<=2774, cognitive 1183<=1223, dead-code 409<=416), typecheck:core clean, 70 focused tests green (PR suites 49/49 + auth/combo neighbors 21/21).

Operator-configured positive minTime floor now survives the plenty-of-headroom relaxation (resolveMinTime instead of a hard 0). Fixes #9763. Thank you @pacocartones!
2026-08-23 01:24:16 -03:00
Rouzbeh†
c92bd40b88 perf(proxy): implement non-blocking async proxy log batching and performance optimizations (A, B, C, D) (#11182)
Validated on the combined batch board + this branch: perf-a-b-c-d + account-fallback-service 93/93, gates + typecheck clean. Owner approved the full bundle including item A (async proxy-log batching, 1s/100-item flush with an unref'd timer — reviewed the implementation: flush helper exists for shutdown wiring, buffered logs are the accepted tradeoff). B (lazy modals), C (O(1) alias maps), D (pre-compiled regex — this is also the entire content of #11187, being closed as subsumed) ride along. Conflict with the tip was only stale provider-count docs. Thank you @rqzbeh!
2026-08-23 01:07:32 -03:00
Rouzbeh†
8fa3e314c8 fix(sse): unpin static Antigravity sessionId and add DNS retry classification (#10443) (#11177)
Validated on the combined batch board + this branch: antigravity-dynamic-session-id + proxy-fetch-dns-retry green; file-size gate green with the proxyFetch 1244 frozen entry (dated annotation for the +5 retry-classification lines, owner-authorized). Static per-account sessionId unpinning ends the concurrent-turn 429s and EmptyStreamError drops on the Hermes→Antigravity path; EAI_AGAIN/ENOTFOUND/ETIMEDOUT now classified retryable. Conflict with the tip was only stale provider-count docs. Resolves the remaining #10443 root causes. Thank you @rqzbeh!
2026-08-23 01:05:08 -03:00
backryun
79c5bdf681 fix(release): repair v3.8.50 base-red tail after latest root lift (#10964)
Merged after conflict triage: the six base-red repair files (vi.json, opencode.ts JSDoc, context-manager test, the three webhook dispatcher tests, the uncloseai orphan-test rename) were already drained on the tip by today's #11130/#11157/#11160/#11113 — those hunks resolved to the tip shape. What lands is the production-fix set: GLM transport-aware Anthropic headers, Claude Code-compatible model-listing rejection, combo live-test single-probe, zero-cost Auto-Combo interval normalization, recovery-clearing union handling, LLMLingua real-path compare, macOS netstat PID discovery, AI Horde R2 strict public-host validation. Sweep of every touched test file: 243/243 green; typecheck + file-size clean. (guide-settings-route's 4 reds reproduce on the pure tip — pre-existing drift from #11079, not from here.) Thank you @backryun!
2026-08-22 23:09:16 -03:00
Webman
2dd20331a7 feat(providers): add Logfare as a free OpenAI-compatible provider (#10644) (#10987)
Merged after count reconciliation: the branch's regenerated docs claimed 57 free forever / 157 migrations from its older base; gate-verified values on the current tip are 56 free forever (Logfare carries a Free badge via gateways.ts freeNote but has no freeModelCatalog per-model entries, so the live-code counter stays at 56) and 159 migrations — the README/SVGs now match the check:docs-counts output exactly. provider-consistency OK at 267 registry / 349 canonical. logfare-registry 4/4, icon + KNOWN_PNGS + discovery-set membership all verified present. Closes #10644. Thank you @jonlwheat2-gif!
2026-08-22 23:01:04 -03:00
Ke Jin
9689dcef9f fix(reasoning): preserve mixed plaintext and drop incompatible state (#10949, #10959) (#10961)
Validated on the combined batch board + this branch: 231/231 across chatcore-translation-paths, reasoning-cache, strip-reasoning-blobs, and both Responses translator suites. Pre-merge: propagated the #11110/#11129 summary:[] defaults into five assertions here (each commented with its PR) — without it this branch red against the tip, and as a bonus the merge drains the 4 reasoning reds that were live on the tip from those merges. Plaintext now wins over a coexisting opaque companion; opaque-only drops cleanly for plaintext targets; combos keep explicit Skip. Fixes #10949 and #10959. Thank you @jackjinke!
2026-08-22 22:58:58 -03:00
Xiangzhe
c018bb41a7 fix(catalog): declare GLM reasoning effort tiers (#10963)
Merged after conflict resolution in modelMetadataRegistry.ts: the tip's effortTiers chain (declared efforts → declared tiers → undefined-if-thinking-declared → codex extension) now carries this PR's GLM guard as the final-fallback override — GLM-family models without a provider-declared contract get the authoritative empty tier list instead of generic OpenAI tiers. GLM/ZCode suites 40/40 on the resolved branch. Closes #10962. Thank you @xz-dev!
2026-08-22 22:54:49 -03:00
Bob.Hou
e52d2db449 fix(compression): CCR must not strand prompts for callers without the retrieve tool (#11084)
Validated on the combined batch board + this branch: ccr-non-mcp-full-prompt-loss + ccr-retrieval-ramp 20/20, file-size gate green with the ccr/index listing (1024, dated annotation — owner-authorized). The callerSupportsCcrRetrieve gate now skips the whole engine for callers whose tools[] cannot reach omniroute_ccr_retrieve — no more 15KB prompt arriving upstream as 112 tokens. Production-measured root cause, textbook TDD. Thank you @HouMinXi!
2026-08-22 22:53:26 -03:00
Ke Jin
e73ab0040c fix(codex): make remote compaction V2 complete reliably (#11041)
Compaction-V2 output now counts as real model output (no synthetic response.failed after response.completed), the Codex SSE filter handles CRLF framing, and terminal detection runs before scan-state bounding. 88/88 stream/readiness suites on the board. Thank you @jackjinke!
2026-08-22 22:49:11 -03:00
amrx
d888f1a08b fix(combo): accept SSE comment lines (e.g. OpenRouter keep-alives) in response quality validation (#11036)
SSE comment lines (OpenRouter keep-alives) and leading whitespace no longer fail the combo quality gate's JSON fallback. First contribution — clean minimal fix with test. Thank you @asorourx, welcome aboard!
2026-08-22 22:49:08 -03:00
Dizzle
62ab93d789 fix(sse): reject a low-overlap stream-recovery continuation instead of concatenating it raw (#11152)
Merged after sibling #11151 landed: streamRecovery.ts auto-merged byte-identical to the validated combined board; the test-file conflict (both PRs added suites at the same anchor) resolved keeping all 11 tests — #11151's four clean-stop cases plus this PR's three threshold cases, with the PR's updated partial-tail fixture for the pre-existing overlap test. Full chain green: 32/32 (wiring + continuation + toolcall regression). The documented 8-char overlap threshold ends the silent mid-word gluing. Thank you @maxmad64bis!
2026-08-22 21:56:26 -03:00
Dizzle
80b8d2a8a2 fix(sse): resume stream recovery after a clean stop with reasoning-only output (#11151)
Merged after conflict resolution against the tip's #11109 (per-call tool_call tracking): scanOpenAiSseText keeps the per-call finish_reason special-case AND gains reasoningText + literal finishReason; canContinue uses the in-flight predicate with the new reasoning-only-clean-stop escape. One integration fix on the branch: the PR's hallucinatedEmptyStop referenced emittedToolCall, which #11109 had renamed — the branch now tracks emittedSawToolCall at the emitted level (any tool_call delta, complete or not), preserving the PR's don't-recover-after-tool-calls intent. Chain suites green: stream-continuation-wiring + stream-continuation + stream-recovery-toolcall 29/29. Thank you @maxmad64bis!
2026-08-22 21:54:48 -03:00
ggdayup
60f25eff98 fix(sse): merge purify_history compression notice into the leading system message (#11113)
Validated on the combined batch board: purify-system-first suite 4/4, typecheck clean. Pre-merge: file-size baseline gained a frozen entry for contextManager.ts at 1001 (+1, this PR's merge-into-leading-system branch) with a dated annotation — the gate caps unlisted files at 1000. Producer side of the live-confirmed TokenRouter 400 class: no internal path emits a mid-array system message anymore. Thank you @ggdayup — the call-log evidence made this airtight!
2026-08-22 21:53:08 -03:00
Dizzle
1058426120 fix(executors): rotate on upstream 400 empty-body rejections (opencode) (#11158)
Validated on the combined batch board over tip 92ef3c71: static gates clean (changelog, file-size, complexity 2624<=2774, cognitive 1182<=1223, dead-code 411<=416), typecheck:core clean, focused tests green.

Empty-envelope 400 (no error field, empty content, finish_reason null) now rotates/retries instead of propagating as success; 200/streaming path never buffered; real-error 400s untouched. account-rotation + new rotation suite 34/34 on the board. Thank you @maxmad64bis!
2026-08-22 21:51:22 -03:00
Praveen K Palaniswamy
92ef3c71ea fix(resilience): honor shared-registry passthrough providers (#11071) (#11165)
Validated on a worktree over the current tip: account-fallback-service 91/91 plus the five sibling lockout suites 24/24. The measurement in the body (40 of 111 passthroughModels providers uncovered on this branch) is the clincher — one lookup via getProviderById().passthroughModels beside the existing checks, closing the #11071 remainder for shared-registry gateways (port of #11075 which had only landed on main). Thank you @yourspraveen!
2026-08-22 20:43:15 -03:00
Praveen K Palaniswamy
2edb7a1fdf fix(dashboard): keep the provider registry out of node:net (#11122) (#11154)
Validated on a worktree over the current tip: the red it fixes reproduced exactly as described (media-page-client-browser-bundle red since #11122 — providerRegistry became reachable from the dashboard client bundle via node:net). Post-fix: bundle test 2/2 green, new ip-parity suite + is-local-provider 7/7, all 7 outboundUrlGuard consumer suites 76/76 (the moved normalizeHost/isPrivateHost keep their re-exports; routing behavior untouched). Thank you @yourspraveen — clean surgical extraction with a pure-JS ipVersion mirroring Node's own regexes.
2026-08-22 20:38:44 -03:00
Rouzbeh†
805252a924 feat(mcp): implement dynamic runtime tool schema plumbing for blocked providers (#11100) (#11155)
Cherry-picked onto the current tip (authorship preserved), generated-count noise stripped. Two pre-merge adjustments: (1) dropped the unrelated localDb.ts re-export hunk (nothing in this PR uses those symbols); (2) automated security review flagged the blocked-provider list resolving once at server creation — the handler now rebuilds the schema per invocation via the resolver (advertised tools/list schema stays a creation-time snapshot, which is inherent to MCP). Vitest: new runtime-blocked-schema suite 3/3, full MCP __tests__ 118/118; contract suites (mcp-web-search-provider-enum-contract, search-blocked-providers-11100) 6/6; typecheck clean. This closes the residual gap noted when #11120 was closed. Thank you @rqzbeh!
2026-08-22 20:23:04 -03:00
Rouzbeh†
64b7389fe9 fix(tests): update translate-path golden snapshot and docs for hailuo-web (#11000) (#11161)
Cherry-picked onto the current tip (authorship preserved), noise files stripped. Pre-merge addition: regenerated the golden snapshot with UPDATE_GOLDEN=1 because the branch's snapshot predated two legitimate tip changes — the dify bare-root from #11065 and the hackclub removal from #11123. The regen'd delta contains exactly those two (audited). This also drains a live base-red: provider-translate-path-golden was failing on the pure tip. 3/3 green. Thank you @rqzbeh!
2026-08-22 20:10:24 -03:00
Harvey Doan
c19c73fdc8 fix(claude): restore canonical tool names so Claude Code accepts tool calls (#11085)
Merged after conflict resolution validated on the combined board (50/50 casing tests green, typecheck:core clean). Two pre-merge adjustments on the branch: (1) the utilization route conflict resolved to the tip shape — its asNullableString/displayName version is newer than the branch's; (2) dropped the newly-added src/lib/db/connections.ts, orphaned once the route kept the tip shape (tip already uses getProviderConnectionById) — nothing imported it. The casing fix itself lands intact: non-streaming OpenAI→Claude conversion now restores canonical tool names, identity echoes no longer pin lowercase, and TOOL_RENAME_MAP gained the Task* tools. Fixes the live-reproduced Claude Code 'No such tool available: bash' failures. Thank you @linhdmn — outstanding repro and root-cause writeup!
2026-08-22 19:00:39 -03:00
Reza Rezaei
e15af18d17 fix(kimi): point kimi-web to international www.kimi.ai (#11045)
Validated on the combined board over tip 80d931ae: kimi suites green (executor-kimi-web, kimi-partner-aff-links, token-health-check-kimi 33 assertions), vitest providerPageHeaderKimiPartnerLink green, typecheck:core clean. Audited the diff: only kimi-web switches to the international www.kimi.ai (Connect-RPC base, website, auth hints); kimi-coding / kimi-coding-apikey affiliate links stay on kimi.com as intended — asserted by the updated tests. Owner approved merge without the VPS smoke. Thank you @MeRezaRezaei!
2026-08-22 18:55:23 -03:00
Andrew B.
56540f24c5 fix(api): save call logs and add endpoint fallback for local rerank providers (#11081)
Validated on a combined board over tip aa128736: focused tests local-rerank-logging + call-logs-row-filter green (7/7 across runs), typecheck:core clean. One pre-merge fix: widened waitForCallLogSaves 5s→15s — the call-log artifact writer's fsync latency exceeds 5s under a loaded host (pre-existing call-log-save-drain flakes identically on the pure tip), so the budget was load-flaky, not the code. Local rerank now logs call entries on success and error paths like embeddings/cloud rerank, captures full request/response payloads, attaches x-omniroute-* headers, and falls back /v1/rerank→/rerank on 404. Thank you @AndrianBalanescu!
2026-08-22 16:54:17 -03:00
Rouzbeh†
aa12873686 fix(providers): remove Hack Club AI provider (#11118) (#11123)
Cherry-picked the author's cleaned single-commit head onto the current tip. One fix applied pre-merge: the removal migration collided at number 161 with today's config_audit_log migration (#11103) — renumbered to 162_remove_hackclub_provider.sql. Focused tests: remove-hackclub-11118 + provider-metrics-deleted-provider green; check:provider-consistency OK (266/348/0). Provider removal requested by Hack Club maintainers (#11118). Thank you @rqzbeh!
2026-08-22 16:26:38 -03:00
Rouzbeh†
367ae2fb97 fix(search): enforce blockedProviders setting on search endpoint (#11100) (#11125)
Cherry-picked the three value commits onto the current tip, dropping the stale base-red sync commits. Focused tests: search-blocked-providers-11100 + search-registry/searxng-loopback/chat-guard/x-search suites 65/65. Fixes #11100 (endpoint half) — GET /v1/search now honors blockedProviders via getAllSearchProviders. Thank you @rqzbeh!
2026-08-22 16:13:26 -03:00
Rouzbeh†
4220c810ee fix(resilience): include RFC1918, CGNAT, and mDNS hosts in isLocalProvider (#11091) (#11122)
Cherry-picked both value commits (a1fa49a8 + a91f6e93, incl. the fail-open guard for unparseable hostnames) onto the current tip, dropping the stale base-red sync commits. Focused tests: is-local-provider-11091 + the isLocalProvider consumer suites (provider-validation-specialty, ollama-local-provider) 127/127; mutation coverage no-drift. Fixes #11091 — RFC1918/CGNAT/link-local/mDNS hosts now classify as local via the existing isPrivateHost. Thank you @rqzbeh!
2026-08-22 16:08:22 -03:00
Rouzbeh†
50fc0d7299 fix(resilience): keep Ollama model-not-found failures scoped to connection model lockout (#11071) (#11078)
Cherry-picked the value commit (2c9202e4) onto the current tip, dropping the stale base-red sync commits. Focused tests: ollama-404-model-lockout 2/2 + the five sibling lockout suites (combo-provider-cooldown-sibling, 8247-model-unhealthy, vertex-passthrough, nvidia-410, account-fallback-service) 112/112; mutation coverage no-drift. Fixes #11071 — local/self-hosted 404s now scope to model lockout per the resilience doctrine. Thank you @rqzbeh!
2026-08-22 16:06:06 -03:00
Rouzbeh†
a51b8ba563 fix(cline): use valid modelType/model format for Cline provider models (#11099) (#11132)
Cherry-picked the value commit (ac09b6b5) onto the current release tip, dropping the stale base-red sync commits that no longer apply. Focused test cline-model-format-11099 2/2 green; check:provider-consistency OK (267/348/0). Fixes #11099 — the zai→z-ai namespace typo. Thank you @rqzbeh!
2026-08-22 15:52:13 -03:00
Dizzle
5631e91f0d fix(providers): learn reasoning_effort capability from upstream 4xx instead of a hardcoded/opt-out default (#11116)
Validated on the combined batch board over release/v3.8.50 tip d91238b7: static gates clean, typecheck:core clean, focused tests green.

Learned reasoning_effort caps mirror the merged learnedThinkingCaps mechanism: parse the upstream 4xx enum, clamp, retry once, consult proactively — covers custom openai-compatible connections the static registry can't. 22 new test cases + full regression list green. Fixes #11111. Thank you @maxmad64bis!
2026-08-22 14:40:57 -03:00
Dizzle
1dd0173468 fix(sse): assign a stable index/id to parallel function_call items in Responses->Chat translation (#11144)
Validated on the combined batch board over release/v3.8.50 tip d91238b7: static gates clean, typecheck:core clean, focused tests green.

TDD red->green: parallel function_call items now get distinct stable index/id at .added time via a per-call Map, interleaved argument deltas no longer glue, dual item_id/output_index correlation. 120-test translator suite green. Thank you @maxmad64bis!
2026-08-22 14:40:45 -03:00
Dizzle
c89fc6ba2a feat(providers): let operators add per-provider error rules via settings (#11104)
Validated on the combined batch board over release/v3.8.50 tip d91238b7: static gates clean, typecheck:core clean, focused tests green.

Operator-declared per-provider error rules via settings, consulted before the built-ins; the allowlist bypass is correct — declaring a rule is itself the opt-in, and no provider-specific rule is hardcoded. Thank you @maxmad64bis!
2026-08-22 14:40:35 -03:00
Dizzle
d021423af3 fix(sse): default summary + strip malformed id on kept Responses input items (#11110)
Validated on the combined batch board over release/v3.8.50 tip d91238b7: static gates clean, typecheck:core clean, focused tests green.

Defaults summary and strips malformed ids on kept Responses input items — both 400s observed against live muse-spark traffic; the flipped legacy assertion is documented contract propagation. Thank you @maxmad64bis!
2026-08-22 14:39:47 -03:00
Dizzle
efc7134167 fix(registry): restore models[0] default + guards; note muse-spark overlay (#11051/#11049) (#11133)
Validated on the combined batch board over release/v3.8.50 tip d91238b7: static gates clean, typecheck:core clean, focused tests green.

Restores the models[0] dashboard default silently changed by #11051, with narrow guards instead of a brittle full snapshot. Thank you @maxmad64bis!
2026-08-22 14:39:12 -03:00
Dizzle
02a078e95f fix(sse): default summary on freshly-built Chat->Responses reasoning items (#11129)
Validated on the combined batch board over release/v3.8.50 tip d91238b7: static gates clean, typecheck:core clean, focused tests green.

Live-confirmed 400 (missing summary on freshly-built Chat->Responses reasoning items); the two legacy assertions updated are contract propagation, each commented. Thank you @maxmad64bis!
2026-08-22 14:38:39 -03:00
Dizzle
d9b3ce266f test(stream): direct coverage + comment for splitConcatenatedToolCallArguments (#11043 followup) (#11135)
Validated on the combined batch board over release/v3.8.50 tip d91238b7: static gates clean, typecheck:core clean, focused tests green.

Test-only followup to #11043 — 3 direct tests for splitConcatenatedToolCallArguments plus the index-normalization comment, exactly the two review nits. Thank you @maxmad64bis!
2026-08-22 14:38:28 -03:00
Dizzle
da490a759f fix(sse): resume stream recovery after a completed tool call (#11109)
Validated on the combined batch board over release/v3.8.50 tip d91238b7: static gates clean (changelog-integrity, file-size, complexity 2619<=2774, cognitive 1178<=1223, dead-code 411<=416), typecheck:core clean, focused tests green (262 batch-touched tests pass; the only red is the pre-existing vi.json harImport key drift from #11069, reproduced on the pure tip — not this batch).

Follow-up fix pushed to the branch pre-merge: the changelog fragment was prose, now a bullet (fragment gate). Thank you @maxmad64bis — the root-cause writeup (per-call finish_reason vs general terminal marker making the in-flight guard a no-op) is exactly right.
2026-08-22 14:37:58 -03:00