diff --git a/CHANGELOG.md b/CHANGELOG.md index b8441e915f..49d6d99e0b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ _In development — bullets added per PR; finalized at release._ ### 🔧 Bug Fixes +- **fix(db): translate the two pt-BR SQLite driver-fallback log lines to English** — `[DB] Pré-inicializando sql.js WASM…` and `[DB] Drivers síncronos indisponíveis…` were the only non-English server log strings, mixing languages in the logs. Now `[DB] Pre-initializing sql.js WASM (synchronous drivers unavailable)…` / `[DB] Synchronous drivers unavailable — falling back to sql.js (WASM)`, guarded by a test that scans the driver path for accented log strings. ([#5103](https://github.com/diegosouzapw/OmniRoute/issues/5103)) - **fix(diagnostics): non-streaming Claude responses no longer false-502 as `empty_choices`** — the v3.8.37 malformed-200 detector (#4942) only understood OpenAI `choices` and Responses-API `output` shapes, so a `/v1/messages` response that stays in Claude shape (`{type:"message", content:[…]}`) fell through to `empty_choices` → 502 (cascading to "All models failed" in a combo). Most visibly, an extended-thinking turn whose buffered body is a single **empty thinking block with a valid `signature`** (Claude Code's non-streaming Bash classifier) 502'd on every call. `detectMalformedNonStream` now understands the Claude shape: text/tool_use blocks and thinking blocks carrying a signature count as valid output, while a genuinely empty `content:[]` is still flagged. ([#5108](https://github.com/diegosouzapw/OmniRoute/issues/5108), thanks @insoln) - **fix(combo): empty-content 502 now fails over within the same request instead of exhausting the provider** — a leg that answers HTTP 200 with no usable completion is rewritten to `502 "Provider returned empty content"`, but the combo exhaustion classifier treated that synthetic 502 as a connection-level failure (`#1731v2`) and marked the whole provider/connection exhausted, skipping every remaining **same-provider** leg in that request. The connection is actually healthy (it just returned an empty body), so empty-content 502s are now classified as model-level transient failures: the request advances to the next leg and the rest of that provider's legs stay eligible. Genuine gateway 502s still trip connection exhaustion. ([#5085](https://github.com/diegosouzapw/OmniRoute/issues/5085), thanks @andrea-kingautomation) - **fix(dashboard): surface the detailed credential-validation error instead of a bare "invalid" badge** — the inline "Check" in the Add-Connection modal discarded the `error` message returned by `/api/providers/validate` and showed only an `invalid` badge. For web providers (claude-web / chatgpt-web) the real cause is often an environment error the backend already reports (e.g. `TLS impersonation client failed to start: EACCES … mkdir tls-client-node/bin`), so users were left guessing. The modal now renders the full reason next to the badge. ([#5088](https://github.com/diegosouzapw/OmniRoute/issues/5088), thanks @tkhs101) diff --git a/src/lib/db/adapters/driverFactory.ts b/src/lib/db/adapters/driverFactory.ts index 2c474d041d..ae342244e2 100644 --- a/src/lib/db/adapters/driverFactory.ts +++ b/src/lib/db/adapters/driverFactory.ts @@ -221,7 +221,7 @@ export async function openDatabaseAsync( return sync; } - console.warn("[DB] Drivers síncronos indisponíveis — usando sql.js (WASM)"); + console.warn("[DB] Synchronous drivers unavailable — falling back to sql.js (WASM)"); const adapter = await preInitSqlJs(filePath); console.log(`[DB] Driver: sql.js | file: ${filePath}`); return adapter; diff --git a/src/lib/db/core.ts b/src/lib/db/core.ts index 261749a814..c277562262 100644 --- a/src/lib/db/core.ts +++ b/src/lib/db/core.ts @@ -1278,8 +1278,8 @@ export async function ensureDbInitialized(): Promise { return; } - // Nenhum driver síncrono — pré-inicializar sql.js (WASM, async) - console.warn("[DB] Pré-inicializando sql.js WASM (drivers síncronos indisponíveis)..."); + // No synchronous driver available — pre-initialize sql.js (WASM, async) + console.warn("[DB] Pre-initializing sql.js WASM (synchronous drivers unavailable)..."); await preInitSqlJs(SQLITE_FILE); // Agora getSqlJsAdapter() retornará o adapter, e getDbInstance() vai usá-lo getDbInstance(); diff --git a/tests/unit/db-driver-logs-english-5103.test.ts b/tests/unit/db-driver-logs-english-5103.test.ts new file mode 100644 index 0000000000..b9f2d4cf0f --- /dev/null +++ b/tests/unit/db-driver-logs-english-5103.test.ts @@ -0,0 +1,54 @@ +/** + * #5103 — Two startup log lines in the SQLite driver-fallback path were written in + * pt-BR ("Pré-inicializando sql.js…", "Drivers síncronos indisponíveis…"), mixing + * languages in the server logs. All user-facing server log strings must be English. + * + * Guard: scan the DB driver-fallback files for `console.*("…")` string literals that + * contain Latin accented characters (the tell-tale of a non-English log line). This + * fails on the pt-BR strings and stays green once they're translated, preventing + * regressions in this path. + */ +import test from "node:test"; +import assert from "node:assert/strict"; +import fs from "node:fs"; +import path from "node:path"; +import { fileURLToPath } from "node:url"; + +const here = path.dirname(fileURLToPath(import.meta.url)); +const repoRoot = path.resolve(here, "../.."); + +const DB_DRIVER_FILES = [ + "src/lib/db/core.ts", + "src/lib/db/adapters/driverFactory.ts", +]; + +// Latin-1 Supplement accented letters used by pt-BR/es/etc. (á à â ã é ê í ó ô õ ú ç …). +const ACCENTED = /[À-ÿ]/; +// Match the string argument(s) of a console.{warn,error,log,info} call (single line). +const CONSOLE_CALL = /console\.(?:warn|error|log|info)\s*\(([^\n]*)\)/g; + +test("#5103 DB driver-fallback log strings contain no non-English (accented) text", () => { + const offenders: string[] = []; + + for (const rel of DB_DRIVER_FILES) { + const abs = path.join(repoRoot, rel); + const src = fs.readFileSync(abs, "utf8"); + const lines = src.split("\n"); + + lines.forEach((line, i) => { + let m: RegExpExecArray | null; + CONSOLE_CALL.lastIndex = 0; + while ((m = CONSOLE_CALL.exec(line)) !== null) { + if (ACCENTED.test(m[1])) { + offenders.push(`${rel}:${i + 1} ${line.trim()}`); + } + } + }); + } + + assert.deepEqual( + offenders, + [], + `Non-English (accented) console log strings found in the DB driver path:\n${offenders.join("\n")}` + ); +});