Skip to content

Commit 78f09c8

Browse files
authored
Release v3.8.41 (#5327)
Release v3.8.41 — 52 commits since v3.8.40 (19 CHANGELOG bullets, 11 contributors). All gating CI green: Unit×8, Coverage×8, Vitest, Package Artifact, Quality Ratchet, CodeQL, Lint, Docs Sync (Strict), Node 24/26 compat, E2E×9, Integration, Electron smoke. Advisory checks overridden (main unprotected): PR Test Policy = test-masking heuristic on the cumulative 52-commit assert delta (legitimate dead-code-sweep removals + consolidations, reviewed per-PR); SonarCloud/SonarQube = new-code maintainability/coverage quality gate (CodeQL/Semgrep/Security/npm-audit/Dependabot all clean — not a security finding).
1 parent 7c23dab commit 78f09c8

222 files changed

Lines changed: 6005 additions & 1205 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.env.example

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1786,6 +1786,23 @@ QUOTA_STORE_DRIVER=sqlite # sqlite | redis
17861786
# Alias for BIFROST_API_KEY (used by scripts that read the env via
17871787
# OMNIROUTE_*). Falls back to BIFROST_API_KEY when unset.
17881788
# OMNIROUTE_BIFROST_KEY=
1789+
# Relay backend selection for the OpenAI-compatible relay endpoint:
1790+
# ts | bifrost | auto. "ts" (default when Bifrost is not configured) uses the
1791+
# TypeScript relay; "auto" selects Bifrost when BIFROST_BASE_URL is set (and
1792+
# BIFROST_ENABLED != 0) and falls back to TS if the sidecar is unreachable;
1793+
# "bifrost" forces Bifrost (strict — no TS fallback). Auth, rate limits,
1794+
# injection guard and model allowlists always run in the Next route first.
1795+
# RELAY_ROUTING_BACKEND is an accepted alias. Responses carry X-Routing-Backend
1796+
# and X-Routing-Fallback.
1797+
# OMNIROUTE_RELAY_BACKEND=
1798+
# RELAY_ROUTING_BACKEND=
1799+
# Opt-in native HTTPS/TLS for `omniroute serve` (equivalent to --tls-cert /
1800+
# --tls-key). Provide BOTH a PEM certificate and its private key and the
1801+
# standalone server terminates TLS on the same listener (wss:// works
1802+
# unchanged). With neither set the server stays plain HTTP; providing only one
1803+
# (or an unreadable path) logs a warning and stays HTTP (never half-enables).
1804+
# OMNIROUTE_TLS_CERT=
1805+
# OMNIROUTE_TLS_KEY=
17891806

17901807
# ─── 1-click local service launchers (PR-3 in #3932) ────────────────────────
17911808
# Master switch for /api/local/* routes. When unset or "0", all /api/local/*

CHANGELOG.md

Lines changed: 32 additions & 2 deletions
Large diffs are not rendered by default.

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,7 @@ Result: 4 layers of fallback = zero downtime
290290

291291
</div>
292292

293-
> Recent highlights from **v3.8.20 → v3.8.39**. Full history in [`CHANGELOG.md`](CHANGELOG.md).
293+
> Recent highlights from **v3.8.20 → v3.8.41**. Full history in [`CHANGELOG.md`](CHANGELOG.md).
294294
295295
- **⚖️ Quota-Share routing** — a dedicated combo strategy that spreads load across accounts by _available quota_: Deficit-Round-Robin scheduling, per-connection `max_concurrent` with cooldown-wait queueing, multi-window usage buckets (5h / 7d / per-model), per-(key,model) caps, session stickiness for prompt-cache integrity, and proactive saturation from upstream token-usage headers. → [Resilience Guide](docs/architecture/RESILIENCE_GUIDE.md)
296296
- **🤖 One-command CLI/agent setup** — a dedicated `setup-*` command configures each coding tool to route through OmniRoute (Claude Code, Codex, Cline, Continue, Cursor, Roo Code, Kilo Code, Crush, Goose, Qwen Code, Aider, OpenCode); `omniroute launch` / `omniroute launch-codex` are zero-config launchers. → [CLI Integrations](docs/guides/CLI-INTEGRATIONS.md)
@@ -302,7 +302,7 @@ Result: 4 layers of fallback = zero downtime
302302
- **🧠 Memory you control** — opt-in int8 vector quantization (Qdrant + sqlite-vec), memory off by default, and a per-request `x-omniroute-no-memory` header. → [Memory](docs/frameworks/MEMORY.md)
303303
- **🛡️ Security** — a prompt-injection guard across every LLM route (backed by a red-team suite), plus a free DuckDuckGo last-resort web search. → [Guardrails](docs/security/GUARDRAILS.md)
304304
- **🤝 More providers & agents** — Cursor Cloud Agent (a 4th cloud agent), CodeBuddy CN (`copilot.tencent.com`), a Google Flow video-generation provider, new gateways **DGrid** and **Pioneer AI** (Fastino Labs), inbound **xAI Grok** translators plus **Grok Build (xAI)** with an OAuth import-token flow, GPT-4 / GPT-4o-mini on the GitHub Copilot provider, multi-model **Factory Droid**, **ZenMux Free** (session-cookie free tier), **Alibaba DashScope** text-to-video (`wan2.7-t2v`), a refreshed 237-provider catalog (OrcaRouter, Wafer AI, OpenAdapter, dit.ai, TokenRouter, …), Vertex AI media generation (speech / transcription / music / video), and one-click account import from CLIProxyAPI (`~/.cli-proxy-api/`). → [Providers](docs/reference/PROVIDER_REFERENCE.md)
305-
- **⚡ Local performance & infra** — a one-click local Redis launcher (`omniroute redis up`, plus a dashboard Redis panel), one-click **Cloudflare Workers** and **Deno Deploy** relay deployers wired into the proxy pool, and an optional Bifrost Go sidecar that offloads the hottest relay path (`BIFROST_BASE_URL`, with automatic fallback to the TypeScript path on timeout). → [Environment](docs/reference/ENVIRONMENT.md)
305+
- **⚡ Local performance & infra** — a one-click local Redis launcher (`omniroute redis up`, plus a dashboard Redis panel), one-click **Cloudflare Workers** and **Deno Deploy** relay deployers wired into the proxy pool, and an optional Bifrost Go sidecar that offloads the hottest relay path (`BIFROST_BASE_URL`, with automatic fallback to the TypeScript path on timeout) — now with a relay-backend selector (`OMNIROUTE_RELAY_BACKEND=ts|bifrost|auto`) so the `/v1/relay` endpoint stays the stable surface while choosing the fastest backend internally. → [Environment](docs/reference/ENVIRONMENT.md)
306306

307307
<br/>
308308

bin/cli/commands/serve.mjs

Lines changed: 42 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,16 @@ import { isTermux } from "../../../scripts/build/postinstallSupport.mjs";
1010
import {
1111
resolveMaxOldSpaceMb,
1212
calibrateHeapFallbackMb,
13+
buildServerNodeOptions,
14+
buildNodeHeapArgs,
1315
} from "../../../scripts/build/runtime-env.mjs";
16+
import { resolveTlsOptions } from "../../../scripts/dev/tls-options.mjs";
1417

1518
const __dirname = dirname(fileURLToPath(import.meta.url));
19+
20+
// URL scheme for the "OmniRoute is running" banner — flipped to https when
21+
// opt-in TLS (#5242) is active. Process-scoped: one `serve` run = one scheme.
22+
let urlScheme = "http";
1623
const ROOT = join(__dirname, "..", "..", "..");
1724
// The standalone bundle ships in `dist/` (since the build-output-isolation
1825
// refactor). Fall back to the legacy `app/` location so an upgrade over a
@@ -39,6 +46,14 @@ export function registerServe(program) {
3946
.option("--max-restarts <n>", t("serve.max_restarts"), parseInt, 2)
4047
.option("--tray", t("serve.tray") || "Show system tray icon (desktop only)")
4148
.option("--no-tray", t("serve.no_tray") || "Disable system tray icon")
49+
.option(
50+
"--tls-cert <path>",
51+
t("serve.tls_cert") || "Path to a TLS certificate (PEM) to serve HTTPS (also OMNIROUTE_TLS_CERT)"
52+
)
53+
.option(
54+
"--tls-key <path>",
55+
t("serve.tls_key") || "Path to the TLS private key (PEM) to serve HTTPS (also OMNIROUTE_TLS_KEY)"
56+
)
4257
.action(async (opts) => {
4358
await runServe(opts);
4459
});
@@ -138,6 +153,11 @@ export async function runServe(opts = {}) {
138153
calibrateHeapFallbackMb(totalmem())
139154
);
140155

156+
// #5242: opt-in native HTTPS. CLI flags take precedence over env; the child
157+
// server (server-ws.mjs) reads these and terminates TLS on the same listener.
158+
const tlsCert = opts.tlsCert ?? process.env.OMNIROUTE_TLS_CERT;
159+
const tlsKey = opts.tlsKey ?? process.env.OMNIROUTE_TLS_KEY;
160+
141161
const env = {
142162
...process.env,
143163
OMNIROUTE_PORT: String(port),
@@ -146,9 +166,19 @@ export async function runServe(opts = {}) {
146166
API_PORT: String(apiPort),
147167
HOSTNAME: process.env.HOSTNAME || "0.0.0.0",
148168
NODE_ENV: "production",
149-
NODE_OPTIONS: `--max-old-space-size=${memoryLimit}`,
169+
// #5238: preserve a user-set NODE_OPTIONS (incl. their own
170+
// `--max-old-space-size=…`) instead of clobbering it with the calibrated
171+
// default — mirror the Electron/standalone launchers.
172+
NODE_OPTIONS: buildServerNodeOptions(process.env, memoryLimit),
173+
...(tlsCert ? { OMNIROUTE_TLS_CERT: tlsCert } : {}),
174+
...(tlsKey ? { OMNIROUTE_TLS_KEY: tlsKey } : {}),
150175
};
151176

177+
// Validate the TLS pair up front so the operator sees a clear warning in the
178+
// CLI (the child re-validates authoritatively). Drives the banner scheme;
179+
// when null we fall through to identical plain-HTTP behavior as before.
180+
urlScheme = resolveTlsOptions(env) ? "https" : "http";
181+
152182
const isDaemon = opts.daemon === true;
153183
const useTray = opts.tray === true;
154184

@@ -174,7 +204,9 @@ export async function runServe(opts = {}) {
174204
}
175205

176206
function runDaemon(serverJs, env, memoryLimit, dashboardPort, apiPort) {
177-
const server = spawn("node", [`--max-old-space-size=${memoryLimit}`, serverJs], {
207+
// #5238: skip the explicit CLI --max-old-space-size when the user pinned the
208+
// heap via NODE_OPTIONS (a CLI arg would shadow/override their value).
209+
const server = spawn("node", [...buildNodeHeapArgs(process.env, memoryLimit), serverJs], {
178210
cwd: APP_DIR,
179211
env,
180212
stdio: "ignore",
@@ -183,12 +215,14 @@ function runDaemon(serverJs, env, memoryLimit, dashboardPort, apiPort) {
183215
writePidFile("server", server.pid);
184216
server.unref();
185217
console.log(`\x1b[32m✔ OmniRoute started in background (PID: ${server.pid})\x1b[0m`);
186-
console.log(` \x1b[1mDashboard:\x1b[0m http://localhost:${dashboardPort}`);
187-
console.log(` \x1b[1mAPI Base:\x1b[0m http://localhost:${apiPort}/v1`);
218+
console.log(` \x1b[1mDashboard:\x1b[0m ${urlScheme}://localhost:${dashboardPort}`);
219+
console.log(` \x1b[1mAPI Base:\x1b[0m ${urlScheme}://localhost:${apiPort}/v1`);
188220
}
189221

190222
function runWithoutRecovery(serverJs, env, memoryLimit, dashboardPort, apiPort, noOpen) {
191-
const server = spawn("node", [`--max-old-space-size=${memoryLimit}`, serverJs], {
223+
// #5238: skip the explicit CLI --max-old-space-size when the user pinned the
224+
// heap via NODE_OPTIONS (a CLI arg would shadow/override their value).
225+
const server = spawn("node", [...buildNodeHeapArgs(process.env, memoryLimit), serverJs], {
192226
cwd: APP_DIR,
193227
env,
194228
stdio: "pipe",
@@ -312,7 +346,7 @@ async function maybeStartTray(port, apiPort, supervisor) {
312346
const { initTray, isTraySupported } = await import("../tray/index.mjs");
313347
if (!isTraySupported()) return;
314348
const { default: open } = await import("open").catch(() => ({ default: null }));
315-
const dashboardUrl = `http://localhost:${port}`;
349+
const dashboardUrl = `${urlScheme}://localhost:${port}`;
316350
const tray = await initTray({
317351
port,
318352
onQuit: () => {
@@ -339,8 +373,8 @@ async function maybeStartTray(port, apiPort, supervisor) {
339373
}
340374

341375
async function onReady(dashboardPort, apiPort, noOpen) {
342-
const dashboardUrl = `http://localhost:${dashboardPort}`;
343-
const apiUrl = `http://localhost:${apiPort}`;
376+
const dashboardUrl = `${urlScheme}://localhost:${dashboardPort}`;
377+
const apiUrl = `${urlScheme}://localhost:${apiPort}`;
344378

345379
console.log(`
346380
\x1b[32m✔ OmniRoute is running!\x1b[0m

bin/cli/locales/en.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,9 @@
241241
"no_recovery": "Disable auto-restart on crash (debugging mode)",
242242
"max_restarts": "Max crash restarts within 30s before giving up (default: 2)",
243243
"tray": "Show system tray icon (desktop only, opt-in)",
244-
"no_tray": "Disable system tray icon"
244+
"no_tray": "Disable system tray icon",
245+
"tls_cert": "Path to a TLS certificate (PEM) to serve HTTPS (also OMNIROUTE_TLS_CERT)",
246+
"tls_key": "Path to the TLS private key (PEM) to serve HTTPS (also OMNIROUTE_TLS_KEY)"
245247
},
246248
"backup": {
247249
"title": "Backup",

bin/cli/runtime/processSupervisor.mjs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
computeRestartDelayMs,
99
waitUntilPortFree,
1010
} from "./supervisorPolicy.mjs";
11+
import { buildNodeHeapArgs } from "../../../scripts/build/runtime-env.mjs";
1112

1213
const CRASH_LOG_LINES = 50;
1314

@@ -30,7 +31,11 @@ export class ServerSupervisor {
3031
this.crashLog = [];
3132

3233
const showLog = process.env.OMNIROUTE_SHOW_LOG === "1";
33-
this.child = spawn("node", [`--max-old-space-size=${this.memoryLimit}`, this.serverPath], {
34+
// #5238: skip the explicit CLI --max-old-space-size when the user pinned the
35+
// heap via NODE_OPTIONS (a CLI arg would shadow/override their value). The
36+
// calibrated heap is already carried by env.NODE_OPTIONS either way.
37+
const heapArgs = buildNodeHeapArgs(process.env, this.memoryLimit);
38+
this.child = spawn("node", [...heapArgs, this.serverPath], {
3439
cwd: dirname(this.serverPath),
3540
env: this.env,
3641
stdio: showLog ? "inherit" : ["ignore", "ignore", "pipe"],

config/quality/file-size-baseline.json

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
{
22
"_comment": "Catraca de tamanho (check-file-size.mjs). frozen so pode encolher; arquivos novos <= cap. --update ratcheta.",
3+
"_rebaseline_2026_06_29_v3841_release": "callLogs 985->997 + chat 1632->1635 + chatHelpers 811->842 (#5351 opencode visible-rotation-logs/ProxyEgress/SQL-vars), base.ts 1475->1497 + openai-to-claude 805->823 (#5352 thinking hydrate/redacted-replay + #5342 empty-messages guard), accountFallback 1777->1783 (#5346 402 auto-disable depleted key) + account-fallback-service.test 1569->1572 (#5346 test), provider-validation-specialty.test 2801->2843 (#5358 grok cf_clearance + #5337 gemini catalog). Cycle-close drift from merged campaign PRs absorbed at release close per generate-release Phase 0 (the PR->release fast-gates do NOT run check:file-size); all irreducible chokepoint/feature growth next to existing branches, covered by per-PR tests. Structural shrink tracked under decomposition roadmap #3501.",
34
"_rebaseline_2026_06_26_v3838_ownerprs_batch": "Lote /review-prs v3.8.38 (PRs do dono + contribuidores): src/lib/db/providers.ts 1093->1107 (+14 = #5121 cookie-dedup branch extraido para o helper findExistingCookieConnection — a extracao reduz a complexidade ciclomatica de createProviderConnection mas adiciona ~14 linhas ao arquivo; trade-off consciente complexity-vs-file-size) e src/lib/usage/usageHistory.ts 934->983 (+49 = #4940 dedup guard SELECT-before-INSERT + endpoint backfill + scheduleStatsEvent debounce). Crescimento de feature/fix legitimo recem-TDD'd; o fast-path PR->release nao roda check:file-size, entao o ramo acumula sem rebaselinar. Reducao estrutural fica como debt (#3501).",
45
"_rebaseline_2026_06_26_relgreen_db_test": "Release-green follow-up: tests/unit/db-core-init.test.ts 867->877 (+10 = the invalid-DATA_DIR test now captures the rejection and asserts both Error type AND message — restores net-neutral assert count after #5117's consolidation, satisfying check:test-masking — instead of a single assert.rejects).",
56
"_rebaseline_2026_06_26_5074_fusion_editor": "PR #5074 own growth: src/app/(dashboard)/dashboard/combos/page.tsx 4485->4594 (+109 = the Fusion judgeModel + fusionTuning editor block — text/number inputs wired through updateFusionTuning, schema-validated) and tests/unit/combo-config.test.ts 800->881 (testFrozen add: 5 new Fusion-config schema tests). Cohesive UI block at the strategy-conditional editor; combos/page.tsx structural shrink tracked in #3501. Covered by combo-config.test.ts.",
@@ -127,7 +128,7 @@
127128
"_rebaseline_pr1043_minimax_tts": "Upstream port decolua/9router#1043 (toanalien) own growth: audioSpeech.ts 965->1061 (+96). Adds MiniMax T2A v2 TTS dispatch (handleMinimaxSpeech + hexToBytes helper) — provider entry was already in audioRegistry (format: minimax-tts) but no handler existed, falling through to the OpenAI-compatible default that fails (T2A has custom shape + hex-encoded audio + base_resp envelope). New branch sits next to the other inline provider branches (xiaomi-mimo, coqui, tortoise, aws-polly) — extracting would just create indirection. Covered by tests/unit/minimax-tts-1043.test.ts (3 tests, GREEN: success, base_resp error, invalid-hex).",
128129
"open-sse/config/providerRegistry.ts": 4731,
129130
"open-sse/executors/antigravity.ts": 1806,
130-
"open-sse/executors/base.ts": 1475,
131+
"open-sse/executors/base.ts": 1497,
131132
"open-sse/executors/chatgpt-web.ts": 2870,
132133
"open-sse/executors/claude-web.ts": 1057,
133134
"open-sse/executors/codex.ts": 1541,
@@ -151,7 +152,7 @@
151152
"open-sse/mcp-server/server.ts": 1555,
152153
"open-sse/mcp-server/tools/advancedTools.ts": 1118,
153154
"_rebaseline_2026_06_27_5193_antigravity_basered": "Base-red (pre-existing release drift, fast-gate PR->release skips check:file-size): accountFallback.ts 1773->1777 and src/app/api/providers/[id]/test/route.ts 924->940 were already over their frozen caps on release/v3.8.39 independent of any antigravity change. Owner chose to rebaseline (keep the documented issue-reference comments #1846/#1449/#347 etc.) rather than accept the contributor comment-stripping in #5200/#5198. Reverted #5200 to restore the comments; bumped these two frozen caps to the actual base sizes. No logic change.",
154-
"open-sse/services/accountFallback.ts": 1777,
155+
"open-sse/services/accountFallback.ts": 1783,
155156
"open-sse/services/batchProcessor.ts": 828,
156157
"open-sse/services/browserBackedChat.ts": 850,
157158
"open-sse/services/claudeCodeCompatible.ts": 1202,
@@ -229,7 +230,7 @@
229230
"src/lib/providers/validation.ts": 4523,
230231
"src/lib/resilience/settings.ts": 841,
231232
"src/lib/tailscaleTunnel.ts": 1202,
232-
"src/lib/usage/callLogs.ts": 985,
233+
"src/lib/usage/callLogs.ts": 997,
233234
"src/lib/usage/providerLimits.ts": 955,
234235
"src/lib/usage/usageHistory.ts": 988,
235236
"_rebaseline_2026_06_27_5193_5203_antigravity_oauthmodal": "Antigravity remote-login own growth: OAuthModal.tsx 960->969 (gate units). #5193 (+~4: remote paste instruction shown for all remote incl. Google + its rationale comment) and #5203 (+~5: handleManualSubmit credential-blob branch + button guard; submit logic extracted to oauthBlobSubmit.ts to minimize). Frozen set to the SUM so either merge order passes. Cohesive at the existing manual-submit chokepoint.",
@@ -243,20 +244,22 @@
243244
"src/shared/services/cliRuntime.ts": 1090,
244245
"src/shared/validation/schemas.ts": 2523,
245246
"_rebaseline_2026_06_28_5275_correlation_id_extract": "Extraction of the safe CorrelationId subset of #5275 (hartmark) — request correlation id stored in call_logs (migration 109) and returned via the X-Correlation-Id response header, WITHOUT the combo/resilience or build/lazy-loading changes (those stay in #5275). Own growth: callLogs.ts 975->985 (correlation_id column on CallLogSummaryRow + read/map), usageHistory.ts 983->988 (correlationId metadata normalize), chat.ts 1575->1632 (withCorrelationId response wiring + combo-failure log carrying correlationId), chatHelpers.ts new 811 (withCorrelationId helper + reqId threading; was 791<cap pre-feature). Cohesive request/logging chokepoint wiring; structural shrink of chat.ts tracked in #3501.",
246-
"src/sse/handlers/chat.ts": 1632,
247-
"src/sse/handlers/chatHelpers.ts": 811,
247+
"src/sse/handlers/chat.ts": 1635,
248+
"src/sse/handlers/chatHelpers.ts": 842,
248249
"src/sse/services/auth.ts": 2401,
249250
"open-sse/executors/default.ts": 876,
250251
"open-sse/translator/request/openai-responses.ts": 902,
251252
"open-sse/executors/kiro.ts": 944,
252-
"open-sse/translator/request/openai-to-claude.ts": 805
253+
"open-sse/translator/request/openai-to-claude.ts": 823,
254+
"tests/unit/account-fallback-service.test.ts": 1572,
255+
"tests/unit/provider-validation-specialty.test.ts": 2843
253256
},
254257
"testCap": 800,
255258
"testFrozen": {
256259
"tests/integration/chat-pipeline.test.ts": 1671,
257260
"tests/integration/chatcore-compression-integration.test.ts": 1111,
258261
"tests/integration/skills-pipeline.test.ts": 918,
259-
"tests/unit/account-fallback-service.test.ts": 1569,
262+
"tests/unit/account-fallback-service.test.ts": 1572,
260263
"tests/unit/arena-elo-sync.test.ts": 830,
261264
"tests/unit/batch_api.test.ts": 1303,
262265
"tests/unit/cc-compatible-provider.test.ts": 1179,
@@ -282,7 +285,7 @@
282285
"tests/unit/oauth-providers-config.test.ts": 873,
283286
"tests/unit/perplexity-web.test.ts": 959,
284287
"tests/unit/provider-models-route.test.ts": 1618,
285-
"tests/unit/provider-validation-specialty.test.ts": 2801,
288+
"tests/unit/provider-validation-specialty.test.ts": 2843,
286289
"_rebaseline_pr4613_compatible_provider_groups": "Reconcile #4613 already-merged growth: providers-page-utils.test.ts 1004->1052 (+48, buildCompatibleProviderGroups partition unit test). Fast-gate PR->release does not run check:file-size, so this surfaced post-merge.",
287290
"tests/unit/providers-page-utils.test.ts": 1052,
288291
"tests/unit/reasoning-cache.test.ts": 980,

0 commit comments

Comments
 (0)