Repository navigation
Release v3.8.12 - #3264
Release v3.8.12#3264
Conversation
Bump 3.8.11 → 3.8.12 across package.json, lockfile, electron/, open-sse/, and docs/reference/openapi.yaml; add the [3.8.12] cycle placeholder to the root CHANGELOG and the 41 i18n mirrors. Integration branch for the v3.8.12 cycle — fixes/features land here via per-issue PRs and it merges to main at release time.
|
Warning You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again! |
Code Review SummaryStatus: 1 Issue (carried forward) + 1 New Warning | Recommendation: Address before merge Overview
Issue Details (click to expand)CRITICAL
WARNING
Resolved Issues (fixed in incremental diff)
Files Reviewed (4 files in incremental diff)
Fix these issues in Kilo Cloud Reviewed by step-3.7-flash-20260528 · 530,503 tokens |
CI Coverage Report
Coverage artifact was not available for this run. |
… anti-bot (#3180) (#3249) grok-web: TLS fingerprint impersonation to bypass Cloudflare anti-bot (#3180); sanitize executor error bodies (#12). Integrated into release/v3.8.12. Thanks @wilsonicdev.
Provider refresh/validation, OpenRouter catalog and proxy UI fixes — incl. NVIDIA NIM /models-suffix path fix (real-VPS validated). Integrated into release/v3.8.12. Thanks @strangersp.
| } | ||
|
|
||
| function randomSessionId(): string { | ||
| return Array.from({ length: 8 }, () => |
There was a problem hiding this comment.
WARNING: Insecure randomness - Math.random() is not cryptographically secure. This generates session IDs and server IDs for WebSocket connections. Use crypto.randomUUID() or randomInt from node:crypto instead.
|
|
||
| it("buildUrl returns Amelia endpoint", () => { | ||
| const url = executor.buildUrl("pepper-1", false); | ||
| assert.ok(url.includes("amelia.chipotle.com")); |
There was a problem hiding this comment.
CRITICAL: Incomplete URL substring check. The test only verifies url.includes("amelia.chipotle.com") which would pass for malicious URLs like https://evil.com#amelia.chipotle.com. Use a proper URL parser or check that the result starts with the expected base URL.
…3256) Block cross-dimension failover in embedding combos. Integrated into release/v3.8.12.
Synchronized deploy-vps hardening (PM2 recreate via bin + /api/monitoring/health gate + fail-on-unhealthy). Supersedes #3262. Integrated into release/v3.8.12.
…r connections (#3271) Bulk activate/deactivate/retest for selected provider connections. Integrated into release/v3.8.12. Thanks @leninejunior.
#3260) (#3275) ds-web/deepseek-v4-pro emits tool calls wrapped as <tool_call name="skill">{"name":"customize-opencode"}</tool_call> instead of the canonical <tool>{json}</tool>. webTools.ts only matched <tool>...</tool>, so the block was silently dropped (and when arguments were present, the surrounding tag leaked into content). Add TOOL_CALL_TAG_RE to capture the JSON body — the real tool name comes from the body, never the tag's name= attribute — and extend the early-exit + range stripping. Regression test: tests/unit/web-tools-translation-3260.test.ts (RED before, GREEN after). Existing web-tools suites stay green (26/26).
#3277) Regression of #764. Claude Code → Groq (llama-3.3-70b-versatile) returned HTTP 400 because the model was treated as reasoning-capable: supportsReasoning() defaulted to true, so applyThinkingBudget did not strip reasoning params, and the claude→openai translator forwarded reasoning_effort (and re-injected it from output_config.effort) — which Groq rejects on non-reasoning models. - providerRegistry: mark llama-3.3-70b-versatile + llama-4-scout supportsReasoning:false (gpt-oss / qwen3-32b keep reasoning — they accept reasoning_effort). - stripThinkingConfig: also strip output_config.effort so the translator can't re-inject reasoning_effort downstream. Regression test: tests/unit/thinking-budget-groq-3258.test.ts (RED before, GREEN after); existing thinking-budget suites stay green (45/45).
…Data (#3273) (#3278) A custom OpenAI-compatible image-edit provider received an empty `model`. In production `globalThis.fetch` is patched with node_modules/undici's fetch, whose `FormData` class differs from `globalThis.FormData`; passing a native FormData made undici serialize it as the string "[object FormData]" (text/plain), dropping every field including `model`. handleOpenAIImageEdit now assembles the multipart body as a Buffer with an explicit boundary + Content-Type, which every fetch impl accepts verbatim. Regression test: tests/unit/image-edits-multipart-3273.test.ts reproduces the exact prod condition (routes through undici's fetch) — RED before (upstream got text/plain [object FormData]), GREEN after. Existing image suites stay green (50/50).
…utors hall Audited every commit since v3.8.11 one-by-one. Added the missing v3.8.12 entries (features #3250/#3259/#3263/#3271, fixes #3248/#3249/#3261/#3256/#3274, maintenance #3270), repointed the combo-rewrite and web-tools entries to their actually-merged PRs (#3268, #3275) instead of the closed #3242/issue links, and added the v3.8.12 Contributors hall. Also co-credited @ibanunmangun on the v3.8.11 #3203 OAuth fix (independent first diagnosis via #3193).
#3279) Webhooks hardcoded parseAndValidatePublicUrl, which blocks any RFC1918/loopback host — breaking self-hosted setups that legitimately point webhooks at internal services (n8n, Home Assistant, a LAN box). Provider URLs already had an opt-in (OMNIROUTE_ALLOW_PRIVATE_PROVIDER_URLS); webhooks now reuse it. - outboundUrlGuard: add parseAndValidateWebhookUrl — gates the private-host check on arePrivateProviderUrlsAllowed() (default OFF); protocol + embedded-credential checks stay unconditional. - swap all webhook call sites (create/update/test/validate-url + dispatcher x2) to it. Regression test: tests/unit/webhook-private-optin-3269.test.ts (RED before, GREEN after); existing webhook SSRF/dispatcher suites stay green (33/33).
…3269) (#3281) Follow-up to the #3269 private-webhook opt-in. With the opt-in on, the private-host check was bypassed entirely, leaving cloud-metadata endpoints (169.254.169.254, metadata.google.internal, 100.100.100.200, link-local 169.254.0.0/16) reachable — the classic SSRF -> IAM-credential pivot — and the webhook test endpoint returned the upstream body, making it a content-exfiltration primitive against internal services. - outboundUrlGuard: add isCloudMetadataHost(); parseAndValidateWebhookUrl blocks those hosts UNCONDITIONALLY, even when private targets are opted in. - webhooks/[id]/test: redact responseBody for private targets (status + latency only). Regression test: tests/unit/webhook-metadata-guard-3269.test.ts (RED before, GREEN after); existing webhook SSRF/opt-in suites stay green (34/34).
…3247) (#3283) A working Qoder PAT was reported as "expired". The validator probes the Cosy endpoint (api1.qoder.sh) — which IS the correct PAT path (the executor falls back to it after the expected 401 from api.qoder.com). The bug was the verdict: isCosyAppError (added by #2860) marked ANY Cosy 500 with "success":false as an auth failure, including a generic {..."msgCode":500,"message":"Internal Server Error"} server fault — contradicting the older #1391 "5xx = valid bypass" rule. Narrow it: a Cosy 500 only marks the PAT invalid when the body carries an EXPLICIT auth signal (unauthorized/forbidden/expired/token invalid/...); a generic Internal Server Error falls back to valid-bypass. #2860's protection for genuine auth rejections is preserved. Regression test: tests/unit/qoder-cli.test.ts — the two pre-existing generic-500 cases now assert valid:true (they encoded the #3247 bug) + a new explicit-auth-signal case asserts valid:false. 13/13 green.
…trip) + soften ToS framing to caution (#3284) - Regenerate the README/dashboard mockup from the catalog: 28 pools in the grid (was 9), a balance-floored stacked bar (Mistral now ~40% of the bar, was ~90%), and a first-month signup-credit strip (~586M). Add the data-driven generator. - FREE_TIERS.md: drop the alarming '🚫 Avoid / terms prohibit' framing — relabel those 19 providers as 'caution — worth checking', note their access is real and the OAuth/keyless ones aren't token-quantifiable (so out of the headline, not excluded as unusable).
…s, webhooks, and embeddings enforcement (#3280) Integrated into release/v3.8.12. Quota Sharing Engine fixes: poolUsageWithDimensions promoted to the QuotaStore interface, single-snapshot burn rate, zero-weight normalization, Anthropic saturation signals, quota.exceeded webhook on block, and embeddings enforcement. Validated: 10/10 PR tests + 34 quota/embedding regression files green, typecheck + lint clean. Dropped the committed .omo/ agent-tooling artifacts.
…is (#3282/#3247) The #3247 fix shipped via #3283 (parallel session) 46s after @wilsonicdev filed the same fix in #3282, leaving his PR stranded with no credit — the #3242 credit-theft pattern. Repoint the entry to the merged #3283, credit @wilsonicdev as co-author for the independent diagnosis, and note #3283 refined it to keep rejecting on an explicit-auth-signal 500.
…er in test (#3285) Integrated into release/v3.8.12. CodeQL hardening on the Chipotle executor: Math.random → crypto.randomInt/randomUUID, and a strict URL hostname check in the test. Fixed the node:crypto import (crypto.randomInt is not on the Web Crypto global → would crash at WS-connect) and added a regression guard exercising both helpers.
Integrated into release/v3.8.12. Registers MiniMax-M3 (1M context, Anthropic-compatible) across 8 provider tiers (minimax, minimax-cn, opencode, opencode-go, opencode-zen, trae, ollama-cloud, nvidia). Validated: 8/8 new registry tests + 25 registry/model-catalog regression files green, typecheck + lint clean. Complements the #3141 max_tokens spec already on release.
…sApp) + promote Free-Token Budget section (#3289) - Add the official Telegram group (t.me/omnirouteOficial) and gather Discord, Telegram and both WhatsApp groups into one community card block at the top; remove the scattered WhatsApp links from the nav line and the Support section (now a pointer to the top). - Move the Free-Token Budget section from the bottom (before License) up to a hero section near the top, retitled '💰 ~1.9B Free Tokens / Month'.
…#3286) Integrated into release/v3.8.12. Salvaged the emitHookBlocking payload-chaining fix from the now-closed plugins-v4 branch (#3221) and adapted it to the shipped release hooks.ts: each blocking handler now sees the body/metadata as mutated by previous handlers. TDD regression test included (RED before, GREEN after); existing plugins-hooks suites green (19+5), typecheck + lint clean.
test:coverage now enforces 60/60/60/60 (statements/lines/functions/branches); real coverage is ~75-82% so this tightens the floor without new test work. Updates the c8 --check-coverage thresholds in package.json and the matching references in CLAUDE.md (Quick Start, testing table, Copilot policy, Hard Rule #9). Salvaged from the never-pushed chore/skills-governance-tdd-vps branch; the i18n CLAUDE.md mirrors carry a separate pre-existing drift and are not gated by check-docs-sync.
….12 diff - chipotle/grokTls: explicit null checks instead of a Promise in a boolean conditional (behavior-preserving; clears the 2 MAJOR reliability bugs) - sqliteQuotaStore.poolUsage: drop the unreachable dimMap scan loops (dimMap was never populated) — the lightweight snapshot already returns no dimensions; poolUsageWithDimensions() is the plan-aware path - BudgetTab: presentation role + keyboard handler on the checkbox wrapper
|
Release v3.8.12
Release v3.8.12
Release v3.8.12


[3.8.12] — 2026-06-06
✨ New Features
sanitizeErrorMessage()(Hard Rule fix(ui): fix Select dropdown dark theme inconsistency #12) (#3250 — thanks @oyi77)webToolshelpers, so cookie-backed providers can participate in tool/function calling through a single serialize/parse path (#3259 — thanks @oyi77)minimax,minimax-cn,opencode(free),opencode-go,opencode-zen,trae,ollama-cloud,nvidia(#3287, [Feature] Minimax M3 #3110 — thanks @wilsonicdev)🔧 Bug Fixes
paid-premium,n8n-text) are no longer force-rewritten tocodex/<combo>on/v1/responses—resolveResponsesApiModelnow returns the request unchanged when the model resolves to a combo (regression from the v3.8.9 Codex WS→HTTP fallback) (#3268, fixes [BUG] Combo names incorrectly resolved as Codex models in v3.8.9+ #3227 / [BUG] Combos suddenly broken #3233 — thanks @wilsonicdev; supersedes the earlier closed fix(v1/responses): skip codex rewrite for combo names (#3233, #3227) #3242)<omniModel>tag before forwarding to the provider, not just the first — a global-regex variant prevents stray routing tags from leaking into the upstream prompt (#3248, fixes [UI/Bug] Integration of #401 and #399 Features into Combo Dashboard and Tag Removal Logic #454 — thanks @MikeTuev)sanitizeErrorMessage()(Hard Rule fix(ui): fix Select dropdown dark theme inconsistency #12) (#3249, fixes [BUG] Grok Web (Subscription) validation still fails on v3.8.9 after #3063 was closed #3180 — thanks @wilsonicdev)/models-suffix probe path (real-VPS validated) (#3261 — thanks @strangersp)ds-web/deepseek-v4-pro) that wrap tool calls as<tool_call name="...">{json}</tool_call>are now parsed correctly — the real tool name is read from the JSON body instead of the tag attribute, and the call is no longer silently dropped whenargumentsis absent (#3275, fixes [BUG] ds-web tool calls with XML wrapper <tool_call name="skill"> fail — fuzzy matcher reads tag attribute instead of JSON body #3260 — thanks @diegosouzapw)llama-3.3-70b-versatile,llama-4-scout) are now flaggedsupportsReasoning: false, soreasoning_effort/output_config.effort/thinkingare stripped before dispatch instead of being forwarded and rejected with HTTP 400 — fixes the Claude Code → Groq regression of fix: HTTP 400 when reasoning/thinking params sent to models that don't support them #764 (#3277, fixes [BUG] Regression of #764: Claude Code → Groq still fails withreasoning_effortHTTP 400 #3258 — thanks @diegosouzapw)POST /v1/images/editsto a custom OpenAI-compatible provider no longer forwards an emptymodel. The multipart body is now built as aBufferwith an explicit boundary instead of a globalFormData— the patched undicifetchserialized a nativeFormDataas the literal string[object FormData](text/plain), dropping every field includingmodel(#3278, fixes Custom OpenAI-compatible /v1/images/edits forwards multipart incorrectly: upstream receives empty model #3273 — thanks @diegosouzapw)poolUsageWithDimensions()promoted onto theQuotaStoreinterface (kills the dynamic type-narrowing hack), single-snapshot burn rate viacomputeBurnRateFromWindow()(the dashboard previously always showed 0), zero-weight allocations normalized to equal distribution, Anthropicanthropic-ratelimit-*saturation signals, aquota.exceededwebhook fired on block, and quota enforcement extended to the embeddings handler (#3280 — thanks @oyi77)emitHookBlockingnow chains the payload between handlers — each blocking handler receives the body/metadata as mutated by previous handlers, so a later plugin can observe an earlier plugin's changes (previously every handler got the original static payload) (#3286 — thanks @oyi77)192.168.x, a docker-internal host) whenOMNIROUTE_ALLOW_PRIVATE_PROVIDER_URLS=true— the webhook guard reuses the same explicit opt-in as private provider URLs (default OFF; protocol and embedded-credential checks stay unconditional). Cloud-metadata / link-local endpoints (169.254.169.254,metadata.google.internal,100.100.100.200,169.254.0.0/16) are blocked unconditionally even with the opt-in on, and the webhook test endpoint redacts the upstream response body for private targets (no SSRF→IAM-credential pivot, no content exfiltration) (#3279, #3281, fixes [BUG] why can not using a private address in add new webhook #3269 — thanks @diegosouzapw)Internal Server Error(HTTP 500). A Cosy 500 only marks the PAT invalid when its body carries an explicit auth signal; a generic server fault now falls back to the [BUG] Qoder PAT validation is a false negative: dashboard says Invalid while qodercli works #1391 valid-bypass rule (#3283, fixes [BUG] Qoder AI provider is telling expired PAT token even if i paste new PAT token which is working in its Qoder CLI #3247 — thanks @wilsonicdev, who independently diagnosed the same root cause and filed #3282; refined here to keep rejecting on an explicit-auth-signal 500)📝 Maintenance
deploy-vpsrecreates the PM2 process via theomniroutebin (instead of a barepm2 restartpinned to the removedapp/server-ws.mjspath) and gates the deploy on/api/monitoring/healthreporting"status":"healthy", failing the job (with recent PM2 logs) when the box never becomes healthy — supersedes fix(ci): deploy-vps via omniroute bin + fail on unhealthy boot #3262 (#3270 — thanks @diegosouzapw)Math.random()→crypto.randomInt()/crypto.randomUUID()(imported fromnode:crypto) for session/server IDs, and a strictnew URL().hostnamecheck (replacing a substring match) in its test (#3285 — thanks @oyi77)🙌 Contributors
Thanks to everyone whose work landed in v3.8.12:
Quality Gate (2026-06-06)
.claude/worktrees/review-prscheckout — CI runs on a clean checkout and is unaffected)OMNIROUTE_GROK_TLS_TIMEOUT_MS/OMNIROUTE_GROK_TLS_GRACE_MSto .env.example + ENVIRONMENT.md)sidebar-costs-section,t12 minimax) were aligned to the new free-tiers nav (feat(free-tiers): per-model free-token budget + Monthly Budget dashboard card #3263) and MiniMax-M3 (feat(models): add MiniMax M3 across all provider tiers (#3110) #3287) and verified 10/10; the only remaining intermittent failures are the documented concurrency flakes (chatcore-translation-paths,observability-fase04circuit-breaker reset window), each of which passes 100% in isolation (65/65, 16/16)Coverage of commits since v3.8.11
v3.8.11..release/v3.8.12After merge → deploy
mainto the Local VPS (192.168.0.15) for homologation → wait for operator OK → only then tag + GitHub release + npm/Docker/Electron.