From 97aac6ac6c3538821573ee97992f5e8fee1b2285 Mon Sep 17 00:00:00 2001 From: Diego Rodrigues de Sa e Souza Date: Thu, 13 Aug 2026 23:02:48 -0300 Subject: [PATCH 01/11] fix(ci): clear base-reds on release/v3.8.50 (round 4) (#10260) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(ci): clear base-reds on release/v3.8.50 (round 4) Drains the HARD failures reported by Release-Green run 31693210948 on issue #9985 (ESLint errors: 2) plus the merge-integrity red every open PR is inheriting. - ESLint error 1: @omniroute/opencode-plugin/src/index.ts had a stray extra '});' (introduced by #9316) that broke parsing with 'unexpected file in NFT list' on the build path. - ESLint error 2: cli-env-inline-comment-10100.test.ts used new Function to extract parseEnvValue from the bin entrypoint (no-new-func, Hard Rule #3). Extracted the helper to bin/cli/utils/parseEnvValue.mjs and import it from both the entrypoint and the test (same behavior, no eval). - open-sse-typecheck (Fast Quality Gates): open-sse/utils/stream.ts imported sseCommentsEnabled twice (#9378) causing TS2300 Duplicate identifier; removed the duplicate import. - Merge integrity (changelog + generated skills): skills/omni-settings/SKILL.md was edited manually by #10169 without updating the generator source, so check:agent-skills-sync failed on every PR (Generated: 1). Moved the curated thinking-budget content into a block (the documented preservation mechanism), which the generator now keeps in sync. Refs #9985 * fix(tests): align wave1-a poolside test with #10216 probed catalog #10216 published Poolside's two authenticated-probe models (poolside/laguna-xs-2.1, poolside/laguna-s-2.1) as static seeds, but the wave1-a free-tier test still asserted 'no invented static model ids' (entry.models === []), failing every open PR. Separate poolside from the empty-models assertion and pin its probed catalog explicitly so a future catalog change is a deliberate update, not a silent drift. * fix(pack): register parseEnvValue.mjs in PACK_ARTIFACT_REQUIRED_PATHS The extract of parseEnvValue to bin/cli/utils/parseEnvValue.mjs added a new direct import to bin/omniroute.mjs, which pack-artifact-entrypoint-closures enforces against PACK_ARTIFACT_REQUIRED_PATHS. Register the module so a future tarball omission fails loudly. * fix(combo): restore default same-model retry semantics after #10217 #10217 wired config.failoverBeforeRetry into the same-model retry guard in both the priority/auto and round-robin loops, but DEFAULT_COMBO_CONFIG defaulted the flag to true — flipping same-model retry off for every combo that never touched the setting, not just the opt-in case. Round-4 bisect (06f41cda63 vs d2fd88dfbc) reproduced this against tests/unit/combo-499-abort.test.ts, tests/unit/combo-quota-exhaustion-only-fallback.test.ts and tests/unit/combo-stream-readiness-fallback.test.ts. Flip the default to false so the historical retry-before-failover behavior returns for combos that never set the flag, while explicit opt-in (the two new tests #10217 added to combo-routing-engine.test.ts) still works. * fix(quality): register visionBridge-responses-9597 in stryker tap.testFiles check-mutation-test-coverage.mjs flagged tests/unit/guardrails/visionBridge-responses-9597.test.ts as covering open-sse/services/combo/comboStructure.ts without being listed in stryker.conf.json's tap.testFiles array. Add it so mutation coverage attribution stays accurate. * test(pack): expect parseEnvValue.mjs in the missing-artifact-paths fixture The prior commit on this branch registered bin/cli/utils/parseEnvValue.mjs in PACK_ARTIFACT_REQUIRED_PATHS but the "findMissingArtifactPaths flags missing root runtime files in the tarball" test still hardcoded the old expected list, so it never accounted for the new required path being absent from the simulated tarball. Add it in its alphabetical slot. * chore(lint): prune stale no-explicit-any suppression for call-log-file-rotation --prune-suppressions found tests/unit/call-log-file-rotation.test.ts no longer produces the 5 suppressed @typescript-eslint/no-explicit-any warnings recorded in config/quality/eslint-suppressions.json. Remove the dead entry so a regression would be caught again. Full-tree run with --max-warnings 0 is clean: 0 errors, 0 warnings. * fix(combo): decouple failoverBeforeRetry same-model guard from the skipUpstreamRetry default Audit found that DEFAULT_COMBO_CONFIG.failoverBeforeRetry has defaulted to true since before #10217 (predates #2417), and that value also feeds the independent skipUpstreamRetry mechanism (src/sse/handlers/chat.ts:859,1126). The previous commit on this branch flipped that default to false to fix the #10217 same-model retry guard, which silently disabled skipUpstreamRetry's own default-on behavior for every combo without an opt-in — a regression in the opposite direction (executor-level retries before the loop's own failover, changing latency/failure behavior). Revert the default back to true and decouple the two mechanisms instead: resolveComboConfig/resolveComboSetupConfig now also compute failoverBeforeRetryExplicit, true only when a cascade layer (combo/provider/ global) literally sets failoverBeforeRetry to true — not merely inherited from the default. The #10217 same-model retry guards in combo.ts (priority/ auto and round-robin loops) now read failoverBeforeRetryExplicit instead of config.failoverBeforeRetry, restoring opt-in-only behavior for that guard while the skipUpstreamRetry pass-through (config.failoverBeforeRetry at combo.ts:1297,2865) is untouched and keeps its historical default-on. * fix(combo,i18n): align getDefaultComboConfig with 10217 explicit flag; pt denoRelay entities Two round-4 follow-ups exposed by the combinated base-red PR run: 1. comboConfig.ts: #10217 round-4 fix (104afeda4e) added failoverBeforeRetryExplicit to resolveComboConfig/resolveComboSetupConfig but getDefaultComboConfig() returned only DEFAULT_COMBO_CONFIG, so the combo-config.test.ts deepEqual (resolveComboConfig(null) === getDefaultComboConfig()) failed on the extra field. Mirror the opt-in flag as false in the default. 2. pt.json: denoRelayOrgDomainHint still carried raw / (the UNCLOSED_TAG RSC regression) — encode as <...> like the other 42 locales, greening i18n-deno-relay-unclosed-tag.test.ts. * chore(lint): disable @next/next/no-location-assign-relative-destination pending per-case review (#10292) The eslint-config-next bump in #10043 shipped this new rule, flagging 6 pre-existing window.location.href navigations — several are deliberate full-page reloads (login/logout state reset). Off with tracking issue rather than a blanket router.push rewrite. * fix(i18n): fill 439 missing UI keys (thinkingMode ×39 locales + pt catch-up) to restore 100% coverage The #10169 Thinking Budget keys existed only in en/pt-BR/vi and the pt (PT-PT) catalog from #10250 lagged 88 recent keys, dropping i18nUiCoverage to 99.3% vs the frozen 100% ratchet baseline. Translated via the i18n:sync-ui marker pipeline; glossary + ICU placeholder post-pass clean. * fix(i18n): zh-TW glossary — replace retired 默認 with canonical 預設 in new thinkingMode keys * chore(quality): rebase dead-code baseline 248 -> 409 for knip 6.32 bump (#10043) dependabot #10043 upgraded knip 6.27 -> 6.32, which detects 162 MORE genuinely-unused exports (331 vs 169) that 6.27 missed; DEAD_FILES unchanged (78). Reproduced identically on the clean release/v3.8.50 tip 266e39d3 with a fresh 6.32 node_modules, so every PR is born red until the tool change is absorbed. Owner authorized rebaseline (2026-08-13 via PR #10260). Structural cleanup of the newly-surfaced dead exports remains separate debt. --------- Co-authored-by: adevwithpurpose Co-authored-by: backryun --- @omniroute/opencode-plugin/src/index.ts | 1 - bin/cli/utils/parseEnvValue.mjs | 21 ++ bin/omniroute.mjs | 23 +- config/quality/eslint-suppressions.json | 5 - config/quality/quality-baseline.json | 5 +- eslint.config.mjs | 4 + open-sse/services/combo.ts | 23 +- open-sse/services/comboConfig.ts | 60 +++- open-sse/utils/stream.ts | 1 - scripts/build/pack-artifact-policy.ts | 1 + skills/omni-settings/SKILL.md | 45 ++- src/i18n/messages/ar.json | 20 +- src/i18n/messages/az.json | 20 +- src/i18n/messages/bg.json | 20 +- src/i18n/messages/bn.json | 20 +- src/i18n/messages/cs.json | 20 +- src/i18n/messages/da.json | 20 +- src/i18n/messages/de.json | 20 +- src/i18n/messages/es.json | 20 +- src/i18n/messages/fa.json | 20 +- src/i18n/messages/fi.json | 20 +- src/i18n/messages/fr.json | 20 +- src/i18n/messages/gu.json | 20 +- src/i18n/messages/he.json | 20 +- src/i18n/messages/hi.json | 20 +- src/i18n/messages/hu.json | 20 +- src/i18n/messages/id.json | 20 +- src/i18n/messages/in.json | 20 +- src/i18n/messages/it.json | 20 +- src/i18n/messages/ja.json | 20 +- src/i18n/messages/ko.json | 20 +- src/i18n/messages/mr.json | 20 +- src/i18n/messages/ms.json | 20 +- src/i18n/messages/nl.json | 20 +- src/i18n/messages/no.json | 20 +- src/i18n/messages/phi.json | 20 +- src/i18n/messages/pl.json | 20 +- src/i18n/messages/pt-BR.json | 20 +- src/i18n/messages/pt.json | 262 ++++++------------ src/i18n/messages/ro.json | 20 +- src/i18n/messages/ru.json | 20 +- src/i18n/messages/sk.json | 20 +- src/i18n/messages/sv.json | 20 +- src/i18n/messages/sw.json | 20 +- src/i18n/messages/ta.json | 20 +- src/i18n/messages/te.json | 20 +- src/i18n/messages/th.json | 20 +- src/i18n/messages/tr.json | 20 +- src/i18n/messages/uk-UA.json | 20 +- src/i18n/messages/ur.json | 20 +- src/i18n/messages/vi.json | 20 +- src/i18n/messages/zh-CN.json | 20 +- src/i18n/messages/zh-TW.json | 20 +- stryker.conf.json | 1 + .../unit/cli-env-inline-comment-10100.test.ts | 31 +-- .../unit/free-tier-providers-wave1-a.test.ts | 14 + tests/unit/pack-artifact-policy.test.ts | 1 + 57 files changed, 652 insertions(+), 666 deletions(-) create mode 100644 bin/cli/utils/parseEnvValue.mjs diff --git a/@omniroute/opencode-plugin/src/index.ts b/@omniroute/opencode-plugin/src/index.ts index 09e3825676..bc18518cad 100644 --- a/@omniroute/opencode-plugin/src/index.ts +++ b/@omniroute/opencode-plugin/src/index.ts @@ -5478,7 +5478,6 @@ export function createOmniRouteConfigHook( rawConnections: localRawConnections, expiresAt: now() + resolved.modelCacheTtl, }); - }); // Startup diagnostics (file-based) — fires at startup via config hook if (resolved.features?.startupDebug === true) { diff --git a/bin/cli/utils/parseEnvValue.mjs b/bin/cli/utils/parseEnvValue.mjs new file mode 100644 index 0000000000..3388bda419 --- /dev/null +++ b/bin/cli/utils/parseEnvValue.mjs @@ -0,0 +1,21 @@ +/** + * Parse a `.env` value with dotenv-compatible comment handling. + * + * Without this, `KEY=value # note` stored the comment text as part of the + * value. The shipped .env ships exactly such a line for QUOTA_STORE_DRIVER, and + * consumers compare it with `===`, so annotating a variable inline silently + * disabled it (#10100). + * + * Quoted values are returned verbatim — a `#` inside quotes is data. For + * unquoted values a `#` *preceded by whitespace* starts a comment, so + * `pass#word` is preserved. + */ +export function parseEnvValue(raw) { + const value = String(raw).trim(); + + const quoted = value.match(/^(['"])([\s\S]*)\1\s*(?:#.*)?$/); + if (quoted) return quoted[2]; + + const commentIdx = value.search(/\s#/); + return (commentIdx === -1 ? value : value.slice(0, commentIdx)).trim(); +} diff --git a/bin/omniroute.mjs b/bin/omniroute.mjs index bfec91fead..c023879da8 100755 --- a/bin/omniroute.mjs +++ b/bin/omniroute.mjs @@ -23,6 +23,7 @@ import { getNodeRuntimeSupport, getNodeRuntimeWarning } from "./nodeRuntimeSuppo import { getDefaultDataDir } from "./cli/data-dir.mjs"; import { shouldProvisionStorageKey } from "./cli/utils/storageKeyProvision.mjs"; import { isVersionFastPath } from "./cli/utils/versionFastPath.mjs"; +import { parseEnvValue } from "./cli/utils/parseEnvValue.mjs"; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); @@ -93,28 +94,6 @@ function migrateElectronServerEnv(dataDir) { } } -/** - * Parse a `.env` value with dotenv-compatible comment handling. - * - * Without this, `KEY=value # note` stored the comment text as part of the - * value. The shipped .env ships exactly such a line for QUOTA_STORE_DRIVER, and - * consumers compare it with `===`, so annotating a variable inline silently - * disabled it (#10100). - * - * Quoted values are returned verbatim — a `#` inside quotes is data. For - * unquoted values a `#` *preceded by whitespace* starts a comment, so - * `pass#word` is preserved. - */ -function parseEnvValue(raw) { - const value = String(raw).trim(); - - const quoted = value.match(/^(['"])([\s\S]*)\1\s*(?:#.*)?$/); - if (quoted) return quoted[2]; - - const commentIdx = value.search(/\s#/); - return (commentIdx === -1 ? value : value.slice(0, commentIdx)).trim(); -} - function loadEnvFile() { const envPaths = []; const loadedEnvPaths = []; diff --git a/config/quality/eslint-suppressions.json b/config/quality/eslint-suppressions.json index 9432c5c002..6e8eaf1238 100644 --- a/config/quality/eslint-suppressions.json +++ b/config/quality/eslint-suppressions.json @@ -1701,11 +1701,6 @@ "count": 43 } }, - "tests/unit/call-log-file-rotation.test.ts": { - "@typescript-eslint/no-explicit-any": { - "count": 5 - } - }, "tests/unit/call-log-startup.test.ts": { "@typescript-eslint/no-explicit-any": { "count": 1 diff --git a/config/quality/quality-baseline.json b/config/quality/quality-baseline.json index a66523435f..7c7f2bb67b 100644 --- a/config/quality/quality-baseline.json +++ b/config/quality/quality-baseline.json @@ -102,7 +102,7 @@ "_rebaseline_2026_07_28_v3849_release": "75.5 -> 99 (+23.5). Aperto EXIGIDO pelo modo --require-tighten do ratchet: a métrica melhorou de verdade no ciclo v3.8.49. A causa é o workflow assíncrono de tradução, que finalmente alcançou o denominador em EN — as rebaselines anteriores (v3.8.39/.44/.47) foram todas afrouxamentos registrando o atraso das traduções, e agora ele foi pago. O coletor SUBTRAI os placeholders (present - placeholder em scripts/quality/collect-metrics.mjs), então os 317 marcadores __MISSING__ que esta release introduziu para o drift de valor já estão descontados dos 99 — o número é honesto, não inflado por placeholder. Medido pelo collect-metrics do CI no run 30404226939." }, "deadExports": { - "value": 248, + "value": 409, "direction": "down", "_rebaseline_2026_08_09_v3850_post_sweep": "227 -> 230. Measured by npm run check:dead-code on the unmodified release/v3.8.50 tip 382449d593 during the mandatory --full-ci pre-flight. The +3 is inherited cycle drift from the authorized merge sweep; this repair adds no production exports. Rebaseline records the actual tip so ci.yml quality-gate can run, while structural cleanup remains separate debt.", "_rebaseline_2026_07_01_v3843_release": "225->227 (+2). v3.8.43 cycle drift, surfaced in the Quality Ratchet job after eslintWarnings was rebaselined (check:dead-code runs there). 227 = measured by check:dead-code (knip) on the release tip 4635076eb. The 5 CI fixes add 0 dead exports: safeHttpHref in linkify.ts is module-local AND used (called by linkifyText); no new exports; test files are not scanned. Tighten via --update next cycle.", @@ -110,7 +110,8 @@ "_rebaseline_2026_06_30_v3842_deadcode_wave": "310 -> 225. Measured by `node scripts/check/check-dead-code.mjs` on the v3.8.42 tip after the JxnLexn dead-code (#5463/#5464/#5466) + duplication (#5471..#5500) wave landed: DEAD_EXPORTS=133 + DEAD_FILES=92 = 225. The stale 310 was the v3.8.38 release snapshot never ratcheted on PR->release fast-gates (check:dead-code runs only on ci.yml PR->main, not quality.yml). Tightening to the true measured value; release-time captain rebaselines up if parallel cycle merges add dead exports.", "_rebaseline_2026_06_27_v3838_release": "345->346 (+1). v3.8.38 cycle drift surfaced by the release-green pre-flight (Quality Ratchet does NOT run on PR->release fast-gates). Net +1 inherited from this cycle's feature/fix merges (new executors/providers, compression fidelity-gate module) minus #5138's removal of dead legacy store modules. Release-finalize working tree touches ONLY CHANGELOG.md + i18n mirrors + README + baselines — 0 production-code change. Structural cleanup tracked as debt.", "_rebaseline_2026_06_26_v3837_release": "343->345. v3.8.37 cycle drift surfaced by the release-green pre-flight (the Quality Ratchet does NOT run on PR->release fast-gates, so warnings/complexity accrued unmeasured across this cycle's 76 commits — provider adds DGrid/Pioneer/xAI, headroom proxy lifecycle #4649, ~50 SSE/translator fixes, Engine Combos #5062). Trust-but-verify: this release-finalize working tree touches ONLY CHANGELOG.md, docs/i18n/*/CHANGELOG.md mirrors, and these baselines — 0 production-code change, so all drift is inherited cycle drift (`any` warn-allowed in open-sse/ + tests/). Tighten via --require-tighten next cycle.", - "_rebaseline_2026_08_11_v3850_merge_storm": "230 -> 248. Own drift from the 2026-08-11 merge storm (99 PRs into release/v3.8.50 via authorized sweep): new providers/executors/handlers added dead exports that knip cannot see as used. Measured on the base-fix tip (7ca73697b0 + this repair PR). Owner authorized rebaseline (2026-08-11) — structural cleanup remains separate debt." + "_rebaseline_2026_08_11_v3850_merge_storm": "230 -> 248. Own drift from the 2026-08-11 merge storm (99 PRs into release/v3.8.50 via authorized sweep): new providers/executors/handlers added dead exports that knip cannot see as used. Measured on the base-fix tip (7ca73697b0 + this repair PR). Owner authorized rebaseline (2026-08-11) — structural cleanup remains separate debt.", + "_rebaseline_2026_08_13_v3850_knip_bump": "248 -> 409. NOT code-added dead exports: dependabot bump #10043 (2026-08-13) upgraded knip 6.27.0 -> 6.32.x, and the new knip detects 162 MORE genuinely-unused exports (331 vs 169 deadExports) that 6.27 missed. DEAD_FILES unchanged (78). Reproduced identically on the clean release/v3.8.50 tip 266e39d3 with a fresh knip 6.32 node_modules — so every PR is born red on this gate until the tool change is absorbed. Owner authorized rebaseline (2026-08-13, via base-reds PR #10260). Structural cleanup of the 162 newly-surfaced dead exports remains separate debt." }, "cognitiveComplexity": { "value": 1223, diff --git a/eslint.config.mjs b/eslint.config.mjs index 1a447da98d..4d54c7e91a 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -62,6 +62,10 @@ const eslintConfig = [ "no-implied-eval": "error", "no-new-func": "error", "no-restricted-imports": ["error", IMPORT_BOUNDARY_RESTRICTIONS], + // New rule shipped by the eslint-config-next bump (#10043); flags 6 pre-existing + // window.location.href navigations, several of which are deliberate full-page + // reloads (login/logout state reset). Off pending per-case review — issue #10292. + "@next/next/no-location-assign-relative-destination": "off", }, }, // G14: DB internals may use the compatibility barrel while it is decomposed; all diff --git a/open-sse/services/combo.ts b/open-sse/services/combo.ts index 58371dc93e..df86a79375 100644 --- a/open-sse/services/combo.ts +++ b/open-sse/services/combo.ts @@ -1919,11 +1919,18 @@ export async function handleComboChat({ // skip the same-model retry when `nextTarget` (computed above) // actually gives us somewhere to fail over to — with no sibling // left, skipping just burns the last attempt for nothing. + // + // #10217 round-4 fix: this guard reads `failoverBeforeRetryExplicit` + // (opt-in only), NOT `config.failoverBeforeRetry` — that field + // defaults to true for the separate skipUpstreamRetry mechanism + // (see DEFAULT_COMBO_CONFIG comment in comboConfig.ts) and reading + // it here would silently skip the same-model retry for every combo, + // not just ones that explicitly opted in. if ( retry < maxRetries && isTransient && !providerExhausted && - (!config.failoverBeforeRetry || !nextTarget) + (!config.failoverBeforeRetryExplicit || !nextTarget) ) { if ( !protectedPriorityTarget && @@ -2438,7 +2445,15 @@ async function handleRoundRobinCombo({ }: HandleRoundRobinOptions): Promise { const config = settings ? resolveComboConfig(combo, settings) - : { ...getDefaultComboConfig(), ...(combo.config || {}) }; + : { + ...getDefaultComboConfig(), + ...(combo.config || {}), + // See resolveComboConfig's failoverBeforeRetryExplicit comment in + // comboConfig.ts (no `settings` here, so only the combo's own config + // can opt in). + failoverBeforeRetryExplicit: + (combo.config as Record | undefined)?.failoverBeforeRetry === true, + }; // #9158: clamp combo-level concurrency to a sane bound — a config carrying a // huge or negative value would otherwise open an unbounded semaphore and // flood targets (or deadlock at 0). @@ -3163,12 +3178,14 @@ async function handleRoundRobinCombo({ // just the lower-level skipUpstreamRetry mechanism. Only skip when // `offset + 1 < modelCount` means a sibling target is actually left // in this rotation; with none left, skipping just wastes the attempt. + // #10217 round-4 fix: opt-in only — read failoverBeforeRetryExplicit, + // not config.failoverBeforeRetry (see comboConfig.ts comment). const hasNextRrTarget = offset + 1 < modelCount; if ( retry < maxRetries && isTransient && !providerExhausted && - (!config.failoverBeforeRetry || !hasNextRrTarget) + (!config.failoverBeforeRetryExplicit || !hasNextRrTarget) ) { continue; } diff --git a/open-sse/services/comboConfig.ts b/open-sse/services/comboConfig.ts index 4489b6194a..a08a1312ec 100644 --- a/open-sse/services/comboConfig.ts +++ b/open-sse/services/comboConfig.ts @@ -126,6 +126,22 @@ const DEFAULT_COMBO_CONFIG = { resetAwareWeeklyWeight: 0.65, resetAwareTieBandPercent: 5, resetAwareExhaustionGuardPercent: 10, + // Historical default (predates #2417/#10217) — true. This value feeds TWO + // independent mechanisms and must stay true-by-default for one of them: + // 1. skipUpstreamRetry (src/sse/handlers/chat.ts:859,1126) — the + // lower-level executor retry skip. Always default-on; changing this + // default flips that mechanism's behavior for every combo, not just + // opted-in ones. + // 2. The #10217 same-model retry guard in this file's combo.ts callers + // (priority/auto + round-robin loops) — meant to be OPT-IN only. That + // guard must NOT read this field directly; it consults the sibling + // `failoverBeforeRetryExplicit` flag computed below in + // resolveComboConfig/resolveComboSetupConfig, which is true only when + // an actual cascade layer (combo/provider/global) set the flag to + // true, not merely inherited from this default. See round-4 base-red + // bisect (06f41cda63 vs d2fd88dfbc) — flipping THIS default to false + // "fixed" mechanism 2 but silently broke mechanism 1's default-on + // behavior for every combo without an explicit opt-in. failoverBeforeRetry: true, // Feature 4985: configurable response-body validation predicate (per-combo). When set, // a 200 OK whose body fails the predicate fails over to the next target. @@ -284,15 +300,32 @@ export function resolveComboConfig( ) ); + const cleanGlobal = clean(global); + const cleanProviderOverride = clean(providerOverride); + const cleanComboConfig = clean(comboConfig); + const merged = { ...DEFAULT_COMBO_CONFIG, - ...clean(global), - ...clean(providerOverride), - ...clean(comboConfig), + ...cleanGlobal, + ...cleanProviderOverride, + ...cleanComboConfig, }; + // #10217 round-4 fix: `failoverBeforeRetry` defaults to true (see comment on + // DEFAULT_COMBO_CONFIG above) and feeds two independent mechanisms. Callers + // that gate the OPT-IN same-model retry guard (combo.ts) must NOT read + // `merged.failoverBeforeRetry` directly — that stays true unless a layer + // explicitly disables it, which can't distinguish "inherited default" from + // "operator opted in". This flag is true only when some cascade layer + // literally set the value to true, i.e. a genuine opt-in. + const failoverBeforeRetryExplicit = + cleanComboConfig.failoverBeforeRetry === true || + cleanProviderOverride.failoverBeforeRetry === true || + cleanGlobal.failoverBeforeRetry === true; + return { ...merged, + failoverBeforeRetryExplicit, shadowRouting: { ...DEFAULT_COMBO_CONFIG.shadowRouting, ...(isRecord(global.shadowRouting) ? clean(global.shadowRouting) : {}), @@ -312,7 +345,13 @@ export function resolveComboConfig( * Get the default combo config (used when no overrides exist) */ export function getDefaultComboConfig() { - return { ...DEFAULT_COMBO_CONFIG }; + return { + ...DEFAULT_COMBO_CONFIG, + // Mirror resolveComboConfig's opt-in flag so a deepEqual against the + // default stays consistent (#10217 round-4 fix). With no cascade layer + // setting the flag, it is a genuine non-opt-in → false. + failoverBeforeRetryExplicit: false, + }; } /** @@ -322,7 +361,14 @@ export function getDefaultComboConfig() { * return type is the single source of truth for ComboContext.config (combo/context.ts). */ export function resolveComboSetupConfig(combo: ComboConfigLike, settings: ComboSettingsLike) { - return settings - ? resolveComboConfig(combo, settings) - : { ...getDefaultComboConfig(), ...((combo?.config as Record) || {}) }; + if (settings) return resolveComboConfig(combo, settings); + const comboConfig = (combo?.config as Record) || {}; + return { + ...getDefaultComboConfig(), + ...comboConfig, + // See resolveComboConfig's failoverBeforeRetryExplicit comment — same + // distinction applies here (no `settings`, so only the combo's own config + // can opt in). + failoverBeforeRetryExplicit: comboConfig.failoverBeforeRetry === true, + }; } diff --git a/open-sse/utils/stream.ts b/open-sse/utils/stream.ts index 24999c2eee..0eeccec17d 100644 --- a/open-sse/utils/stream.ts +++ b/open-sse/utils/stream.ts @@ -74,7 +74,6 @@ import { hasUnsupportedReasoningSignal, } from "./reasoningFields.ts"; import { applyThinkTag, flushThink, initThinkState } from "./thinkTagParser.ts"; -import { sseCommentsEnabled } from "./sseHeartbeat.ts"; import { caseInsensitiveToolNameLookup, restoreOpenAIToolNames, diff --git a/scripts/build/pack-artifact-policy.ts b/scripts/build/pack-artifact-policy.ts index 5ccbe52a3e..012026da3a 100644 --- a/scripts/build/pack-artifact-policy.ts +++ b/scripts/build/pack-artifact-policy.ts @@ -192,6 +192,7 @@ export const PACK_ARTIFACT_REQUIRED_PATHS: string[] = [ // tests/unit/pack-artifact-entrypoint-closures.test.ts). "bin/cli/data-dir.mjs", "bin/cli/utils/ensureAndroidCacheDir.mjs", + "bin/cli/utils/parseEnvValue.mjs", "bin/cli/utils/storageKeyProvision.mjs", "bin/cli/utils/versionFastPath.mjs", "bin/mcp-server.mjs", diff --git a/skills/omni-settings/SKILL.md b/skills/omni-settings/SKILL.md index 79d930097b..9ab8f95dfb 100644 --- a/skills/omni-settings/SKILL.md +++ b/skills/omni-settings/SKILL.md @@ -319,15 +319,7 @@ curl -X PUT https://localhost:20128/api/settings/system-prompt \ Get thinking budget configuration -Returns proxy-level thinking/reasoning **request rewrite** settings: - -| Field | Meaning | -|-------|---------| -| `mode` | `passthrough` (leave client reasoning alone — **required for Codex visible thinking**), `auto` (**strips** all client thinking fields), `custom`, `adaptive` | -| `customBudget` | Fixed budget when `mode=custom` | -| `effortLevel` | Base effort when `mode=adaptive` | - -**Not** compression and **not** “decrypt encrypted reasoning”. Full guide: `docs/guides/THINKING_BUDGET.md`. +Returns the current thinking/reasoning budget settings for AI models. ```bash curl https://localhost:20128/api/settings/thinking-budget \ @@ -338,17 +330,13 @@ curl https://localhost:20128/api/settings/thinking-budget \ Update thinking budget configuration -Example — keep client-controlled reasoning (Codex/Desktop): - ```bash curl -X PUT https://localhost:20128/api/settings/thinking-budget \ - -H "Authorization: Bearer $OMNIROUTE_TOKEN" \ + -H "Authorization: Bearer $OMNIROUTE_TOKEN" -H "Content-Type: application/json" \ - -d '{"mode":"passthrough","customBudget":10240,"effortLevel":"medium"}' + -d '{}' ``` -Warning: `mode=auto` deletes `reasoning` / `reasoning_effort` / Claude `thinking` from the outbound body before upstream. That can empty thinking panels even when the client requested Ultra + summary. - ### GET /api/tags List Ollama-compatible model tags @@ -398,3 +386,30 @@ curl -X POST https://localhost:20128/api/settings/purge-usage-history \ ## Payloads See the full OpenAPI specification at `GET /api/openapi/spec` or `docs/openapi.yaml` for detailed request/response schemas. + + + + +### GET /api/settings/thinking-budget — behavior + +Returns proxy-level thinking/reasoning **request rewrite** settings: + +| Field | Meaning | +|-------|---------| +| `mode` | `passthrough` (leave client reasoning alone — **required for Codex visible thinking**), `auto` (**strips** all client thinking fields), `custom`, `adaptive` | +| `customBudget` | Fixed budget when `mode=custom` | +| `effortLevel` | Base effort when `mode=adaptive` | + +**Not** compression and **not** "decrypt encrypted reasoning". Full guide: `docs/guides/THINKING_BUDGET.md`. + +Example — keep client-controlled reasoning (Codex/Desktop): + +```bash +curl -X PUT https://localhost:20128/api/settings/thinking-budget \ + -H "Authorization: Bearer $OMNIROUTE_TOKEN" \ + -H "Content-Type: application/json" \ + -d '{"mode":"passthrough","customBudget":10240,"effortLevel":"medium"}' +``` + +Warning: `mode=auto` deletes `reasoning` / `reasoning_effort` / Claude `thinking` from the outbound body before upstream. That can empty thinking panels even when the client requested Ultra + summary. + diff --git a/src/i18n/messages/ar.json b/src/i18n/messages/ar.json index f9387c23e0..9e98994974 100644 --- a/src/i18n/messages/ar.json +++ b/src/i18n/messages/ar.json @@ -6821,8 +6821,17 @@ "chars": "{count} حرف", "thinkingBudgetTitle": "ميزانية التفكير", "thinkingBudgetDesc": "التحكم في استخدام الرمز المميز لاستدلال الذكاء الاصطناعي عبر جميع الطلبات", + "thinkingBudgetIndependenceHint": "تستمر ميزات الضغط والتوجيه وحدود الرموز في العمل في كل وضع. الوضع التلقائي لا يعني \"إظهار التفكير تلقائيًا\" - بل يقوم بإزالة حقول تفكير العميل.", "passthrough": "العبور", "passthroughDesc": "لا توجد تغييرات - يتحكم العميل في ميزانية التفكير", + "thinkingModePassthrough": "تمرير", + "thinkingModePassthroughDesc": "اترك سبب العميل دون تغيير (الجهد، الملخص، كتل التفكير). مطلوب لرؤية التفكير في Codex/Desktop. افتراضي.", + "thinkingModeAuto": "تلقائي (شريط)", + "thinkingModeAutoDesc": "قم بإزالة جميع حقول تفكير/تفكير العميل (reasoning, reasoning_effort, Claude thinking, Gemini thinking_config) ودع المزود يخترع القيم الافتراضية. يمكن إخفاء لوحات التفكير وكسر طلبات ملخص العميل.", + "thinkingModeCustom": "مخصص", + "thinkingModeCustomDesc": "استبدل كل طلب بميزانية ثابتة من رموز التفكير التي تحددها أدناه.", + "thinkingModeAdaptive": "تكييفي", + "thinkingModeAdaptiveDesc": "قم بتوسيع ميزانية التفكير من جهد أساسي باستخدام عدد الرسائل، والأدوات، وطول المطالبة.", "auto": "تلقائي", "autoDesc": "قم بتجريد كل تكوينات التفكير - دع مقدم الخدمة يقرر", "custom": "مخصص", @@ -8146,16 +8155,7 @@ "cliproxyapiHealth": "الصحة", "cliproxyapiPort": "منفذ", "qdrantHost": "مضيف", - "qdrantCollection": "مجموعة", - "thinkingBudgetIndependenceHint": "__MISSING__:Compression, routing, and token-limit features keep working in every mode. Auto does not mean “auto-show thinking” — it strips client reasoning fields.", - "thinkingModePassthrough": "__MISSING__:Passthrough", - "thinkingModePassthroughDesc": "__MISSING__:Leave client reasoning unchanged (effort, summary, thinking blocks). Required for Codex/Desktop visible thinking. Default.", - "thinkingModeAuto": "__MISSING__:Auto (strip)", - "thinkingModeAutoDesc": "__MISSING__:Strip all client thinking/reasoning fields (reasoning, reasoning_effort, Claude thinking, Gemini thinking_config) and let the provider invent defaults. Can hide thinking panels and break client summary requests.", - "thinkingModeCustom": "__MISSING__:Custom", - "thinkingModeCustomDesc": "__MISSING__:Overwrite every request with a fixed thinking token budget you set below.", - "thinkingModeAdaptive": "__MISSING__:Adaptive", - "thinkingModeAdaptiveDesc": "__MISSING__:Scale thinking budget from a base effort using message count, tools, and prompt length." + "qdrantCollection": "مجموعة" }, "contextRtk": { "title": "محرك آر تي كيه", diff --git a/src/i18n/messages/az.json b/src/i18n/messages/az.json index 8aebaa92c1..47a03d8d7c 100644 --- a/src/i18n/messages/az.json +++ b/src/i18n/messages/az.json @@ -6821,8 +6821,17 @@ "chars": "{count} chars", "thinkingBudgetTitle": "Thinking Budget", "thinkingBudgetDesc": "Control AI reasoning token usage across all requests", + "thinkingBudgetIndependenceHint": "Sıxma, yönləndirmə və token-limit xüsusiyyətləri hər bir rejimdə işləməyə davam edir. Auto \"avtomatik düşüncə göstərmək\" demək deyil - bu, müştəri düşüncə sahələrini çıxarır.", "passthrough": "Passthrough", "passthroughDesc": "No changes — client controls thinking budget", + "thinkingModePassthrough": "Keçid", + "thinkingModePassthroughDesc": "Müştəri səbəblərini dəyişməz saxlayın (səy, xülasə, düşüncə blokları). Codex/Desktop görünən düşüncə üçün tələb olunur. Varsayılan.", + "thinkingModeAuto": "Avtomatik (zolaq)", + "thinkingModeAutoDesc": "Bütün müştəri düşüncə/əsaslandırma sahələrini (əsaslandırma, əsaslandırma_səy, Claude düşüncəsi, Gemini düşüncə_quraşdırması) silin və təminatçının standartları icad etməsinə icazə verin. Düşüncə panellərini gizlətmək və müştəri xülasə tələblərini pozmaq mümkündür.", + "thinkingModeCustom": "Xüsusi", + "thinkingModeCustomDesc": "Aşağıda təyin etdiyiniz sabit düşüncə token büdcəsi ilə hər bir sorğunu üst-üstə yazın.", + "thinkingModeAdaptive": "Uyğunlaşan", + "thinkingModeAdaptiveDesc": "Mesaj sayı, alətlər və təklif uzunluğundan istifadə edərək əsas səydən düşüncə büdcəsini ölçün.", "auto": "Auto Combo", "autoDesc": "Self-healing smart routing pool (Performance optimized)", "custom": "Custom", @@ -8146,16 +8155,7 @@ "cliproxyapiHealth": "Sağlamlıq", "cliproxyapiPort": "Port", "qdrantHost": "Ev sahibi", - "qdrantCollection": "Kolleksiya", - "thinkingBudgetIndependenceHint": "__MISSING__:Compression, routing, and token-limit features keep working in every mode. Auto does not mean “auto-show thinking” — it strips client reasoning fields.", - "thinkingModePassthrough": "__MISSING__:Passthrough", - "thinkingModePassthroughDesc": "__MISSING__:Leave client reasoning unchanged (effort, summary, thinking blocks). Required for Codex/Desktop visible thinking. Default.", - "thinkingModeAuto": "__MISSING__:Auto (strip)", - "thinkingModeAutoDesc": "__MISSING__:Strip all client thinking/reasoning fields (reasoning, reasoning_effort, Claude thinking, Gemini thinking_config) and let the provider invent defaults. Can hide thinking panels and break client summary requests.", - "thinkingModeCustom": "__MISSING__:Custom", - "thinkingModeCustomDesc": "__MISSING__:Overwrite every request with a fixed thinking token budget you set below.", - "thinkingModeAdaptive": "__MISSING__:Adaptive", - "thinkingModeAdaptiveDesc": "__MISSING__:Scale thinking budget from a base effort using message count, tools, and prompt length." + "qdrantCollection": "Kolleksiya" }, "contextRtk": { "title": "RTK Engine", diff --git a/src/i18n/messages/bg.json b/src/i18n/messages/bg.json index 50183bedbd..cf8c6bc8f1 100644 --- a/src/i18n/messages/bg.json +++ b/src/i18n/messages/bg.json @@ -6821,8 +6821,17 @@ "chars": "{count} знака", "thinkingBudgetTitle": "Мислен бюджет", "thinkingBudgetDesc": "Контролирайте използването на токен за мотивиране на AI във всички заявки", + "thinkingBudgetIndependenceHint": "Функциите за компресия, маршрутизиране и лимит на токени продължават да работят във всеки режим. Авто не означава \"авто-показване на мислене\" — той премахва полетата за разсъждения на клиента.", "passthrough": "Преминаване", "passthroughDesc": "Без промени — клиентът контролира мислещия бюджет", + "thinkingModePassthrough": "Пропускане", + "thinkingModePassthroughDesc": "Оставете разсъжденията на клиента непроменени (усилие, резюме, блокове на мислене). Изисква се за видимото мислене на Codex/Desktop. По подразбиране.", + "thinkingModeAuto": "Авто (премахване)", + "thinkingModeAutoDesc": "Премахнете всички полета за мислене/разсъждение на клиента (reasoning, reasoning_effort, Claude thinking, Gemini thinking_config) и нека доставчикът да измисли подразбиращи се стойности. Може да скриете панелите за мислене и да нарушите заявките за обобщение на клиента.", + "thinkingModeCustom": "Персонализиран", + "thinkingModeCustomDesc": "Презапишете всяка заявка с фиксиран бюджет за токени за мислене, който зададете по-долу.", + "thinkingModeAdaptive": "Адаптивен", + "thinkingModeAdaptiveDesc": "Мащабирайте бюджета за мислене от основно усилие, използвайки брой съобщения, инструменти и дължина на подсказките.", "auto": "Авто", "autoDesc": "Премахнете цялата мислеща конфигурация — оставете доставчика да реши", "custom": "По поръчка", @@ -8146,16 +8155,7 @@ "cliproxyapiHealth": "Здраве", "cliproxyapiPort": "Порт", "qdrantHost": "Хост", - "qdrantCollection": "Колекция", - "thinkingBudgetIndependenceHint": "__MISSING__:Compression, routing, and token-limit features keep working in every mode. Auto does not mean “auto-show thinking” — it strips client reasoning fields.", - "thinkingModePassthrough": "__MISSING__:Passthrough", - "thinkingModePassthroughDesc": "__MISSING__:Leave client reasoning unchanged (effort, summary, thinking blocks). Required for Codex/Desktop visible thinking. Default.", - "thinkingModeAuto": "__MISSING__:Auto (strip)", - "thinkingModeAutoDesc": "__MISSING__:Strip all client thinking/reasoning fields (reasoning, reasoning_effort, Claude thinking, Gemini thinking_config) and let the provider invent defaults. Can hide thinking panels and break client summary requests.", - "thinkingModeCustom": "__MISSING__:Custom", - "thinkingModeCustomDesc": "__MISSING__:Overwrite every request with a fixed thinking token budget you set below.", - "thinkingModeAdaptive": "__MISSING__:Adaptive", - "thinkingModeAdaptiveDesc": "__MISSING__:Scale thinking budget from a base effort using message count, tools, and prompt length." + "qdrantCollection": "Колекция" }, "contextRtk": { "title": "RTK Engine", diff --git a/src/i18n/messages/bn.json b/src/i18n/messages/bn.json index 33f14dfbd5..e483932fa4 100644 --- a/src/i18n/messages/bn.json +++ b/src/i18n/messages/bn.json @@ -6821,8 +6821,17 @@ "chars": "{count} chars", "thinkingBudgetTitle": "Thinking Budget", "thinkingBudgetDesc": "Control AI reasoning token usage across all requests", + "thinkingBudgetIndependenceHint": "সংকোচন, রাউটিং, এবং টোকেন-সীমা বৈশিষ্ট্যগুলি প্রতিটি মোডে কাজ করতে থাকে। অটো মানে “অটো-শো চিন্তা” নয় — এটি ক্লায়েন্টের যুক্তি ক্ষেত্রগুলি মুছে ফেলে।", "passthrough": "Passthrough", "passthroughDesc": "No changes — client controls thinking budget", + "thinkingModePassthrough": "পাসথ্রু", + "thinkingModePassthroughDesc": "ক্লায়েন্টের যুক্তি অপরিবর্তিত রাখুন (প্রয়াস, সারসংক্ষেপ, চিন্তার ব্লক)। Codex/Desktop দৃশ্যমান চিন্তার জন্য প্রয়োজনীয়। ডিফল্ট।", + "thinkingModeAuto": "অটো (স্ট্রিপ)", + "thinkingModeAutoDesc": "সব ক্লায়েন্ট চিন্তা/যুক্তি ক্ষেত্রগুলি মুছে ফেলুন (যুক্তি, যুক্তি_প্রয়াস, ক্লড চিন্তা, জেমিনি চিন্তা_কনফিগ) এবং প্রদানকারীকে ডিফল্টগুলি আবিষ্কার করতে দিন। চিন্তার প্যানেলগুলি লুকানো যেতে পারে এবং ক্লায়েন্ট সারসংক্ষেপের অনুরোধগুলি ভেঙে দিতে পারে।", + "thinkingModeCustom": "কাস্টম", + "thinkingModeCustomDesc": "নিচে আপনি সেট করা একটি নির্দিষ্ট চিন্তা টোকেন বাজেট দিয়ে প্রতিটি অনুরোধকে ওভাররাইট করুন।", + "thinkingModeAdaptive": "অ্যাডাপটিভ", + "thinkingModeAdaptiveDesc": "বার্তা সংখ্যা, সরঞ্জাম এবং প্রম্পট দৈর্ঘ্য ব্যবহার করে একটি ভিত্তি প্রচেষ্টার থেকে চিন্তার বাজেট স্কেল করুন।", "auto": "Auto Combo", "autoDesc": "Self-healing smart routing pool (Performance optimized)", "custom": "Custom", @@ -8146,16 +8155,7 @@ "cliproxyapiHealth": "স্বাস্থ্য", "cliproxyapiPort": "পোর্ট", "qdrantHost": "হোস্ট", - "qdrantCollection": "সংগ্রহ", - "thinkingBudgetIndependenceHint": "__MISSING__:Compression, routing, and token-limit features keep working in every mode. Auto does not mean “auto-show thinking” — it strips client reasoning fields.", - "thinkingModePassthrough": "__MISSING__:Passthrough", - "thinkingModePassthroughDesc": "__MISSING__:Leave client reasoning unchanged (effort, summary, thinking blocks). Required for Codex/Desktop visible thinking. Default.", - "thinkingModeAuto": "__MISSING__:Auto (strip)", - "thinkingModeAutoDesc": "__MISSING__:Strip all client thinking/reasoning fields (reasoning, reasoning_effort, Claude thinking, Gemini thinking_config) and let the provider invent defaults. Can hide thinking panels and break client summary requests.", - "thinkingModeCustom": "__MISSING__:Custom", - "thinkingModeCustomDesc": "__MISSING__:Overwrite every request with a fixed thinking token budget you set below.", - "thinkingModeAdaptive": "__MISSING__:Adaptive", - "thinkingModeAdaptiveDesc": "__MISSING__:Scale thinking budget from a base effort using message count, tools, and prompt length." + "qdrantCollection": "সংগ্রহ" }, "contextRtk": { "title": "RTK Engine", diff --git a/src/i18n/messages/cs.json b/src/i18n/messages/cs.json index a4f6a5a2d9..0609644a0e 100644 --- a/src/i18n/messages/cs.json +++ b/src/i18n/messages/cs.json @@ -6821,8 +6821,17 @@ "chars": "{count} znaků", "thinkingBudgetTitle": "Promýšlení rozpočtu", "thinkingBudgetDesc": "Řídí využití AI reasoning tokenů v požadavcích", + "thinkingBudgetIndependenceHint": "Funkce komprese, směrování a limit tokenů fungují ve všech režimech. Automatický režim neznamená „automatické zobrazení myšlení“ — odstraňuje pole pro uvažování klienta.", "passthrough": "Průchod", "passthroughDesc": "Beze změny – klient kontroluje rozpočet", + "thinkingModePassthrough": "Přesměrování", + "thinkingModePassthroughDesc": "Nechte důvody klienta beze změny (úsilí, shrnutí, myšlenkové bloky). Povinné pro viditelné myšlení Codex/Desktop. Výchozí.", + "thinkingModeAuto": "Auto (strip)", + "thinkingModeAutoDesc": "Odeberte všechna pole myšlení/úvah klienta (úvaha, úsilí o úvahu, myšlení Claude, myšlení Gemini_config) a nechte poskytovatele vymyslet výchozí hodnoty. Můžete skrýt panely myšlení a přerušit žádosti o shrnutí klienta.", + "thinkingModeCustom": "Vlastní", + "thinkingModeCustomDesc": "Přepište každou žádost s pevným rozpočtem tokenů pro myšlení, který nastavíte níže.", + "thinkingModeAdaptive": "Adaptivní", + "thinkingModeAdaptiveDesc": "Škálování rozpočtu na myšlení na základě základního úsilí pomocí počtu zpráv, nástrojů a délky výzvy.", "auto": "Auto", "autoDesc": "Odstraní veškeré thinking nastavení – nechá rozhodnutí na poskytovateli", "custom": "Vlastní", @@ -8146,16 +8155,7 @@ "cliproxyapiHealth": "Zdraví", "cliproxyapiPort": "Port", "qdrantHost": "Host", - "qdrantCollection": "Kolekce", - "thinkingBudgetIndependenceHint": "__MISSING__:Compression, routing, and token-limit features keep working in every mode. Auto does not mean “auto-show thinking” — it strips client reasoning fields.", - "thinkingModePassthrough": "__MISSING__:Passthrough", - "thinkingModePassthroughDesc": "__MISSING__:Leave client reasoning unchanged (effort, summary, thinking blocks). Required for Codex/Desktop visible thinking. Default.", - "thinkingModeAuto": "__MISSING__:Auto (strip)", - "thinkingModeAutoDesc": "__MISSING__:Strip all client thinking/reasoning fields (reasoning, reasoning_effort, Claude thinking, Gemini thinking_config) and let the provider invent defaults. Can hide thinking panels and break client summary requests.", - "thinkingModeCustom": "__MISSING__:Custom", - "thinkingModeCustomDesc": "__MISSING__:Overwrite every request with a fixed thinking token budget you set below.", - "thinkingModeAdaptive": "__MISSING__:Adaptive", - "thinkingModeAdaptiveDesc": "__MISSING__:Scale thinking budget from a base effort using message count, tools, and prompt length." + "qdrantCollection": "Kolekce" }, "contextRtk": { "title": "RTK Engine", diff --git a/src/i18n/messages/da.json b/src/i18n/messages/da.json index 8faabde096..380bc7cf83 100644 --- a/src/i18n/messages/da.json +++ b/src/i18n/messages/da.json @@ -6821,8 +6821,17 @@ "chars": "{count} tegn", "thinkingBudgetTitle": "Tænke budget", "thinkingBudgetDesc": "Kontroller brugen af AI-ræsonnementstoken på tværs af alle anmodninger", + "thinkingBudgetIndependenceHint": "Kompressions-, routing- og token-grænsefunktioner fortsætter med at fungere i alle tilstande. Auto betyder ikke \"auto-vis tænkning\" - det fjerner klientens ræsonneringsfelter.", "passthrough": "Gennemløb", "passthroughDesc": "Ingen ændringer - klienten styrer tænkebudgettet", + "thinkingModePassthrough": "Passthrough", + "thinkingModePassthroughDesc": "Lad klientens ræsonnering forblive uændret (indsats, resumé, tænkeblokke). Påkrævet for Codex/Desktop synlig tænkning. Standard.", + "thinkingModeAuto": "Auto (strip)", + "thinkingModeAutoDesc": "Fjern alle klienttanker/overvejelser felter (overvejelse, overvejelse_besvær, Claude tænkning, Gemini tænkning_config) og lad udbyderen opfinde standarder. Kan skjule tænke paneler og bryde klient opsummeringsanmodninger.", + "thinkingModeCustom": "Brugerdefineret", + "thinkingModeCustomDesc": "Overskriv hver anmodning med et fast tænketokenbudget, du angiver nedenfor.", + "thinkingModeAdaptive": "Adaptiv", + "thinkingModeAdaptiveDesc": "Skalér tænkningsbudgettet fra en grundindsats ved hjælp af beskedantal, værktøjer og promptlængde.", "auto": "Auto", "autoDesc": "Fjern al tænkekonfig - lad udbyderen bestemme", "custom": "Brugerdefineret", @@ -8146,16 +8155,7 @@ "cliproxyapiHealth": "Sundhed", "cliproxyapiPort": "Port", "qdrantHost": "Vært", - "qdrantCollection": "Samling", - "thinkingBudgetIndependenceHint": "__MISSING__:Compression, routing, and token-limit features keep working in every mode. Auto does not mean “auto-show thinking” — it strips client reasoning fields.", - "thinkingModePassthrough": "__MISSING__:Passthrough", - "thinkingModePassthroughDesc": "__MISSING__:Leave client reasoning unchanged (effort, summary, thinking blocks). Required for Codex/Desktop visible thinking. Default.", - "thinkingModeAuto": "__MISSING__:Auto (strip)", - "thinkingModeAutoDesc": "__MISSING__:Strip all client thinking/reasoning fields (reasoning, reasoning_effort, Claude thinking, Gemini thinking_config) and let the provider invent defaults. Can hide thinking panels and break client summary requests.", - "thinkingModeCustom": "__MISSING__:Custom", - "thinkingModeCustomDesc": "__MISSING__:Overwrite every request with a fixed thinking token budget you set below.", - "thinkingModeAdaptive": "__MISSING__:Adaptive", - "thinkingModeAdaptiveDesc": "__MISSING__:Scale thinking budget from a base effort using message count, tools, and prompt length." + "qdrantCollection": "Samling" }, "contextRtk": { "title": "RTK Engine", diff --git a/src/i18n/messages/de.json b/src/i18n/messages/de.json index a8c31e516c..aa515ce09a 100644 --- a/src/i18n/messages/de.json +++ b/src/i18n/messages/de.json @@ -6821,8 +6821,17 @@ "chars": "{count} Zeichen", "thinkingBudgetTitle": "Denkendes Budget", "thinkingBudgetDesc": "Kontrollieren Sie die Verwendung von KI-Begründungstoken für alle Anfragen", + "thinkingBudgetIndependenceHint": "Kompressions-, Routing- und Token-Limit-Funktionen funktionieren in jedem Modus. Auto bedeutet nicht „Auto-Anzeige-Denken“ – es entfernt die Felder für die Client-Argumentation.", "passthrough": "Passthrough", "passthroughDesc": "Keine Änderungen – der Kunde kontrolliert das Denkbudget", + "thinkingModePassthrough": "Durchleitung", + "thinkingModePassthroughDesc": "Lassen Sie die Client-Begründung unverändert (Aufwand, Zusammenfassung, Denkblöcke). Erforderlich für Codex/Desktop sichtbares Denken. Standard.", + "thinkingModeAuto": "Auto (strip)", + "thinkingModeAutoDesc": "Entfernen Sie alle Felder für das Denken/Überlegen des Clients (reasoning, reasoning_effort, Claude thinking, Gemini thinking_config) und lassen Sie den Anbieter Standardwerte erfinden. Denken-Panels können ausgeblendet werden und die Zusammenfassungsanfragen des Clients können unterbrochen werden.", + "thinkingModeCustom": "Benutzerdefiniert", + "thinkingModeCustomDesc": "Überschreibe jede Anfrage mit einem festen Denk-Token-Budget, das du unten festlegst.", + "thinkingModeAdaptive": "Adaptiv", + "thinkingModeAdaptiveDesc": "Skalieren Sie das Denkbudget von einem Basiseinsatz unter Verwendung der Nachrichtenanzahl, der Tools und der Eingabelänge.", "auto": "Automatisch", "autoDesc": "Entfernen Sie alle Denkkonfigurationen – lassen Sie den Anbieter entscheiden", "custom": "Benutzerdefiniert", @@ -8146,16 +8155,7 @@ "cliproxyapiHealth": "Gesundheit", "cliproxyapiPort": "Port", "qdrantHost": "Host", - "qdrantCollection": "Sammlung", - "thinkingBudgetIndependenceHint": "__MISSING__:Compression, routing, and token-limit features keep working in every mode. Auto does not mean “auto-show thinking” — it strips client reasoning fields.", - "thinkingModePassthrough": "__MISSING__:Passthrough", - "thinkingModePassthroughDesc": "__MISSING__:Leave client reasoning unchanged (effort, summary, thinking blocks). Required for Codex/Desktop visible thinking. Default.", - "thinkingModeAuto": "__MISSING__:Auto (strip)", - "thinkingModeAutoDesc": "__MISSING__:Strip all client thinking/reasoning fields (reasoning, reasoning_effort, Claude thinking, Gemini thinking_config) and let the provider invent defaults. Can hide thinking panels and break client summary requests.", - "thinkingModeCustom": "__MISSING__:Custom", - "thinkingModeCustomDesc": "__MISSING__:Overwrite every request with a fixed thinking token budget you set below.", - "thinkingModeAdaptive": "__MISSING__:Adaptive", - "thinkingModeAdaptiveDesc": "__MISSING__:Scale thinking budget from a base effort using message count, tools, and prompt length." + "qdrantCollection": "Sammlung" }, "contextRtk": { "title": "RTK Engine", diff --git a/src/i18n/messages/es.json b/src/i18n/messages/es.json index 9b115ac671..afb6a8317c 100644 --- a/src/i18n/messages/es.json +++ b/src/i18n/messages/es.json @@ -6821,8 +6821,17 @@ "chars": "{count} caracteres", "thinkingBudgetTitle": "Pensando en el presupuesto", "thinkingBudgetDesc": "Controle el uso del token de razonamiento de IA en todas las solicitudes", + "thinkingBudgetIndependenceHint": "Las funciones de compresión, enrutamiento y límite de tokens siguen funcionando en todos los modos. Auto no significa \"auto-mostrar pensamiento\": elimina los campos de razonamiento del cliente.", "passthrough": "Paso a través", "passthroughDesc": "Sin cambios: el cliente controla el presupuesto pensando en", + "thinkingModePassthrough": "Passthrough", + "thinkingModePassthroughDesc": "Dejar el razonamiento del cliente sin cambios (esfuerzo, resumen, bloques de pensamiento). Requerido para Codex/Desktop visible thinking. Predeterminado.", + "thinkingModeAuto": "Auto (strip)", + "thinkingModeAutoDesc": "Elimina todos los campos de pensamiento/razonamiento del cliente (razonamiento, esfuerzo_razonamiento, pensamiento de Claude, configuración_de_pensamiento de Gemini) y permite que el proveedor invente valores predeterminados. Se pueden ocultar los paneles de pensamiento y romper las solicitudes de resumen del cliente.", + "thinkingModeCustom": "Personalizado", + "thinkingModeCustomDesc": "Sobrescribe cada solicitud con un presupuesto fijo de tokens de pensamiento que establezcas a continuación.", + "thinkingModeAdaptive": "Adaptativo", + "thinkingModeAdaptiveDesc": "Escalar el presupuesto de pensamiento a partir de un esfuerzo base utilizando el recuento de mensajes, herramientas y longitud del aviso.", "auto": "Automático", "autoDesc": "Elimine toda configuración de pensamiento: deje que el proveedor decida", "custom": "personalizado", @@ -8146,16 +8155,7 @@ "cliproxyapiHealth": "Salud", "cliproxyapiPort": "Puerto", "qdrantHost": "Anfitrión", - "qdrantCollection": "Colección", - "thinkingBudgetIndependenceHint": "__MISSING__:Compression, routing, and token-limit features keep working in every mode. Auto does not mean “auto-show thinking” — it strips client reasoning fields.", - "thinkingModePassthrough": "__MISSING__:Passthrough", - "thinkingModePassthroughDesc": "__MISSING__:Leave client reasoning unchanged (effort, summary, thinking blocks). Required for Codex/Desktop visible thinking. Default.", - "thinkingModeAuto": "__MISSING__:Auto (strip)", - "thinkingModeAutoDesc": "__MISSING__:Strip all client thinking/reasoning fields (reasoning, reasoning_effort, Claude thinking, Gemini thinking_config) and let the provider invent defaults. Can hide thinking panels and break client summary requests.", - "thinkingModeCustom": "__MISSING__:Custom", - "thinkingModeCustomDesc": "__MISSING__:Overwrite every request with a fixed thinking token budget you set below.", - "thinkingModeAdaptive": "__MISSING__:Adaptive", - "thinkingModeAdaptiveDesc": "__MISSING__:Scale thinking budget from a base effort using message count, tools, and prompt length." + "qdrantCollection": "Colección" }, "contextRtk": { "title": "RTK Engine", diff --git a/src/i18n/messages/fa.json b/src/i18n/messages/fa.json index 244242ab0a..f8939025e2 100644 --- a/src/i18n/messages/fa.json +++ b/src/i18n/messages/fa.json @@ -6821,8 +6821,17 @@ "chars": "{count} chars", "thinkingBudgetTitle": "Thinking Budget", "thinkingBudgetDesc": "Control AI reasoning token usage across all requests", + "thinkingBudgetIndependenceHint": "ویژگی‌های فشرده‌سازی، مسیریابی و محدودیت توکن در هر حالت کار می‌کنند. حالت خودکار به معنای \"نمایش خودکار تفکر\" نیست - این حالت فیلدهای استدلال کلاینت را حذف می‌کند.", "passthrough": "Passthrough", "passthroughDesc": "No changes — client controls thinking budget", + "thinkingModePassthrough": "عبور از طریق", + "thinkingModePassthroughDesc": "دلایل مشتری را بدون تغییر بگذارید (تلاش، خلاصه، بلوک‌های تفکر). برای تفکر قابل مشاهده Codex/Desktop الزامی است. پیش‌فرض.", + "thinkingModeAuto": "خودکار (حذف)", + "thinkingModeAutoDesc": "تمام فیلدهای تفکر/استدلال مشتری (استدلال، تلاش استدلال، تفکر کلود، پیکربندی تفکر جمنای) را حذف کنید و اجازه دهید ارائه‌دهنده پیش‌فرض‌ها را اختراع کند. می‌توان پنل‌های تفکر را پنهان کرد و درخواست‌های خلاصه مشتری را مختل کرد.", + "thinkingModeCustom": "سفارشی", + "thinkingModeCustomDesc": "هر درخواست را با یک بودجه توکن تفکر ثابت که در زیر تعیین کرده‌اید، بازنویسی کنید.", + "thinkingModeAdaptive": "سازگار", + "thinkingModeAdaptiveDesc": "مقیاس تفکر بودجه از یک تلاش پایه با استفاده از تعداد پیام، ابزارها و طول پیام.", "auto": "Auto Combo", "autoDesc": "Self-healing smart routing pool (Performance optimized)", "custom": "Custom", @@ -8146,16 +8155,7 @@ "cliproxyapiHealth": "سلامت", "cliproxyapiPort": "پورت", "qdrantHost": "میزبان", - "qdrantCollection": "مجموعه", - "thinkingBudgetIndependenceHint": "__MISSING__:Compression, routing, and token-limit features keep working in every mode. Auto does not mean “auto-show thinking” — it strips client reasoning fields.", - "thinkingModePassthrough": "__MISSING__:Passthrough", - "thinkingModePassthroughDesc": "__MISSING__:Leave client reasoning unchanged (effort, summary, thinking blocks). Required for Codex/Desktop visible thinking. Default.", - "thinkingModeAuto": "__MISSING__:Auto (strip)", - "thinkingModeAutoDesc": "__MISSING__:Strip all client thinking/reasoning fields (reasoning, reasoning_effort, Claude thinking, Gemini thinking_config) and let the provider invent defaults. Can hide thinking panels and break client summary requests.", - "thinkingModeCustom": "__MISSING__:Custom", - "thinkingModeCustomDesc": "__MISSING__:Overwrite every request with a fixed thinking token budget you set below.", - "thinkingModeAdaptive": "__MISSING__:Adaptive", - "thinkingModeAdaptiveDesc": "__MISSING__:Scale thinking budget from a base effort using message count, tools, and prompt length." + "qdrantCollection": "مجموعه" }, "contextRtk": { "title": "RTK Engine", diff --git a/src/i18n/messages/fi.json b/src/i18n/messages/fi.json index b9797b2afe..fa32b59a5e 100644 --- a/src/i18n/messages/fi.json +++ b/src/i18n/messages/fi.json @@ -6821,8 +6821,17 @@ "chars": "{count} merkkiä", "thinkingBudgetTitle": "Miettivä budjetti", "thinkingBudgetDesc": "Hallitse tekoälyn päättelytunnuksen käyttöä kaikissa pyynnöissä", + "thinkingBudgetIndependenceHint": "Pakkaus-, reititys- ja token-rajaratkaisut toimivat kaikissa tiloissa. Auto ei tarkoita \"automaattista ajattelua\" — se poistaa asiakasajattelun kentät.", "passthrough": "Läpivienti", "passthroughDesc": "Ei muutoksia – asiakas hallitsee ajattelubudjettia", + "thinkingModePassthrough": "Ohitus", + "thinkingModePassthroughDesc": "Jätä asiakasyhteenveto muuttumattomaksi (vaivannäkö, yhteenveto, ajatuslohkot). Vaaditaan Codex/Desktopin näkyvää ajattelua. Oletusarvo.", + "thinkingModeAuto": "Auto (strip)", + "thinkingModeAutoDesc": "Poista kaikki asiakaspohjaiset ajattelu/ajatteluprosessi kentät (reasoning, reasoning_effort, Claude thinking, Gemini thinking_config) ja anna palveluntarjoajan keksiä oletusarvot. Voit piilottaa ajattelupaneelit ja rikkoa asiakassummapyyntöjä.", + "thinkingModeCustom": "Mukautettu", + "thinkingModeCustomDesc": "Ylikirjoita jokainen pyyntö kiinteällä ajattelutoken-budjetilla, jonka asetat alla.", + "thinkingModeAdaptive": "Soveltuva", + "thinkingModeAdaptiveDesc": "Skaalaa ajattelubudjettia perusponnistuksen perusteella käyttäen viestilukuja, työkaluja ja kehotepituutta.", "auto": "Auto", "autoDesc": "Poista kaikki ajatellut asetukset – anna palveluntarjoajan päättää", "custom": "Mukautettu", @@ -8146,16 +8155,7 @@ "cliproxyapiHealth": "Terveys", "cliproxyapiPort": "Portti", "qdrantHost": "Isäntä", - "qdrantCollection": "Kokoelma", - "thinkingBudgetIndependenceHint": "__MISSING__:Compression, routing, and token-limit features keep working in every mode. Auto does not mean “auto-show thinking” — it strips client reasoning fields.", - "thinkingModePassthrough": "__MISSING__:Passthrough", - "thinkingModePassthroughDesc": "__MISSING__:Leave client reasoning unchanged (effort, summary, thinking blocks). Required for Codex/Desktop visible thinking. Default.", - "thinkingModeAuto": "__MISSING__:Auto (strip)", - "thinkingModeAutoDesc": "__MISSING__:Strip all client thinking/reasoning fields (reasoning, reasoning_effort, Claude thinking, Gemini thinking_config) and let the provider invent defaults. Can hide thinking panels and break client summary requests.", - "thinkingModeCustom": "__MISSING__:Custom", - "thinkingModeCustomDesc": "__MISSING__:Overwrite every request with a fixed thinking token budget you set below.", - "thinkingModeAdaptive": "__MISSING__:Adaptive", - "thinkingModeAdaptiveDesc": "__MISSING__:Scale thinking budget from a base effort using message count, tools, and prompt length." + "qdrantCollection": "Kokoelma" }, "contextRtk": { "title": "RTK Engine", diff --git a/src/i18n/messages/fr.json b/src/i18n/messages/fr.json index b8940a793e..06c7424641 100644 --- a/src/i18n/messages/fr.json +++ b/src/i18n/messages/fr.json @@ -6821,8 +6821,17 @@ "chars": "{count} caractères", "thinkingBudgetTitle": "Penser le budget", "thinkingBudgetDesc": "Contrôler l'utilisation des jetons de raisonnement IA pour toutes les requêtes", + "thinkingBudgetIndependenceHint": "Les fonctionnalités de compression, de routage et de limite de jetons continuent de fonctionner dans tous les modes. Auto ne signifie pas « auto-afficher la réflexion » — cela supprime les champs de raisonnement du client.", "passthrough": "Passage", "passthroughDesc": "Aucun changement — le client contrôle le budget en pensant", + "thinkingModePassthrough": "Passerelle", + "thinkingModePassthroughDesc": "Laissez le raisonnement du client inchangé (effort, résumé, blocs de réflexion). Requis pour la pensée visible de Codex/Desktop. Par défaut.", + "thinkingModeAuto": "Auto (strip)", + "thinkingModeAutoDesc": "Supprimez tous les champs de réflexion/raisonnement client (raisonnement, effort_raisonnement, réflexion Claude, configuration_thinking_Gemini) et laissez le fournisseur inventer des valeurs par défaut. Peut masquer les panneaux de réflexion et interrompre les demandes de résumé client.", + "thinkingModeCustom": "Personnalisé", + "thinkingModeCustomDesc": "Écrasez chaque demande avec un budget de jetons de réflexion fixe que vous définissez ci-dessous.", + "thinkingModeAdaptive": "Adaptatif", + "thinkingModeAdaptiveDesc": "Échelle de réflexion budgétaire à partir d'un effort de base en utilisant le nombre de messages, les outils et la longueur des invites.", "auto": "Automatique", "autoDesc": "Supprimez toute configuration de réflexion - laissez le fournisseur décider", "custom": "Personnalisé", @@ -8146,16 +8155,7 @@ "cliproxyapiHealth": "Santé", "cliproxyapiPort": "Port", "qdrantHost": "Hôte", - "qdrantCollection": "Collection", - "thinkingBudgetIndependenceHint": "__MISSING__:Compression, routing, and token-limit features keep working in every mode. Auto does not mean “auto-show thinking” — it strips client reasoning fields.", - "thinkingModePassthrough": "__MISSING__:Passthrough", - "thinkingModePassthroughDesc": "__MISSING__:Leave client reasoning unchanged (effort, summary, thinking blocks). Required for Codex/Desktop visible thinking. Default.", - "thinkingModeAuto": "__MISSING__:Auto (strip)", - "thinkingModeAutoDesc": "__MISSING__:Strip all client thinking/reasoning fields (reasoning, reasoning_effort, Claude thinking, Gemini thinking_config) and let the provider invent defaults. Can hide thinking panels and break client summary requests.", - "thinkingModeCustom": "__MISSING__:Custom", - "thinkingModeCustomDesc": "__MISSING__:Overwrite every request with a fixed thinking token budget you set below.", - "thinkingModeAdaptive": "__MISSING__:Adaptive", - "thinkingModeAdaptiveDesc": "__MISSING__:Scale thinking budget from a base effort using message count, tools, and prompt length." + "qdrantCollection": "Collection" }, "contextRtk": { "title": "RTK Engine", diff --git a/src/i18n/messages/gu.json b/src/i18n/messages/gu.json index 540c5c5e83..024bd04ff2 100644 --- a/src/i18n/messages/gu.json +++ b/src/i18n/messages/gu.json @@ -6821,8 +6821,17 @@ "chars": "{count} chars", "thinkingBudgetTitle": "Thinking Budget", "thinkingBudgetDesc": "Control AI reasoning token usage across all requests", + "thinkingBudgetIndependenceHint": "સંકોચન, માર્ગદર્શન, અને ટોકન-મર્યાદા સુવિધાઓ દરેક મોડમાં કાર્યરત રહે છે. ઓટોનો અર્થ “ઓટો-શો વિચારો” નથી — તે ક્લાયન્ટની વિચારણા ક્ષેત્રોને દૂર કરે છે.", "passthrough": "Passthrough", "passthroughDesc": "No changes — client controls thinking budget", + "thinkingModePassthrough": "પાસથ્રૂ", + "thinkingModePassthroughDesc": "ક્લાયન્ટનું કારણ બદલવા નહી (પ્રયાસ, સારાંશ, વિચાર બ્લોક). Codex/Desktop દૃશ્યમાન વિચાર માટે જરૂરી. ડિફોલ્ટ.", + "thinkingModeAuto": "ઓટો (સ્ટ્રિપ)", + "thinkingModeAutoDesc": "બધા ક્લાયન્ટ વિચારણા/વિચારણા ક્ષેત્રો (વિચારણા, વિચારણા_પ્રયાસ, ક્લોડ વિચારણા, જેમિની વિચારણા_કન્ફિગ) દૂર કરો અને પ્રદાતા ડિફોલ્ટ્સ શોધવા દો. વિચારણા પેનલ છુપાવી શકાય છે અને ક્લાયન્ટ સારાંશ વિનંતીઓને તોડે છે.", + "thinkingModeCustom": "કસ્ટમ", + "thinkingModeCustomDesc": "તમારા દ્વારા નીચે નિર્ધારિત કરેલા સ્થિર વિચાર ટોકન બજેટ સાથે દરેક વિનંતીને ઓવરરાઇટ કરો.", + "thinkingModeAdaptive": "અનુકૂળ", + "thinkingModeAdaptiveDesc": "સંદેશા સંખ્યા, સાધનો, અને પ્રોમ્પ્ટ લંબાઈનો ઉપયોગ કરીને આધાર પ્રયાસમાંથી વિચારધારા બજેટને સ્કેલ કરો.", "auto": "Auto Combo", "autoDesc": "Self-healing smart routing pool (Performance optimized)", "custom": "Custom", @@ -8146,16 +8155,7 @@ "cliproxyapiHealth": "આરોગ્ય", "cliproxyapiPort": "પોર્ટ", "qdrantHost": "હોસ્ટ", - "qdrantCollection": "સંગ્રહ", - "thinkingBudgetIndependenceHint": "__MISSING__:Compression, routing, and token-limit features keep working in every mode. Auto does not mean “auto-show thinking” — it strips client reasoning fields.", - "thinkingModePassthrough": "__MISSING__:Passthrough", - "thinkingModePassthroughDesc": "__MISSING__:Leave client reasoning unchanged (effort, summary, thinking blocks). Required for Codex/Desktop visible thinking. Default.", - "thinkingModeAuto": "__MISSING__:Auto (strip)", - "thinkingModeAutoDesc": "__MISSING__:Strip all client thinking/reasoning fields (reasoning, reasoning_effort, Claude thinking, Gemini thinking_config) and let the provider invent defaults. Can hide thinking panels and break client summary requests.", - "thinkingModeCustom": "__MISSING__:Custom", - "thinkingModeCustomDesc": "__MISSING__:Overwrite every request with a fixed thinking token budget you set below.", - "thinkingModeAdaptive": "__MISSING__:Adaptive", - "thinkingModeAdaptiveDesc": "__MISSING__:Scale thinking budget from a base effort using message count, tools, and prompt length." + "qdrantCollection": "સંગ્રહ" }, "contextRtk": { "title": "RTK Engine", diff --git a/src/i18n/messages/he.json b/src/i18n/messages/he.json index 556e33bc00..b6dc7a1b22 100644 --- a/src/i18n/messages/he.json +++ b/src/i18n/messages/he.json @@ -6821,8 +6821,17 @@ "chars": "{count} תווים", "thinkingBudgetTitle": "חשיבה תקציב", "thinkingBudgetDesc": "שליטה בשימוש באסימונים של AI בכל הבקשות", + "thinkingBudgetIndependenceHint": "תכונות דחיסה, ניתוב ומגבלת טוקנים ממשיכות לפעול בכל מצב. אוטומטי לא אומר \"הצגת חשיבה אוטומטית\" — זה מסיר את שדות ההיגיון של הלקוח.", "passthrough": "מעבר", "passthroughDesc": "ללא שינויים - הלקוח שולט בתקציב החשיבה", + "thinkingModePassthrough": "מעבר", + "thinkingModePassthroughDesc": "השאר את ההיגיון של הלקוח ללא שינוי (מאמץ, סיכום, בלוקים של חשיבה). נדרש עבור חשיבה נראית של Codex/Desktop. ברירת מחדל.", + "thinkingModeAuto": "אוטומטי (סטריפ)", + "thinkingModeAutoDesc": "מחק את כל השדות של חשיבה/הסקה של הלקוח (הסקה, מאמץ הסקה, חשיבת קלוד, תצורת חשיבת ג'מיני) ותן לספק להמציא ברירות מחדל. ניתן להסתיר פאנלים של חשיבה ולשבור בקשות סיכום של הלקוח.", + "thinkingModeCustom": "מותאם אישית", + "thinkingModeCustomDesc": "כתוב מחדש כל בקשה עם תקציב קבוע של טוקנים לחשיבה שהגדרת למטה.", + "thinkingModeAdaptive": "מותאם", + "thinkingModeAdaptiveDesc": "הגדל את תקציב החשיבה ממאמץ בסיסי באמצעות מספר הודעות, כלים ואורך ההנחיה.", "auto": "אוטומטי", "autoDesc": "הסר את כל תצורת החשיבה - תן לספק להחליט", "custom": "מותאם אישית", @@ -8146,16 +8155,7 @@ "cliproxyapiHealth": "בריאות", "cliproxyapiPort": "פורט", "qdrantHost": "מארח", - "qdrantCollection": "אוסף", - "thinkingBudgetIndependenceHint": "__MISSING__:Compression, routing, and token-limit features keep working in every mode. Auto does not mean “auto-show thinking” — it strips client reasoning fields.", - "thinkingModePassthrough": "__MISSING__:Passthrough", - "thinkingModePassthroughDesc": "__MISSING__:Leave client reasoning unchanged (effort, summary, thinking blocks). Required for Codex/Desktop visible thinking. Default.", - "thinkingModeAuto": "__MISSING__:Auto (strip)", - "thinkingModeAutoDesc": "__MISSING__:Strip all client thinking/reasoning fields (reasoning, reasoning_effort, Claude thinking, Gemini thinking_config) and let the provider invent defaults. Can hide thinking panels and break client summary requests.", - "thinkingModeCustom": "__MISSING__:Custom", - "thinkingModeCustomDesc": "__MISSING__:Overwrite every request with a fixed thinking token budget you set below.", - "thinkingModeAdaptive": "__MISSING__:Adaptive", - "thinkingModeAdaptiveDesc": "__MISSING__:Scale thinking budget from a base effort using message count, tools, and prompt length." + "qdrantCollection": "אוסף" }, "contextRtk": { "title": "RTK Engine", diff --git a/src/i18n/messages/hi.json b/src/i18n/messages/hi.json index ee4fc9e8bd..bc0a978377 100644 --- a/src/i18n/messages/hi.json +++ b/src/i18n/messages/hi.json @@ -6821,8 +6821,17 @@ "chars": "{count} वर्ण", "thinkingBudgetTitle": "सोच बजट", "thinkingBudgetDesc": "सभी अनुरोधों में एआई तर्क टोकन उपयोग को नियंत्रित करें", + "thinkingBudgetIndependenceHint": "संपीड़न, रूटिंग, और टोकन-सीमा सुविधाएँ हर मोड में काम करती रहती हैं। ऑटो का मतलब \"ऑटो-शो थिंकिंग\" नहीं है - यह क्लाइंट तर्क क्षेत्रों को हटा देता है।", "passthrough": "पारगमन", "passthroughDesc": "कोई परिवर्तन नहीं - ग्राहक सोच बजट को नियंत्रित करता है", + "thinkingModePassthrough": "पासथ्रू", + "thinkingModePassthroughDesc": "क्लाइंट तर्क को अपरिवर्तित छोड़ें (प्रयास, सारांश, सोचने के ब्लॉक)। Codex/Desktop दृश्य सोच के लिए आवश्यक। डिफ़ॉल्ट।", + "thinkingModeAuto": "ऑटो (स्ट्रिप)", + "thinkingModeAutoDesc": "सभी क्लाइंट सोच/कारण क्षेत्रों (reasoning, reasoning_effort, Claude thinking, Gemini thinking_config) को हटा दें और प्रदाता को डिफ़ॉल्ट आविष्कार करने दें। सोच पैनल छिपा सकते हैं और क्लाइंट सारांश अनुरोधों को तोड़ सकते हैं।", + "thinkingModeCustom": "कस्टम", + "thinkingModeCustomDesc": "नीचे सेट किए गए निश्चित थिंकिंग टोकन बजट के साथ हर अनुरोध को ओवरराइट करें।", + "thinkingModeAdaptive": "अनुकूलनशील", + "thinkingModeAdaptiveDesc": "संदेश संख्या, उपकरणों और प्रॉम्प्ट की लंबाई का उपयोग करके एक आधार प्रयास से सोचने के बजट को स्केल करें।", "auto": "ऑटो", "autoDesc": "सभी सोच कॉन्फ़िगरेशन को हटा दें - प्रदाता को निर्णय लेने दें", "custom": "कस्टम", @@ -8146,16 +8155,7 @@ "cliproxyapiHealth": "स्वास्थ्य", "cliproxyapiPort": "पोर्ट", "qdrantHost": "होस्ट", - "qdrantCollection": "संग्रह", - "thinkingBudgetIndependenceHint": "__MISSING__:Compression, routing, and token-limit features keep working in every mode. Auto does not mean “auto-show thinking” — it strips client reasoning fields.", - "thinkingModePassthrough": "__MISSING__:Passthrough", - "thinkingModePassthroughDesc": "__MISSING__:Leave client reasoning unchanged (effort, summary, thinking blocks). Required for Codex/Desktop visible thinking. Default.", - "thinkingModeAuto": "__MISSING__:Auto (strip)", - "thinkingModeAutoDesc": "__MISSING__:Strip all client thinking/reasoning fields (reasoning, reasoning_effort, Claude thinking, Gemini thinking_config) and let the provider invent defaults. Can hide thinking panels and break client summary requests.", - "thinkingModeCustom": "__MISSING__:Custom", - "thinkingModeCustomDesc": "__MISSING__:Overwrite every request with a fixed thinking token budget you set below.", - "thinkingModeAdaptive": "__MISSING__:Adaptive", - "thinkingModeAdaptiveDesc": "__MISSING__:Scale thinking budget from a base effort using message count, tools, and prompt length." + "qdrantCollection": "संग्रह" }, "contextRtk": { "title": "RTK Engine", diff --git a/src/i18n/messages/hu.json b/src/i18n/messages/hu.json index e2a3e96e47..777acfc59d 100644 --- a/src/i18n/messages/hu.json +++ b/src/i18n/messages/hu.json @@ -6821,8 +6821,17 @@ "chars": "{count} karakter", "thinkingBudgetTitle": "Gondolkodó költségvetés", "thinkingBudgetDesc": "Az AI érvelési jogkivonat használatának szabályozása minden kérésnél", + "thinkingBudgetIndependenceHint": "A tömörítési, irányítási és token-korlátozási funkciók minden módban működnek. Az automatikus nem azt jelenti, hogy „automatikus megjelenítés gondolkodás” — eltávolítja az ügyfél érvelési mezőit.", "passthrough": "Átjárás", "passthroughDesc": "Nincs változás – az ügyfél irányítja a költségvetést", + "thinkingModePassthrough": "Átjáró", + "thinkingModePassthroughDesc": "Hagyja a kliens indoklását változatlanul (erőfeszítés, összefoglaló, gondolkodási blokkok). Kötelező a Codex/Desktop látható gondolkodásához. Alapértelmezett.", + "thinkingModeAuto": "Automatikus (csík)", + "thinkingModeAutoDesc": "Törölje az összes kliens gondolkodási/érvelési mezőt (érvelés, érvelési_erőfeszítés, Claude gondolkodás, Gemini gondolkodás_beállítás) és hagyja, hogy a szolgáltató találja ki az alapértelmezetteket. Elrejtheti a gondolkodási panelek és megszakíthatja a kliens összegzési kéréseket.", + "thinkingModeCustom": "Egyedi", + "thinkingModeCustomDesc": "Felülírja az összes kérést egy rögzített gondolkodási token költségkerettel, amelyet alább állít be.", + "thinkingModeAdaptive": "Adaptív", + "thinkingModeAdaptiveDesc": "Skálázza a gondolkodási költségvetést egy alap erőfeszítésből az üzenetek számának, az eszközöknek és a prompt hosszának figyelembevételével.", "auto": "Auto", "autoDesc": "Távolítsa el az összes gondolkodó konfigurációt – hagyja, hogy a szolgáltató döntsön", "custom": "Egyedi", @@ -8146,16 +8155,7 @@ "cliproxyapiHealth": "Egészség", "cliproxyapiPort": "Port", "qdrantHost": "Gazda", - "qdrantCollection": "Gyűjtemény", - "thinkingBudgetIndependenceHint": "__MISSING__:Compression, routing, and token-limit features keep working in every mode. Auto does not mean “auto-show thinking” — it strips client reasoning fields.", - "thinkingModePassthrough": "__MISSING__:Passthrough", - "thinkingModePassthroughDesc": "__MISSING__:Leave client reasoning unchanged (effort, summary, thinking blocks). Required for Codex/Desktop visible thinking. Default.", - "thinkingModeAuto": "__MISSING__:Auto (strip)", - "thinkingModeAutoDesc": "__MISSING__:Strip all client thinking/reasoning fields (reasoning, reasoning_effort, Claude thinking, Gemini thinking_config) and let the provider invent defaults. Can hide thinking panels and break client summary requests.", - "thinkingModeCustom": "__MISSING__:Custom", - "thinkingModeCustomDesc": "__MISSING__:Overwrite every request with a fixed thinking token budget you set below.", - "thinkingModeAdaptive": "__MISSING__:Adaptive", - "thinkingModeAdaptiveDesc": "__MISSING__:Scale thinking budget from a base effort using message count, tools, and prompt length." + "qdrantCollection": "Gyűjtemény" }, "contextRtk": { "title": "RTK Engine", diff --git a/src/i18n/messages/id.json b/src/i18n/messages/id.json index 0a54443096..41dbb6c12a 100644 --- a/src/i18n/messages/id.json +++ b/src/i18n/messages/id.json @@ -6821,8 +6821,17 @@ "chars": "{count} karakter", "thinkingBudgetTitle": "Memikirkan Anggaran", "thinkingBudgetDesc": "Kontrol penggunaan token penalaran AI di semua permintaan", + "thinkingBudgetIndependenceHint": "Fitur kompresi, pengalihan, dan batas-token tetap berfungsi di setiap mode. Auto tidak berarti “auto-show thinking” — itu menghapus bidang penalaran klien.", "passthrough": "Melewati", "passthroughDesc": "Tidak ada perubahan — klien mengontrol anggaran pemikiran", + "thinkingModePassthrough": "Lewati", + "thinkingModePassthroughDesc": "Biarkan alasan klien tidak berubah (usaha, ringkasan, blok pemikiran). Diperlukan untuk pemikiran terlihat Codex/Desktop. Default.", + "thinkingModeAuto": "Auto (strip)", + "thinkingModeAutoDesc": "Hapus semua bidang pemikiran/alasan klien (reasoning, reasoning_effort, Claude thinking, Gemini thinking_config) dan biarkan penyedia menciptakan default. Dapat menyembunyikan panel pemikiran dan memutuskan permintaan ringkasan klien.", + "thinkingModeCustom": "Kustom", + "thinkingModeCustomDesc": "Timpakan setiap permintaan dengan anggaran token pemikiran tetap yang Anda tetapkan di bawah.", + "thinkingModeAdaptive": "Adaptif", + "thinkingModeAdaptiveDesc": "Skala anggaran pemikiran dari upaya dasar menggunakan jumlah pesan, alat, dan panjang prompt.", "auto": "Otomatis", "autoDesc": "Hapus semua konfigurasi pemikiran — biarkan penyedia memutuskan", "custom": "Adat", @@ -8146,16 +8155,7 @@ "cliproxyapiHealth": "Kesehatan", "cliproxyapiPort": "Port", "qdrantHost": "Host", - "qdrantCollection": "Koleksi", - "thinkingBudgetIndependenceHint": "__MISSING__:Compression, routing, and token-limit features keep working in every mode. Auto does not mean “auto-show thinking” — it strips client reasoning fields.", - "thinkingModePassthrough": "__MISSING__:Passthrough", - "thinkingModePassthroughDesc": "__MISSING__:Leave client reasoning unchanged (effort, summary, thinking blocks). Required for Codex/Desktop visible thinking. Default.", - "thinkingModeAuto": "__MISSING__:Auto (strip)", - "thinkingModeAutoDesc": "__MISSING__:Strip all client thinking/reasoning fields (reasoning, reasoning_effort, Claude thinking, Gemini thinking_config) and let the provider invent defaults. Can hide thinking panels and break client summary requests.", - "thinkingModeCustom": "__MISSING__:Custom", - "thinkingModeCustomDesc": "__MISSING__:Overwrite every request with a fixed thinking token budget you set below.", - "thinkingModeAdaptive": "__MISSING__:Adaptive", - "thinkingModeAdaptiveDesc": "__MISSING__:Scale thinking budget from a base effort using message count, tools, and prompt length." + "qdrantCollection": "Koleksi" }, "contextRtk": { "title": "RTK Engine", diff --git a/src/i18n/messages/in.json b/src/i18n/messages/in.json index 6c7d4ae360..d856f0511d 100644 --- a/src/i18n/messages/in.json +++ b/src/i18n/messages/in.json @@ -6821,8 +6821,17 @@ "chars": "{count} chars", "thinkingBudgetTitle": "Thinking Budget", "thinkingBudgetDesc": "Control AI reasoning token usage across all requests", + "thinkingBudgetIndependenceHint": "Fitur kompresi, pengalihan, dan batas-token terus berfungsi di setiap mode. Auto tidak berarti \"auto-show thinking\" — itu menghapus bidang penalaran klien.", "passthrough": "Passthrough", "passthroughDesc": "No changes — client controls thinking budget", + "thinkingModePassthrough": "Lewati", + "thinkingModePassthroughDesc": "Biarkan alasan klien tidak berubah (usaha, ringkasan, blok pemikiran). Diperlukan untuk pemikiran terlihat Codex/Desktop. Default.", + "thinkingModeAuto": "Auto (strip)", + "thinkingModeAutoDesc": "Hapus semua bidang pemikiran/alasan klien (reasoning, reasoning_effort, Claude thinking, Gemini thinking_config) dan biarkan penyedia menciptakan default. Dapat menyembunyikan panel pemikiran dan memutuskan permintaan ringkasan klien.", + "thinkingModeCustom": "Kustom", + "thinkingModeCustomDesc": "Timpakan setiap permintaan dengan anggaran token pemikiran tetap yang Anda tetapkan di bawah ini.", + "thinkingModeAdaptive": "Adaptif", + "thinkingModeAdaptiveDesc": "Skala anggaran pemikiran dari upaya dasar menggunakan jumlah pesan, alat, dan panjang prompt.", "auto": "Auto Combo", "autoDesc": "Self-healing smart routing pool (Performance optimized)", "custom": "Custom", @@ -8146,16 +8155,7 @@ "cliproxyapiHealth": "Kesehatan", "cliproxyapiPort": "Port", "qdrantHost": "Tuan Rumah", - "qdrantCollection": "Koleksi", - "thinkingBudgetIndependenceHint": "__MISSING__:Compression, routing, and token-limit features keep working in every mode. Auto does not mean “auto-show thinking” — it strips client reasoning fields.", - "thinkingModePassthrough": "__MISSING__:Passthrough", - "thinkingModePassthroughDesc": "__MISSING__:Leave client reasoning unchanged (effort, summary, thinking blocks). Required for Codex/Desktop visible thinking. Default.", - "thinkingModeAuto": "__MISSING__:Auto (strip)", - "thinkingModeAutoDesc": "__MISSING__:Strip all client thinking/reasoning fields (reasoning, reasoning_effort, Claude thinking, Gemini thinking_config) and let the provider invent defaults. Can hide thinking panels and break client summary requests.", - "thinkingModeCustom": "__MISSING__:Custom", - "thinkingModeCustomDesc": "__MISSING__:Overwrite every request with a fixed thinking token budget you set below.", - "thinkingModeAdaptive": "__MISSING__:Adaptive", - "thinkingModeAdaptiveDesc": "__MISSING__:Scale thinking budget from a base effort using message count, tools, and prompt length." + "qdrantCollection": "Koleksi" }, "contextRtk": { "title": "RTK Engine", diff --git a/src/i18n/messages/it.json b/src/i18n/messages/it.json index 8483d7a4d3..f7cdce01d4 100644 --- a/src/i18n/messages/it.json +++ b/src/i18n/messages/it.json @@ -6821,8 +6821,17 @@ "chars": "{count} caratteri", "thinkingBudgetTitle": "Pensare al bilancio", "thinkingBudgetDesc": "Controlla l'utilizzo dei token di ragionamento dell'intelligenza artificiale in tutte le richieste", + "thinkingBudgetIndependenceHint": "Le funzionalità di compressione, instradamento e limite di token continuano a funzionare in ogni modalità. Auto non significa \"auto-mostrare il pensiero\" — rimuove i campi di ragionamento del client.", "passthrough": "Passante", "passthroughDesc": "Nessun cambiamento: il cliente controlla il budget", + "thinkingModePassthrough": "Passa attraverso", + "thinkingModePassthroughDesc": "Lascia invariata la motivazione del cliente (sforzo, riepilogo, blocchi di pensiero). Richiesto per il pensiero visibile di Codex/Desktop. Predefinito.", + "thinkingModeAuto": "Auto (strip)", + "thinkingModeAutoDesc": "Rimuovi tutti i campi di pensiero/razionamento del client (razionamento, sforzo_razionamento, pensiero Claude, configurazione_pensiero Gemini) e lascia che il fornitore inventi i valori predefiniti. Può nascondere i pannelli di pensiero e interrompere le richieste di riepilogo del client.", + "thinkingModeCustom": "Personalizzato", + "thinkingModeCustomDesc": "Sovrascrivi ogni richiesta con un budget fisso di token di pensiero che imposti di seguito.", + "thinkingModeAdaptive": "Adattivo", + "thinkingModeAdaptiveDesc": "Scala il budget di pensiero da uno sforzo di base utilizzando il conteggio dei messaggi, gli strumenti e la lunghezza del prompt.", "auto": "Auto", "autoDesc": "Elimina ogni configurazione pensante: lascia decidere al provider", "custom": "Costume", @@ -8146,16 +8155,7 @@ "cliproxyapiHealth": "Salute", "cliproxyapiPort": "Porta", "qdrantHost": "Host", - "qdrantCollection": "Collezione", - "thinkingBudgetIndependenceHint": "__MISSING__:Compression, routing, and token-limit features keep working in every mode. Auto does not mean “auto-show thinking” — it strips client reasoning fields.", - "thinkingModePassthrough": "__MISSING__:Passthrough", - "thinkingModePassthroughDesc": "__MISSING__:Leave client reasoning unchanged (effort, summary, thinking blocks). Required for Codex/Desktop visible thinking. Default.", - "thinkingModeAuto": "__MISSING__:Auto (strip)", - "thinkingModeAutoDesc": "__MISSING__:Strip all client thinking/reasoning fields (reasoning, reasoning_effort, Claude thinking, Gemini thinking_config) and let the provider invent defaults. Can hide thinking panels and break client summary requests.", - "thinkingModeCustom": "__MISSING__:Custom", - "thinkingModeCustomDesc": "__MISSING__:Overwrite every request with a fixed thinking token budget you set below.", - "thinkingModeAdaptive": "__MISSING__:Adaptive", - "thinkingModeAdaptiveDesc": "__MISSING__:Scale thinking budget from a base effort using message count, tools, and prompt length." + "qdrantCollection": "Collezione" }, "contextRtk": { "title": "RTK Engine", diff --git a/src/i18n/messages/ja.json b/src/i18n/messages/ja.json index 005e1ee84b..13503227f4 100644 --- a/src/i18n/messages/ja.json +++ b/src/i18n/messages/ja.json @@ -6821,8 +6821,17 @@ "chars": "{count} 文字", "thinkingBudgetTitle": "予算を考える", "thinkingBudgetDesc": "すべてのリクエストにわたる AI 推論トークンの使用を制御する", + "thinkingBudgetIndependenceHint": "圧縮、ルーティング、およびトークン制限機能はすべてのモードで動作し続けます。自動は「自動表示思考」を意味するのではなく、クライアントの推論フィールドを削除します。", "passthrough": "パススルー", "passthroughDesc": "変更なし – クライアントが思考予算をコントロール", + "thinkingModePassthrough": "パススルー", + "thinkingModePassthroughDesc": "クライアントの理由付けを変更しない(努力、要約、思考ブロック)。Codex/Desktopの可視思考に必要です。デフォルト。", + "thinkingModeAuto": "自動(ストリップ)", + "thinkingModeAutoDesc": "すべてのクライアントの思考/推論フィールド(reasoning、reasoning_effort、Claude thinking、Gemini thinking_config)を削除し、プロバイダーにデフォルトを考案させます。思考パネルを非表示にし、クライアントのサマリーリクエストを中断させることができます。", + "thinkingModeCustom": "カスタム", + "thinkingModeCustomDesc": "下記で設定した固定の思考トークン予算で、すべてのリクエストを上書きします。", + "thinkingModeAdaptive": "適応型", + "thinkingModeAdaptiveDesc": "メッセージ数、ツール、およびプロンプトの長さを使用して、基本的な努力からスケール思考予算を算出します。", "auto": "自動", "autoDesc": "すべての思考構成を取り除きます - プロバイダーに決定させます", "custom": "カスタム", @@ -8146,16 +8155,7 @@ "cliproxyapiHealth": "健康", "cliproxyapiPort": "ポート", "qdrantHost": "ホスト", - "qdrantCollection": "コレクション", - "thinkingBudgetIndependenceHint": "__MISSING__:Compression, routing, and token-limit features keep working in every mode. Auto does not mean “auto-show thinking” — it strips client reasoning fields.", - "thinkingModePassthrough": "__MISSING__:Passthrough", - "thinkingModePassthroughDesc": "__MISSING__:Leave client reasoning unchanged (effort, summary, thinking blocks). Required for Codex/Desktop visible thinking. Default.", - "thinkingModeAuto": "__MISSING__:Auto (strip)", - "thinkingModeAutoDesc": "__MISSING__:Strip all client thinking/reasoning fields (reasoning, reasoning_effort, Claude thinking, Gemini thinking_config) and let the provider invent defaults. Can hide thinking panels and break client summary requests.", - "thinkingModeCustom": "__MISSING__:Custom", - "thinkingModeCustomDesc": "__MISSING__:Overwrite every request with a fixed thinking token budget you set below.", - "thinkingModeAdaptive": "__MISSING__:Adaptive", - "thinkingModeAdaptiveDesc": "__MISSING__:Scale thinking budget from a base effort using message count, tools, and prompt length." + "qdrantCollection": "コレクション" }, "contextRtk": { "title": "RTK Engine", diff --git a/src/i18n/messages/ko.json b/src/i18n/messages/ko.json index 801e6f1aa0..258e5b9c7d 100644 --- a/src/i18n/messages/ko.json +++ b/src/i18n/messages/ko.json @@ -6821,8 +6821,17 @@ "chars": "{count}자", "thinkingBudgetTitle": "사고 예산", "thinkingBudgetDesc": "모든 요청에서 AI 추론 토큰 사용을 제어합니다.", + "thinkingBudgetIndependenceHint": "압축, 라우팅 및 토큰 제한 기능은 모든 모드에서 계속 작동합니다. 자동은 \"자동 표시 사고\"를 의미하지 않으며, 클라이언트 추론 필드를 제거합니다.", "passthrough": "통과", "passthroughDesc": "변경 사항 없음 - 클라이언트가 사고 예산을 제어합니다.", + "thinkingModePassthrough": "패스스루", + "thinkingModePassthroughDesc": "클라이언트 추론 변경하지 않기 (노력, 요약, 사고 블록). Codex/Desktop 가시적 사고에 필요합니다. 기본값.", + "thinkingModeAuto": "자동 (스트립)", + "thinkingModeAutoDesc": "모든 클라이언트 사고/추론 필드(추론, 추론_노력, Claude 사고, Gemini 사고_구성)를 제거하고 제공자가 기본값을 생성하도록 하십시오. 사고 패널을 숨기고 클라이언트 요약 요청을 중단할 수 있습니다.", + "thinkingModeCustom": "사용자 정의", + "thinkingModeCustomDesc": "아래 설정한 고정된 사고 토큰 예산으로 모든 요청을 덮어씁니다.", + "thinkingModeAdaptive": "적응형", + "thinkingModeAdaptiveDesc": "메시지 수, 도구 및 프롬프트 길이를 사용하여 기본 노력에서 예산을 조정하세요.", "auto": "자동 콤보", "autoDesc": "자가 복구형 스마트 라우팅 풀(성능 최적화)", "custom": "맞춤", @@ -8146,16 +8155,7 @@ "cliproxyapiHealth": "건강", "cliproxyapiPort": "포트", "qdrantHost": "호스트", - "qdrantCollection": "컬렉션", - "thinkingBudgetIndependenceHint": "__MISSING__:Compression, routing, and token-limit features keep working in every mode. Auto does not mean “auto-show thinking” — it strips client reasoning fields.", - "thinkingModePassthrough": "__MISSING__:Passthrough", - "thinkingModePassthroughDesc": "__MISSING__:Leave client reasoning unchanged (effort, summary, thinking blocks). Required for Codex/Desktop visible thinking. Default.", - "thinkingModeAuto": "__MISSING__:Auto (strip)", - "thinkingModeAutoDesc": "__MISSING__:Strip all client thinking/reasoning fields (reasoning, reasoning_effort, Claude thinking, Gemini thinking_config) and let the provider invent defaults. Can hide thinking panels and break client summary requests.", - "thinkingModeCustom": "__MISSING__:Custom", - "thinkingModeCustomDesc": "__MISSING__:Overwrite every request with a fixed thinking token budget you set below.", - "thinkingModeAdaptive": "__MISSING__:Adaptive", - "thinkingModeAdaptiveDesc": "__MISSING__:Scale thinking budget from a base effort using message count, tools, and prompt length." + "qdrantCollection": "컬렉션" }, "contextRtk": { "title": "RTK Engine", diff --git a/src/i18n/messages/mr.json b/src/i18n/messages/mr.json index 675f919bf6..e64bf7fbbe 100644 --- a/src/i18n/messages/mr.json +++ b/src/i18n/messages/mr.json @@ -6821,8 +6821,17 @@ "chars": "{count} chars", "thinkingBudgetTitle": "Thinking Budget", "thinkingBudgetDesc": "Control AI reasoning token usage across all requests", + "thinkingBudgetIndependenceHint": "संकुचन, मार्गनिर्देशन, आणि टोकन-सीमा वैशिष्ट्ये प्रत्येक मोडमध्ये कार्यरत राहतात. ऑटो म्हणजे \"ऑटो-शो विचार\" नाही — हे क्लायंट विचार क्षेत्रे काढून टाकते.", "passthrough": "Passthrough", "passthroughDesc": "No changes — client controls thinking budget", + "thinkingModePassthrough": "पॅसथ्रू", + "thinkingModePassthroughDesc": "क्लायंटचे कारण बदलू नका (प्रयत्न, सारांश, विचार ब्लॉक्स). Codex/Desktop दृश्यमान विचारांसाठी आवश्यक. डिफॉल्ट.", + "thinkingModeAuto": "ऑटो (स्ट्रीप)", + "thinkingModeAutoDesc": "सर्व क्लायंट विचार/तर्क क्षेत्रे (तर्क, तर्क_प्रयत्न, क्लॉड विचार, जेमिनी विचार_कॉन्फिग) काढा आणि प्रदाता डिफॉल्ट्स तयार करू द्या. विचार पॅनेल लपवू शकता आणि क्लायंट सारांश विनंत्या तोडू शकता.", + "thinkingModeCustom": "कस्टम", + "thinkingModeCustomDesc": "तुम्ही खाली सेट केलेल्या निश्चित विचार टोकन बजेटसह प्रत्येक विनंती ओव्हरराइट करा.", + "thinkingModeAdaptive": "अनुकूलनीय", + "thinkingModeAdaptiveDesc": "संदेश संख्या, साधने, आणि प्रॉम्प्ट लांबीचा वापर करून मूलभूत प्रयत्नातून विचारांचा बजेट स्केल करा.", "auto": "Auto Combo", "autoDesc": "Self-healing smart routing pool (Performance optimized)", "custom": "Custom", @@ -8146,16 +8155,7 @@ "cliproxyapiHealth": "आरोग्य", "cliproxyapiPort": "पोर्ट", "qdrantHost": "होस्ट", - "qdrantCollection": "संग्रह", - "thinkingBudgetIndependenceHint": "__MISSING__:Compression, routing, and token-limit features keep working in every mode. Auto does not mean “auto-show thinking” — it strips client reasoning fields.", - "thinkingModePassthrough": "__MISSING__:Passthrough", - "thinkingModePassthroughDesc": "__MISSING__:Leave client reasoning unchanged (effort, summary, thinking blocks). Required for Codex/Desktop visible thinking. Default.", - "thinkingModeAuto": "__MISSING__:Auto (strip)", - "thinkingModeAutoDesc": "__MISSING__:Strip all client thinking/reasoning fields (reasoning, reasoning_effort, Claude thinking, Gemini thinking_config) and let the provider invent defaults. Can hide thinking panels and break client summary requests.", - "thinkingModeCustom": "__MISSING__:Custom", - "thinkingModeCustomDesc": "__MISSING__:Overwrite every request with a fixed thinking token budget you set below.", - "thinkingModeAdaptive": "__MISSING__:Adaptive", - "thinkingModeAdaptiveDesc": "__MISSING__:Scale thinking budget from a base effort using message count, tools, and prompt length." + "qdrantCollection": "संग्रह" }, "contextRtk": { "title": "RTK Engine", diff --git a/src/i18n/messages/ms.json b/src/i18n/messages/ms.json index 5ca627cef8..14971e35d7 100644 --- a/src/i18n/messages/ms.json +++ b/src/i18n/messages/ms.json @@ -6821,8 +6821,17 @@ "chars": "{count} aksara", "thinkingBudgetTitle": "Belanjawan Berfikir", "thinkingBudgetDesc": "Kawal penggunaan token penaakulan AI merentas semua permintaan", + "thinkingBudgetIndependenceHint": "Ciri pemampatan, penghalaan, dan had token terus berfungsi dalam setiap mod. Auto tidak bermaksud “auto-tunjuk pemikiran” — ia menghapuskan medan pemikiran klien.", "passthrough": "Laluan", "passthroughDesc": "Tiada perubahan — pelanggan mengawal belanjawan berfikir", + "thinkingModePassthrough": "Passthrough", + "thinkingModePassthroughDesc": "Biarkan alasan klien tidak berubah (usaha, ringkasan, blok pemikiran). Diperlukan untuk pemikiran terlihat Codex/Desktop. Lalai.", + "thinkingModeAuto": "Auto (strip)", + "thinkingModeAutoDesc": "Buang semua medan pemikiran/pertimbangan klien (reasoning, reasoning_effort, Claude thinking, Gemini thinking_config) dan biarkan penyedia mencipta lalai. Boleh menyembunyikan panel pemikiran dan memecahkan permintaan ringkasan klien.", + "thinkingModeCustom": "Kustom", + "thinkingModeCustomDesc": "Tulis semula setiap permintaan dengan bajet token pemikiran tetap yang anda tetapkan di bawah.", + "thinkingModeAdaptive": "Adaptif", + "thinkingModeAdaptiveDesc": "Skala pemikiran bajet dari usaha asas menggunakan bilangan mesej, alat, dan panjang arahan.", "auto": "Auto", "autoDesc": "Keluarkan semua konfigurasi pemikiran — biarkan pembekal memutuskan", "custom": "Adat", @@ -8146,16 +8155,7 @@ "cliproxyapiHealth": "Kesihatan", "cliproxyapiPort": "Pelabuhan", "qdrantHost": "Hos", - "qdrantCollection": "Koleksi", - "thinkingBudgetIndependenceHint": "__MISSING__:Compression, routing, and token-limit features keep working in every mode. Auto does not mean “auto-show thinking” — it strips client reasoning fields.", - "thinkingModePassthrough": "__MISSING__:Passthrough", - "thinkingModePassthroughDesc": "__MISSING__:Leave client reasoning unchanged (effort, summary, thinking blocks). Required for Codex/Desktop visible thinking. Default.", - "thinkingModeAuto": "__MISSING__:Auto (strip)", - "thinkingModeAutoDesc": "__MISSING__:Strip all client thinking/reasoning fields (reasoning, reasoning_effort, Claude thinking, Gemini thinking_config) and let the provider invent defaults. Can hide thinking panels and break client summary requests.", - "thinkingModeCustom": "__MISSING__:Custom", - "thinkingModeCustomDesc": "__MISSING__:Overwrite every request with a fixed thinking token budget you set below.", - "thinkingModeAdaptive": "__MISSING__:Adaptive", - "thinkingModeAdaptiveDesc": "__MISSING__:Scale thinking budget from a base effort using message count, tools, and prompt length." + "qdrantCollection": "Koleksi" }, "contextRtk": { "title": "RTK Engine", diff --git a/src/i18n/messages/nl.json b/src/i18n/messages/nl.json index 0be6cb0242..3063a4237a 100644 --- a/src/i18n/messages/nl.json +++ b/src/i18n/messages/nl.json @@ -6821,8 +6821,17 @@ "chars": "{count} tekens", "thinkingBudgetTitle": "Denkbudget", "thinkingBudgetDesc": "Beheer het gebruik van AI-redeneringstokens voor alle verzoeken", + "thinkingBudgetIndependenceHint": "Compressie-, routerings- en tokenlimietfuncties blijven in elke modus werken. Auto betekent niet “auto-show denken” — het verwijdert de redeneervelden van de client.", "passthrough": "Doorvoer", "passthroughDesc": "Geen wijzigingen – de klant bepaalt het denkbudget", + "thinkingModePassthrough": "Doorvoer", + "thinkingModePassthroughDesc": "Laat de reden van de cliënt ongewijzigd (inspanningen, samenvatting, denkblokken). Vereist voor Codex/Desktop zichtbare gedachten. Standaard.", + "thinkingModeAuto": "Auto (strip)", + "thinkingModeAutoDesc": "Verwijder alle velden voor klantdenken/redenering (redenering, redenering_inspanning, Claude denken, Gemini denken_config) en laat de provider standaardwaarden verzinnen. Kan denkpanelen verbergen en klant samenvattingsverzoeken onderbreken.", + "thinkingModeCustom": "Aangepast", + "thinkingModeCustomDesc": "Overschrijf elke aanvraag met een vast denk-tokenbudget dat je hieronder instelt.", + "thinkingModeAdaptive": "Adaptief", + "thinkingModeAdaptiveDesc": "Schaal het denkbudget vanaf een basisinspanningen met behulp van het aantal berichten, tools en de lengte van de prompt.", "auto": "Automatisch", "autoDesc": "Verwijder alle denkconfiguraties – laat de provider beslissen", "custom": "Aangepast", @@ -8146,16 +8155,7 @@ "cliproxyapiHealth": "Gezondheid", "cliproxyapiPort": "Haven", "qdrantHost": "Host", - "qdrantCollection": "Verzameling", - "thinkingBudgetIndependenceHint": "__MISSING__:Compression, routing, and token-limit features keep working in every mode. Auto does not mean “auto-show thinking” — it strips client reasoning fields.", - "thinkingModePassthrough": "__MISSING__:Passthrough", - "thinkingModePassthroughDesc": "__MISSING__:Leave client reasoning unchanged (effort, summary, thinking blocks). Required for Codex/Desktop visible thinking. Default.", - "thinkingModeAuto": "__MISSING__:Auto (strip)", - "thinkingModeAutoDesc": "__MISSING__:Strip all client thinking/reasoning fields (reasoning, reasoning_effort, Claude thinking, Gemini thinking_config) and let the provider invent defaults. Can hide thinking panels and break client summary requests.", - "thinkingModeCustom": "__MISSING__:Custom", - "thinkingModeCustomDesc": "__MISSING__:Overwrite every request with a fixed thinking token budget you set below.", - "thinkingModeAdaptive": "__MISSING__:Adaptive", - "thinkingModeAdaptiveDesc": "__MISSING__:Scale thinking budget from a base effort using message count, tools, and prompt length." + "qdrantCollection": "Verzameling" }, "contextRtk": { "title": "RTK Engine", diff --git a/src/i18n/messages/no.json b/src/i18n/messages/no.json index f4f65c5356..eb14cdadbe 100644 --- a/src/i18n/messages/no.json +++ b/src/i18n/messages/no.json @@ -6821,8 +6821,17 @@ "chars": "{count} tegn", "thinkingBudgetTitle": "Tenker budsjett", "thinkingBudgetDesc": "Kontroller bruk av AI-resonnementstoken på tvers av alle forespørsler", + "thinkingBudgetIndependenceHint": "Komprimering, ruting og token-grensefunksjoner fortsetter å fungere i alle moduser. Auto betyr ikke \"auto-vis tenkning\" — det fjerner klientens resonneringsfelt.", "passthrough": "Gjennomgang", "passthroughDesc": "Ingen endringer – klienten kontrollerer tenkebudsjettet", + "thinkingModePassthrough": "Passthrough", + "thinkingModePassthroughDesc": "La klientens begrunnelse være uendret (innsats, sammendrag, tankeblokker). Påkrevd for Codex/Desktop synlig tenkning. Standard.", + "thinkingModeAuto": "Auto (strip)", + "thinkingModeAutoDesc": "Fjern alle klienttenkning/ressoneringsfelt (ressonering, resoneringsinnsats, Claude tenkning, Gemini tenkning_config) og la leverandøren finne på standardverdier. Kan skjule tenkningspaneler og bryte klientoppsummeringsforespørslene.", + "thinkingModeCustom": "Egendefinert", + "thinkingModeCustomDesc": "Overskriv hver forespørsel med et fast tenketoken-budsjett du setter nedenfor.", + "thinkingModeAdaptive": "Adaptiv", + "thinkingModeAdaptiveDesc": "Skaler tenkningsbudsjettet fra en grunninnsats ved å bruke meldingsantall, verktøy og lengde på prompten.", "auto": "Auto", "autoDesc": "Fjern all tenkekonfigurasjon – la leverandøren bestemme", "custom": "Egendefinert", @@ -8146,16 +8155,7 @@ "cliproxyapiHealth": "Helse", "cliproxyapiPort": "Port", "qdrantHost": "Vert", - "qdrantCollection": "Samling", - "thinkingBudgetIndependenceHint": "__MISSING__:Compression, routing, and token-limit features keep working in every mode. Auto does not mean “auto-show thinking” — it strips client reasoning fields.", - "thinkingModePassthrough": "__MISSING__:Passthrough", - "thinkingModePassthroughDesc": "__MISSING__:Leave client reasoning unchanged (effort, summary, thinking blocks). Required for Codex/Desktop visible thinking. Default.", - "thinkingModeAuto": "__MISSING__:Auto (strip)", - "thinkingModeAutoDesc": "__MISSING__:Strip all client thinking/reasoning fields (reasoning, reasoning_effort, Claude thinking, Gemini thinking_config) and let the provider invent defaults. Can hide thinking panels and break client summary requests.", - "thinkingModeCustom": "__MISSING__:Custom", - "thinkingModeCustomDesc": "__MISSING__:Overwrite every request with a fixed thinking token budget you set below.", - "thinkingModeAdaptive": "__MISSING__:Adaptive", - "thinkingModeAdaptiveDesc": "__MISSING__:Scale thinking budget from a base effort using message count, tools, and prompt length." + "qdrantCollection": "Samling" }, "contextRtk": { "title": "RTK Engine", diff --git a/src/i18n/messages/phi.json b/src/i18n/messages/phi.json index 05fe69224b..ffe828d87b 100644 --- a/src/i18n/messages/phi.json +++ b/src/i18n/messages/phi.json @@ -6821,8 +6821,17 @@ "chars": "{count} character", "thinkingBudgetTitle": "Pag-iisip na Badyet", "thinkingBudgetDesc": "Kontrolin ang paggamit ng token ng pangangatwiran ng AI sa lahat ng kahilingan", + "thinkingBudgetIndependenceHint": "Ang mga tampok ng compression, routing, at token-limit ay patuloy na gumagana sa bawat mode. Ang Auto ay hindi nangangahulugang \"auto-show thinking\" — inaalis nito ang mga field ng pag-iisip ng kliyente.", "passthrough": "Passthrough", "passthroughDesc": "Walang pagbabago — kinokontrol ng kliyente ang pag-iisip na badyet", + "thinkingModePassthrough": "Passthrough", + "thinkingModePassthroughDesc": "Iwanang hindi nagbago ang dahilan ng kliyente (pagsisikap, buod, mga bloke ng pag-iisip). Kinakailangan para sa Codex/Desktop na nakikitang pag-iisip. Default.", + "thinkingModeAuto": "Auto (strip)", + "thinkingModeAutoDesc": "Tanggalin ang lahat ng mga patlang ng pag-iisip/pag-iisip ng kliyente (reasoning, reasoning_effort, Claude thinking, Gemini thinking_config) at hayaan ang provider na mag-imbento ng mga default. Maaaring itago ang mga panel ng pag-iisip at sirain ang mga kahilingan sa buod ng kliyente.", + "thinkingModeCustom": "Pasadya", + "thinkingModeCustomDesc": "I-override ang bawat kahilingan gamit ang isang nakatakdang badyet ng token sa pag-iisip na itinakda mo sa ibaba.", + "thinkingModeAdaptive": "Nababagay", + "thinkingModeAdaptiveDesc": "I-scale ang pag-iisip ng badyet mula sa isang pangunahing pagsisikap gamit ang bilang ng mensahe, mga tool, at haba ng prompt.", "auto": "Auto", "autoDesc": "I-strip ang lahat ng thinking config — hayaan ang provider na magpasya", "custom": "Custom", @@ -8146,16 +8155,7 @@ "cliproxyapiHealth": "Kalusugan", "cliproxyapiPort": "Port", "qdrantHost": "Host", - "qdrantCollection": "Koleksyon", - "thinkingBudgetIndependenceHint": "__MISSING__:Compression, routing, and token-limit features keep working in every mode. Auto does not mean “auto-show thinking” — it strips client reasoning fields.", - "thinkingModePassthrough": "__MISSING__:Passthrough", - "thinkingModePassthroughDesc": "__MISSING__:Leave client reasoning unchanged (effort, summary, thinking blocks). Required for Codex/Desktop visible thinking. Default.", - "thinkingModeAuto": "__MISSING__:Auto (strip)", - "thinkingModeAutoDesc": "__MISSING__:Strip all client thinking/reasoning fields (reasoning, reasoning_effort, Claude thinking, Gemini thinking_config) and let the provider invent defaults. Can hide thinking panels and break client summary requests.", - "thinkingModeCustom": "__MISSING__:Custom", - "thinkingModeCustomDesc": "__MISSING__:Overwrite every request with a fixed thinking token budget you set below.", - "thinkingModeAdaptive": "__MISSING__:Adaptive", - "thinkingModeAdaptiveDesc": "__MISSING__:Scale thinking budget from a base effort using message count, tools, and prompt length." + "qdrantCollection": "Koleksyon" }, "contextRtk": { "title": "RTK Engine", diff --git a/src/i18n/messages/pl.json b/src/i18n/messages/pl.json index a9224a8978..ee53ffade7 100644 --- a/src/i18n/messages/pl.json +++ b/src/i18n/messages/pl.json @@ -6821,8 +6821,17 @@ "chars": "{count} znaków", "thinkingBudgetTitle": "Budżet na thinking", "thinkingBudgetDesc": "Kontrolowanie zużycia tokens reasoning AI we wszystkich żądaniach.", + "thinkingBudgetIndependenceHint": "Funkcje kompresji, routingu i limitu tokenów działają w każdym trybie. Auto nie oznacza „automatycznego pokazywania myślenia” — usuwa pola rozumowania klienta.", "passthrough": "Passthrough", "passthroughDesc": "Brak zmian — klient kontroluje budżet na thinking.", + "thinkingModePassthrough": "Przepuszczenie", + "thinkingModePassthroughDesc": "Zachowaj uzasadnienie klienta bez zmian (wysiłek, podsumowanie, bloki myślenia). Wymagane dla widocznego myślenia Codex/Desktop. Domyślnie.", + "thinkingModeAuto": "Auto (strip)", + "thinkingModeAutoDesc": "Usuń wszystkie pola myślenia/rozumowania klienta (rozumowanie, wysiłek rozumowania, myślenie Claude'a, konfiguracja myślenia Gemini) i pozwól dostawcy wymyślić domyślne wartości. Można ukryć panele myślenia i przerwać żądania podsumowania klienta.", + "thinkingModeCustom": "Niestandardowy", + "thinkingModeCustomDesc": "Nadpisz każde żądanie stałym budżetem tokenów myślowych, który ustawisz poniżej.", + "thinkingModeAdaptive": "Adaptacyjny", + "thinkingModeAdaptiveDesc": "Skaluj budżet myślenia na podstawie wysiłku przy użyciu liczby wiadomości, narzędzi i długości podpowiedzi.", "auto": "Auto Combo", "autoDesc": "Samonaprawiająca się pula inteligentnego routingu (zoptymalizowana pod kątem wydajności)", "custom": "Niestandardowy", @@ -8146,16 +8155,7 @@ "cliproxyapiHealth": "Zdrowie", "cliproxyapiPort": "Port", "qdrantHost": "Host", - "qdrantCollection": "Kolekcja", - "thinkingBudgetIndependenceHint": "__MISSING__:Compression, routing, and token-limit features keep working in every mode. Auto does not mean “auto-show thinking” — it strips client reasoning fields.", - "thinkingModePassthrough": "__MISSING__:Passthrough", - "thinkingModePassthroughDesc": "__MISSING__:Leave client reasoning unchanged (effort, summary, thinking blocks). Required for Codex/Desktop visible thinking. Default.", - "thinkingModeAuto": "__MISSING__:Auto (strip)", - "thinkingModeAutoDesc": "__MISSING__:Strip all client thinking/reasoning fields (reasoning, reasoning_effort, Claude thinking, Gemini thinking_config) and let the provider invent defaults. Can hide thinking panels and break client summary requests.", - "thinkingModeCustom": "__MISSING__:Custom", - "thinkingModeCustomDesc": "__MISSING__:Overwrite every request with a fixed thinking token budget you set below.", - "thinkingModeAdaptive": "__MISSING__:Adaptive", - "thinkingModeAdaptiveDesc": "__MISSING__:Scale thinking budget from a base effort using message count, tools, and prompt length." + "qdrantCollection": "Kolekcja" }, "contextRtk": { "title": "Silnik RTK", diff --git a/src/i18n/messages/pt-BR.json b/src/i18n/messages/pt-BR.json index 7442152bdb..f85fbba50d 100644 --- a/src/i18n/messages/pt-BR.json +++ b/src/i18n/messages/pt-BR.json @@ -6821,8 +6821,17 @@ "chars": "{count} caracteres", "thinkingBudgetTitle": "Orçamento de Raciocínio", "thinkingBudgetDesc": "Controla se o OmniRoute reescreve parâmetros de thinking/reasoning do cliente antes das requisições irem upstream. Separado de compressão, prompt cache e limites de token de API key.", + "thinkingBudgetIndependenceHint": "Compressão, roteamento e limites de token continuam funcionando em todos os modos. Auto não significa “mostrar thinking automaticamente” — ele remove os campos de reasoning do cliente.", "passthrough": "Passagem Direta", "passthroughDesc": "Sem alterações — cliente controla orçamento de raciocínio", + "thinkingModePassthrough": "Passagem direta", + "thinkingModePassthroughDesc": "Mantém o reasoning do cliente inalterado (effort, summary, thinking blocks). Necessário para thinking visível no Codex/Desktop. Padrão.", + "thinkingModeAuto": "Auto (remover)", + "thinkingModeAutoDesc": "Remove todos os campos de thinking/reasoning do cliente (reasoning, reasoning_effort, Claude thinking, Gemini thinking_config) e deixa o provedor inventar padrões. Pode ocultar painéis de thinking e quebrar pedidos de summary do cliente.", + "thinkingModeCustom": "Personalizado", + "thinkingModeCustomDesc": "Sobrescreve cada requisição com um orçamento fixo de tokens de thinking definido abaixo.", + "thinkingModeAdaptive": "Adaptativo", + "thinkingModeAdaptiveDesc": "Escala o orçamento de thinking a partir de um esforço base usando contagem de mensagens, ferramentas e tamanho do prompt.", "auto": "Auto Combo", "autoDesc": "Pool de roteamento inteligente (Otimizado)", "custom": "Personalizado", @@ -8146,16 +8155,7 @@ "cliproxyapiHealth": "Saúde", "cliproxyapiPort": "Porta", "qdrantHost": "Host", - "qdrantCollection": "Coleção", - "thinkingBudgetIndependenceHint": "Compressão, roteamento e limites de token continuam funcionando em todos os modos. Auto não significa “mostrar thinking automaticamente” — ele remove os campos de reasoning do cliente.", - "thinkingModePassthrough": "Passagem direta", - "thinkingModePassthroughDesc": "Mantém o reasoning do cliente inalterado (effort, summary, thinking blocks). Necessário para thinking visível no Codex/Desktop. Padrão.", - "thinkingModeAuto": "Auto (remover)", - "thinkingModeAutoDesc": "Remove todos os campos de thinking/reasoning do cliente (reasoning, reasoning_effort, Claude thinking, Gemini thinking_config) e deixa o provedor inventar padrões. Pode ocultar painéis de thinking e quebrar pedidos de summary do cliente.", - "thinkingModeCustom": "Personalizado", - "thinkingModeCustomDesc": "Sobrescreve cada requisição com um orçamento fixo de tokens de thinking definido abaixo.", - "thinkingModeAdaptive": "Adaptativo", - "thinkingModeAdaptiveDesc": "Escala o orçamento de thinking a partir de um esforço base usando contagem de mensagens, ferramentas e tamanho do prompt." + "qdrantCollection": "Coleção" }, "contextRtk": { "title": "Motor RTK", diff --git a/src/i18n/messages/pt.json b/src/i18n/messages/pt.json index bca5a7520e..ea789f8b49 100644 --- a/src/i18n/messages/pt.json +++ b/src/i18n/messages/pt.json @@ -979,7 +979,7 @@ "disabled": "Desativado", "featureFlagOmnirouteEmergencyFallbackDescription": "Encaminhar pedidos com orçamento esgotado para o fornecedor/modelo de contingência gratuito de emergência.", "featureFlagArenaEloSyncEnabledDescription": "Ativar a sincronização periódica do ELO da tabela de classificação da Arena AI para classificações de inteligência do modelo.", - "featureFlagExposeCcDiscoveryAliasesDescription": "__MISSING__:Advertise claude/<provider>/<model> mirror ids on /v1/models so Claude Code gateway model discovery lists non-Claude models. Warning: doubles catalog entries for all clients when enabled globally.", + "featureFlagExposeCcDiscoveryAliasesDescription": "Anuncie os ids de espelho claude/<provider>/<model> em /v1/models para que a descoberta de modelos do gateway Claude Code liste modelos não Claude. Aviso: duplica entradas de catálogo para todos os clientes quando ativado globalmente.", "sidebar": { "home": "Página inicial", "dashboard": "Painel", @@ -1097,7 +1097,7 @@ "combosLive": "Combo Studio", "combosLiveSubtitle": "Cascata de encaminhamento em tempo real", "compressionStudio": "Compression Studio", - "compressionExclusions": "__MISSING__:Exclusions", + "compressionExclusions": "Exclusões", "contextSettingsSubtitle": "Predefinições globais", "contextHeadroomSubtitle": "Compactação tabular", "contextSessionDedupSubtitle": "Desduplicação entre turnos", @@ -1108,7 +1108,7 @@ "contextUltraSubtitle": "Poda heurística", "contextOmniglyphSubtitle": "Contexto como imagens", "compressionStudioSubtitle": "Cascata de motores em tempo real", - "compressionExclusionsSubtitle": "__MISSING__:Per-model/endpoint bypass", + "compressionExclusionsSubtitle": "Bypass por modelo/ponto final", "chaosConfigSubtitle": "Execução paralela multi-modelo", "routingSection": "Encaminhamento", "protocolsSection": "Protocolos", @@ -1151,7 +1151,7 @@ "settingsSecurity": "Segurança", "settingsAccessTokens": "Tokens de Acesso", "settingsFeatureFlags": "Sinalizadores de recursos", - "settingsCache": "__MISSING__:Cache", + "settingsCache": "Cache", "settingsAuthz": "Autorização", "settingsRouting": "Encaminhamento", "settingsResilience": "Resiliência", @@ -1163,7 +1163,7 @@ "runtime": "Runtime", "consoleLogs": "Registos da Consola", "logsTimeline": "Linha do Tempo", - "logsTimelineSubtitle": "__MISSING__:Visual request timeline", + "logsTimelineSubtitle": "Linha do tempo de pedidos visuais", "globalRouting": "Encaminhamento Global", "mitmProxy": "Proxy MITM", "oneProxy": "1Proxy", @@ -1238,7 +1238,7 @@ "settingsSecuritySubtitle": "Auth e criptografia", "settingsAccessTokensSubtitle": "Tokens de CLI com âmbito para modo remoto", "settingsFeatureFlagsSubtitle": "Alternar recursos do sistema", - "settingsCacheSubtitle": "__MISSING__:Model catalog and response caching", + "settingsCacheSubtitle": "Catálogo de Modelos e Cache de Respostas", "settingsSidebar": "Barra Lateral", "settingsSidebarSubtitle": "Personaliza o layout da barra lateral", "settingsAuthzSubtitle": "Inventário de rotas e política de desvio", @@ -1530,79 +1530,7 @@ "settings.update": "Settings Updated", "settings.update_failed": "Settings Update Failed", "sync.token.created": "Sync Token Created", - "sync.token.revoked": "Sync Token Revoked", - "apiKey": { - "activate": "Chave de API Ativada", - "ban": "Chave de API Banida", - "deactivate": "Chave de API Desativada", - "regenerate": "Chave de API Regenerada", - "scopes": { - "grant": "Âmbitos da Chave de API Concedidos", - "revoke": "Âmbitos da Chave de API Revogados", - "update": "Âmbitos da Chave de API Atualizados" - }, - "unban": "Chave de API Desbanida" - }, - "auth": { - "login": { - "error": "Erro de Início de Sessão", - "failed": "Falha no Início de Sessão", - "locked": "Início de Sessão Bloqueado", - "misconfigured": "Início de Sessão Mal Configurado", - "setup_required": "Configuração de Início de Sessão Necessária", - "success": "Início de Sessão com Sucesso" - }, - "logout": { - "success": "Fim de Sessão com Sucesso" - } - }, - "compliance": { - "cleanup": "Limpeza de Conformidade" - }, - "provider": { - "credentials": { - "applied": "Credenciais do Fornecedor Aplicadas", - "batch_revoked": "Credenciais do Fornecedor Revogadas em Lote", - "bulk_created": "Credenciais do Fornecedor Criadas em Massa", - "bulk_imported": "Credenciais do Fornecedor Importadas em Massa", - "created": "Credenciais do Fornecedor Criadas", - "imported": "Credenciais do Fornecedor Importadas", - "revoked": "Credenciais do Provedor Revogadas", - "updated": "Credenciais do Provedor Atualizadas" - }, - "validation": { - "ssrf_blocked": "SSRF do Provedor Bloqueado" - } - }, - "quota": { - "plan": { - "updated": "Plano de Quotas Atualizado" - }, - "pool": { - "created": "Pool de Quotas Criado", - "deleted": "Pool de Quotas Eliminado", - "updated": "Pool de Quotas Atualizado" - }, - "store": { - "driver_changed": "Driver do Armazenamento de Quotas Alterado" - } - }, - "server": { - "start": "Arranque do Servidor" - }, - "service": { - "reveal_api_key": "Chave de API do Serviço Revelada" - }, - "settings": { - "update": "Definições Atualizadas", - "update_failed": "Falha ao Atualizar Definições" - }, - "sync": { - "token": { - "created": "Token de Sincronização Criado", - "revoked": "Token de Sincronização Revogado" - } - } + "sync.token.revoked": "Sync Token Revoked" }, "mcpMetricCalls24h": "Chamadas (24h)", "mcpMetricSuccessRate": "Taxa de sucesso", @@ -1693,7 +1621,7 @@ "settingsGeneralDescription": "Storage, database, and general instance configuration", "settingsAppearanceDescription": "Tema, marca e personalização visual", "settingsAiDescription": "Comportamentos de IA, orçamentos de thinking, visão e definições de memória", - "settingsCacheDescription": "__MISSING__:TTL for model catalog cache entries", + "settingsCacheDescription": "TTL para entradas de cache do catálogo de modelos", "settingsSecurityDescription": "Definições de autenticação, autorização e controlo de acesso", "featureFlags": "Sinalizadores de recursos", "featureFlagsDescription": "Capacidades do sistema de controle e recursos experimentais", @@ -2724,14 +2652,14 @@ "auto": "Automático", "always": "Sempre" }, - "ccDiscoveryInfoButton": "__MISSING__:How to enable discovery in Claude Code", - "ccDiscoveryInfoTooltip": "__MISSING__:Advertise non-Claude models under claude/<provider>/<model> mirror ids so Claude Code's gateway model discovery can list them. Doubles catalog entries for all clients when enabled globally.", - "ccDiscoveryInfoLink": "__MISSING__:Open Feature Flags", - "ccOnboardingTitle": "__MISSING__:settings.json for gateway model discovery", - "ccOnboardingCopy": "__MISSING__:Copy", - "ccOnboardingCopied": "__MISSING__:Copied", - "ccOnboardingKeyPlaceholder": "__MISSING__:", - "ccOnboardingWindowNote": "__MISSING__:Claude Code assumes a 200K context window for any model id it does not recognize. For a model with a different real window, add CLAUDE_CODE_AUTO_COMPACT_WINDOW just under it so auto-compaction does not fire too early.", + "ccDiscoveryInfoButton": "Como ativar a descoberta no Claude Code", + "ccDiscoveryInfoTooltip": "Anuncie modelos não-Claude sob claude/<provider>/<model> IDs de espelho para que a descoberta de modelos do gateway do Claude Code possa listá-los. Dobra as entradas do catálogo para todos os clientes quando ativado globalmente.", + "ccDiscoveryInfoLink": "Abrir Feature Flags", + "ccOnboardingTitle": "settings.json para descoberta do modelo de gateway", + "ccOnboardingCopy": "Copiar", + "ccOnboardingCopied": "Copiado", + "ccOnboardingKeyPlaceholder": "", + "ccOnboardingWindowNote": "Claude Code assume uma janela de contexto de 200K para qualquer ID de modelo que não reconhece. Para um modelo com uma janela real diferente, adicione CLAUDE_CODE_AUTO_COMPACT_WINDOW logo abaixo para que a auto-compacção não seja acionada muito cedo.", "failedSave": "Falha ao guardar", "profileSyncTitle": "Sincronização automática de perfis da CLI", "profileSyncDescription": "Após a sincronização dos modelos do fornecedor, regenerar automaticamente os perfis de ferramentas da CLI a partir do catálogo ativo. Desativado por predefinição — apenas os ficheiros de perfil são escritos; a configuração ativa/predefinida nunca é alterada.", @@ -3983,7 +3911,7 @@ "modelsCount": "{count, plural, one {# modelo} other {# modelos}}", "sectionTitle": "Superfície de Integração", "sectionDescription": "APIs compatíveis com OpenAI e endpoints de protocolo operacional", - "tabApis": "__MISSING__:APIs", + "tabApis": "APIs", "tabProtocols": "Protocolos", "tabsAria": "Secções de endpoint", "protocolsTitle": "Protocolos", @@ -5499,18 +5427,18 @@ "interceptFetchHint": "Reescrever chamadas de ferramentas nativas web_fetch para o /v1/web/fetch do OmniRoute.", "interceptionLoadError": "Falha ao carregar as definições de interceção: {error}", "interceptionSaveError": "Falha ao guardar as definições de interceção: {error}", - "ccAliasSectionTitle": "__MISSING__:Expose in Claude Code (claude/…)", - "ccAliasSectionHint": "__MISSING__:Advertise this provider's models under claude/<provider>/<model> mirror ids so Claude Code's gateway model discovery can list them. Off by default — enabling this doubles catalog entries for all clients.", - "ccAliasProviderLevelLabel": "__MISSING__:Provider default", - "ccAliasModelOverridesLabel": "__MISSING__:Per-model overrides", - "ccAliasModelOverrideAriaLabel": "__MISSING__:Override for {modelId}", - "ccAliasStateInherit": "__MISSING__:Inherit", - "ccAliasStateOn": "__MISSING__:On", - "ccAliasStateOff": "__MISSING__:Off", - "ccAliasAddModelPlaceholder": "__MISSING__:Model id (e.g. gpt-4o)", - "ccAliasAddModelButton": "__MISSING__:Add override", - "ccAliasLoadError": "__MISSING__:Failed to load discovery-alias settings: {error}", - "ccAliasSaveError": "__MISSING__:Failed to save discovery-alias setting: {error}", + "ccAliasSectionTitle": "Expose em Claude Code (claude/…)", + "ccAliasSectionHint": "Anuncie os modelos deste fornecedor sob claude/<provider>/<model> IDs de espelho para que a descoberta de modelos do gateway do Claude Code os possa listar. Desativado por padrão — ativar isto duplica as entradas do catálogo para todos os clientes.", + "ccAliasProviderLevelLabel": "Fornecedor padrão", + "ccAliasModelOverridesLabel": "Substituições por modelo", + "ccAliasModelOverrideAriaLabel": "Substituição para {modelId}", + "ccAliasStateInherit": "Herdar", + "ccAliasStateOn": "Ligado", + "ccAliasStateOff": "Desligado", + "ccAliasAddModelPlaceholder": "Id do modelo (ex: gpt-4o)", + "ccAliasAddModelButton": "Adicionar substituição", + "ccAliasLoadError": "Falha ao carregar as definições de discovery-alias: {error}", + "ccAliasSaveError": "Falha ao salvar a configuração discovery-alias: {error}", "compatUpstreamHeadersLabel": "Cabeçalhos upstream extra", "compatUpstreamHeadersHint": "Definição de alto privilégio — mesmo nível de confiança que editar credenciais de API do fornecedor; só admins de confiança devem usar.", "compatUpstreamHeaderName": "Nome do cabeçalho", @@ -5746,8 +5674,8 @@ "t3ChatWebCookieHint": "Abra t3.chat → DevTools → Aplicativo → Armazenamento local → https://t3.chat, copie 'convex-session-id'. Em seguida, abra DevTools → Rede, copie o cabeçalho completo do cookie de qualquer solicitação de chat. Cole os dois valores nos campos abaixo.", "t3ChatWebCookiePlaceholder": "id-de-sessão-convexa=abc123...", "grokWebCookieHint": "Dica de Cookie Web do Grok", - "blockClaudeExtraUsageDescription": "__MISSING__:When enabled, OmniRoute marks this Claude connection unavailable as soon as the usage API reports queued extra usage, so fallback switches to another connection instead of continuing on pay-as-you-go extra billing.", - "blockClaudeExtraUsageLabel": "__MISSING__:Block extra Claude usage", + "blockClaudeExtraUsageDescription": "Quando ativado, o OmniRoute marca esta conexão Claude como indisponível assim que a API de utilização reporta utilização extra em fila, para que a alternativa mude para outra conexão em vez de continuar com a faturação extra pay-as-you-go.", + "blockClaudeExtraUsageLabel": "Bloquear uso extra do Claude", "disableCoolingDescription": "Ignorar o cooldown transitório para que esta ligação permaneça elegível mesmo após erros recuperáveis (estados terminais como banido/expirado continuam a aplicar-se).", "disableCoolingLabel": "Desativar cooldown para esta ligação", "bulkPasteAdded": "{count, plural, one {1 chave adicionada} other {# chaves adicionadas}}", @@ -5934,13 +5862,13 @@ "importGrokAuth": "Importar autenticação do Grok Build", "zedImportTitle": "Importar do Porta-chaves do Zed", "zedImportDescription": "Detetar credenciais de fornecedores de IA (OpenAI, Anthropic, Google, Mistral, xAI) guardadas pelo Zed IDE no porta-chaves do SO e importá-las como ligações. O Zed IDE tem de estar instalado nesta máquina.", - "zedImportButton": "__MISSING__:Import from Zed", - "zedImportFailed": "__MISSING__:Zed import failed", + "zedImportButton": "Importar de Zed", + "zedImportFailed": "Falha na importação do Zed", "zedImportHint": "Dica de Importação do Zed", "zedImportNetworkError": "Erro de Rede na Importação do Zed", "zedImportNone": "Sem Importação do Zed", - "zedImportSuccess": "__MISSING__:Imported {credentials} credential(s) from Zed for {providers} provider(s)", - "zedImporting": "__MISSING__:Importing…", + "zedImportSuccess": "Importou {credentials} credencial(is) do Zed para {providers} fornecedor(es)", + "zedImporting": "A Importar…", "zedNoCredentials": "Nenhuma credencial do Zed encontrada no porta-chaves", "zedUnsupportedCredentials": "Encontradas {count} credenciais no porta-chaves, mas nenhuma corresponde aos fornecedores suportados", "zedManualTitle": "Importação manual de token", @@ -6090,7 +6018,7 @@ "bailian-coding-plan": "Ligue o Alibaba Coding Plan com uma chave de API.", "bedrock": "Integração nativa com o Bedrock: a descoberta de modelos utiliza os modelos de fundação e perfis de inferência do Bedrock, enquanto o chat utiliza as APIs regionais Converse/ConverseStream do Bedrock Runtime.", "anthropic": "Ligue a Anthropic com uma chave de API.", - "ant-ling": "__MISSING__:Register and create an API key at the Ant Ling API console (https://chat.ant-ling.com/open), then paste it here. OmniRoute routes chat traffic to https://api.ant-ling.com/v1/chat/completions; the provider is OpenAI-compatible and also exposes an Anthropic-compatible surface.", + "ant-ling": "Registe-se e crie uma chave de API no console da API Ant Ling (https://chat.ant-ling.com/open), depois cole-a aqui. O OmniRoute direciona o tráfego de chat para https://api.ant-ling.com/v1/chat/completions; o fornecedor é compatível com OpenAI e também expõe uma interface compatível com Anthropic.", "api-airforce": "Obtenha a sua chave de API em https://panel.api.airforce — endpoint compatível com a OpenAI em https://api.airforce/v1", "arcee-ai": "Obtenha a chave de API em arcee.ai", "azure-ai": "O Foundry utiliza a superfície v1 da OpenAI com nomes de implementação como modelos. O OmniRoute normaliza os URLs de recursos raiz para os endpoints v1 chat e /models.", @@ -6111,7 +6039,7 @@ "chutes": "Chave de API Bearer para o gateway compatível com OpenAI da Chutes.", "clarifai": "O Clarifai expõe chat, respostas e /models compatíveis com OpenAI em /v2/ext/openai/v1. Os modelos públicos/da comunidade requerem normalmente um PAT; as chaves com âmbito de aplicação só funcionam para recursos dentro dessa aplicação.", "cloudflare-ai": "Requer Token de API E ID de Conta (encontrados em dash.cloudflare.com)", - "clova-studio": "__MISSING__:CLOVA Studio (HyperCLOVA X) is OpenAI-compatible on /v1/openai. OmniRoute probes /v1/openai/models and routes chat traffic to /v1/openai/chat/completions. Uses the current clovastudio.stream.ntruss.com host — the legacy clovastudio.apigw.ntruss.com endpoint is being deprecated.", + "clova-studio": "O CLOVA Studio (HyperCLOVA X) é compatível com OpenAI em /v1/openai. O OmniRoute interroga /v1/openai/models e direciona o tráfego de chat para /v1/openai/chat/completions. Utiliza o host atual clovastudio.stream.ntruss.com — o endpoint legado clovastudio.apigw.ntruss.com está a ser descontinuado.", "codestral": "Ligue o Codestral com uma chave de API.", "cohere": "Avaliação gratuita: 1.000 chamadas de API/mês para testes, sem necessidade de cartão de crédito", "command-code": "Crie ou copie uma chave de API do Command Code e, em seguida, cole-a aqui como um token Bearer.", @@ -6155,9 +6083,9 @@ "watsonx": "O gateway de modelos watsonx expõe /chat/completions e /models compatíveis com a OpenAI em /ml/gateway/v1.", "ideogram": "Obtenha a chave de API em ideogram.ai/docs/api", "iflytek": "Obtenha a chave de API em console.xfyun.cn", - "inception": "__MISSING__:Inception Labs is OpenAI-compatible at https://api.inceptionlabs.ai/v1. mercury-2 is the first diffusion LLM (dLLM) in the catalog — 5-10x faster generation than comparable autoregressive models, with tool calling, json_mode, and structured outputs.", + "inception": "Inception Labs é compatível com OpenAI em https://api.inceptionlabs.ai/v1. mercury-2 é o primeiro LLM de difusão (dLLM) no catálogo — geração 5-10x mais rápida do que modelos autoregressivos comparáveis, com chamada de ferramentas, json_mode e saídas estruturadas.", "inference-net": "$25 em créditos gratuitos no registo, além de bolsas de investigação disponíveis", - "internlm": "__MISSING__:Free monthly quota ~1M input / 3M output tokens (~10 RPM)", + "internlm": "Quota mensal gratuita ~1M de tokens de entrada / 3M de tokens de saída (~10 RPM)", "jina-ai": "Chave de API Bearer para a API de rerank da Jina AI.", "jina-reader": "Ligue o Jina Reader com uma chave de API.", "kenari": "O Kenari expõe um endpoint de conclusões de chat compatível com a OpenAI em https://kenari.id/v1/chat/completions, além de um catálogo /v1/models em tempo real que abrange Claude, GPT, DeepSeek, GLM, Kimi e muito mais. O OmniRoute utiliza o protocolo OpenAI e lista modelos via passthrough.", @@ -6204,7 +6132,7 @@ "perplexity": "Ligue a Perplexity com uma chave de API.", "piapi": "Ligue a PiAPI com uma chave de API.", "pioneer": "$75 em créditos de utilização gratuitos — sem necessidade de cartão de crédito", - "plamo": "__MISSING__:PLaMo is OpenAI-compatible at https://api.platform.preferredai.jp/v1. Built by Preferred Networks and optimized for Japanese. Docs are primarily in Japanese.", + "plamo": "PLaMo é compatível com OpenAI em https://api.platform.preferredai.jp/v1. Construído pela Preferred Networks e otimizado para japonês. A documentação está principalmente em japonês.", "poe": "O Poe expõe chat e responses compatíveis com a OpenAI em https://api.poe.com/v1, com verificações de saldo autenticadas em /usage/current_balance.", "pollinations": "Nível gratuito sem chave: openai, openai-fast, openai-large, qwen-coder, mistral, deepseek, grok, gemini-flash-lite-3.1, perplexity-fast, perplexity-reasoning. Os modelos premium (claude, gemini, midijourney) requerem uma chave de API da Pollinations de enter.pollinations.ai.", "publicai": "Requer uma chave de API — crédito único no registo, depois pago", @@ -6215,7 +6143,7 @@ "runwayml": "A geração de vídeo da Runway é baseada em tarefas. O OmniRoute submete tarefas de texto para vídeo ou imagem para vídeo, consulta /v1/tasks/[id] e normaliza as saídas de vídeo concluídas de volta para a resposta /v1/videos/generations semelhante à da OpenAI.", "sambanova": "$5 em créditos gratuitos no registo (validade de 30 dias), sem necessidade de cartão de crédito", "sap": "A descoberta de modelos utiliza /v2/lm/scenarios/foundation-models/models em AI_API_URL. Os pedidos de chat utilizam deploymentUrl/chat/completions e requerem AI-Resource-Group.", - "sarvam": "__MISSING__:Sarvam AI is OpenAI-compatible on /v1. OmniRoute probes /v1/models and routes chat traffic to /v1/chat/completions. Models are tuned for Indic languages.", + "sarvam": "Sarvam AI é compatível com OpenAI em /v1. OmniRoute investiga /v1/models e direciona o tráfego de chat para /v1/chat/completions. Os modelos são ajustados para línguas índicas.", "scaleway": "1M de tokens gratuitos para novas contas — em conformidade com a UE/RGPD (Paris), Qwen3 235B e Llama 70B", "sensenova": "Obtenha a chave de API em platform.sensenova.cn", "siliconflow": "$1 em créditos gratuitos mais modelos permanentemente gratuitos após verificação de identidade", @@ -6232,7 +6160,7 @@ "together": "Ligue a Together AI com uma chave de API.", "tokenrouter": "O TokenRouter expõe um endpoint de chat completions compatível com a OpenAI em https://api.tokenrouter.com/v1/chat/completions, além de um catálogo /v1/models funcional. O OmniRoute utiliza o protocolo OpenAI.", "topaz": "Ligue a Topaz com uma chave de API.", - "typhoon": "__MISSING__:Typhoon is OpenAI-compatible on /v1. Built by SCB 10X (Thailand); typhoon-v2.5-30b-a3b-instruct is a thai-first, multilingual model.", + "typhoon": "Typhoon é compatível com OpenAI em /v1. Construído pela SCB 10X (Tailândia); typhoon-v2.5-30b-a3b-instruct é um modelo multilíngue com foco na Tailândia.", "udio": "Cole o cookie de sessão de udio.com (autenticação Supabase)", "uncloseai": "Nenhuma autenticação necessária. A API aceita qualquer string não vazia como chave para identificação.", "upstage": "Ligue a Upstage com uma chave de API.", @@ -6245,7 +6173,7 @@ "voyage-ai": "Chave de API Bearer para as APIs de embeddings e rerank da Voyage AI.", "wafer": "Chave de API de https://wafer.ai", "wandb": "Ligue o Weights & Biases Inference com uma chave de API.", - "writer": "__MISSING__:Writer Palmyra is OpenAI-compatible at https://api.writer.com/v1. palmyra-x5 offers a 1M-token context window.", + "writer": "Writer Palmyra é compatível com OpenAI em https://api.writer.com/v1. palmyra-x5 oferece uma janela de contexto de 1M tokens.", "x5lab": "O X5Lab expõe um endpoint de chat completions compatível com a OpenAI em https://api.x5lab.dev/v1/chat/completions, além de um catálogo /v1/models em tempo real. O OmniRoute utiliza o protocolo OpenAI e lista modelos via passthrough.", "xai": "Ligue a xAI (Grok) com uma chave de API.", "xiaomi-mimo": "Ligue a Xiaomi MiMo com uma chave de API.", @@ -6502,18 +6430,18 @@ "requestBodyLimitSaving": "A guardar...", "requestBodyLimitSave": "Guardar", "requestBodyLimitCurrent": "Atual: {value}", - "cacheConfigLoadFailed": "__MISSING__:Failed to load cache settings", - "cacheConfigSaveSuccess": "__MISSING__:Cache settings saved", - "cacheConfigSaveFailed": "__MISSING__:Failed to save cache settings", - "modelCatalogTtlWholeNumberError": "__MISSING__:Use a whole number", - "modelCatalogTtlMinimumError": "__MISSING__:Minimum is {min} ms", - "modelCatalogTtlMaximumError": "__MISSING__:Maximum is {max} ms", - "modelCatalogCacheTtl": "__MISSING__:Model Catalog Cache TTL", - "modelCatalogCacheTtlDescription": "__MISSING__:How long model catalog responses are cached before refreshing", - "modelCatalogCacheTtlLabel": "__MISSING__:Model catalog cache TTL in milliseconds", - "modelCatalogCacheTtlSaving": "__MISSING__:Saving...", - "modelCatalogCacheTtlSave": "__MISSING__:Save", - "modelCatalogCacheTtlCurrent": "__MISSING__:Current: {value} ms", + "cacheConfigLoadFailed": "Falha ao carregar as definições de cache", + "cacheConfigSaveSuccess": "Configurações de cache guardadas", + "cacheConfigSaveFailed": "Falha ao guardar as definições de cache", + "modelCatalogTtlWholeNumberError": "Utilize um número inteiro", + "modelCatalogTtlMinimumError": "O mínimo é {min} ms", + "modelCatalogTtlMaximumError": "O máximo é {max} ms", + "modelCatalogCacheTtl": "Tempo de Vida do Cache do Catálogo de Modelos", + "modelCatalogCacheTtlDescription": "Quanto tempo as respostas do catálogo de modelos são armazenadas em cache antes de serem atualizadas", + "modelCatalogCacheTtlLabel": "TTL do cache do catálogo de modelos em milissegundos", + "modelCatalogCacheTtlSaving": "A Guardar...", + "modelCatalogCacheTtlSave": "Guardar", + "modelCatalogCacheTtlCurrent": "Atual: {value} ms", "mitmProxy": "Proxy MITM", "pricing": "Preços", "storage": "Armazenamento", @@ -6844,7 +6772,7 @@ "denoRelayOrgDomainRequired": "O domínio da organização é obrigatório", "denoRelayDeployFailed": "Falha no Deno Deploy", "denoRelayTokenHint": "Token de organização (prefixo ddo_) de console.deno.com → Organização → Definições → Tokens de Organização. Usado uma vez para o deploy e nunca armazenado.", - "denoRelayOrgDomainHint": "O domínio predefinido da sua organização do Deno Deploy (ex. acme.deno.net). O relay estará acessível em https://..deno.net.", + "denoRelayOrgDomainHint": "O domínio predefinido da sua organização do Deno Deploy (ex. acme.deno.net). O relay estará acessível em https://<app-name>.<org-slug>.deno.net.", "proxyFreePoolFilterProtocol": "Filtrar por protocolo", "proxyFreePoolProtocol": "Protocolo", "proxyFreePoolCountryPlaceholder": "País (ex. US)", @@ -6893,8 +6821,17 @@ "chars": "{count} caracteres", "thinkingBudgetTitle": "Pensando no orçamento", "thinkingBudgetDesc": "Controle o uso do token de raciocínio de IA em todas as solicitações", + "thinkingBudgetIndependenceHint": "Os recursos de compressão, roteamento e limite de tokens continuam a funcionar em todos os modos. Auto não significa \"auto-exibir raciocínio\" — remove os campos de raciocínio do cliente.", "passthrough": "Passagem", "passthroughDesc": "Sem alterações – o cliente controla o orçamento pensado", + "thinkingModePassthrough": "Passagem direta", + "thinkingModePassthroughDesc": "Deixe o raciocínio do cliente inalterado (esforço, resumo, blocos de pensamento). Necessário para o pensamento visível do Codex/Desktop. Padrão.", + "thinkingModeAuto": "Auto (strip)", + "thinkingModeAutoDesc": "Remova todos os campos de pensamento/razão do cliente (razão, esforço_de_razão, pensamento Claude, configuração_de_pensamento Gemini) e deixe o fornecedor inventar padrões. Pode ocultar painéis de pensamento e interromper solicitações de resumo do cliente.", + "thinkingModeCustom": "Personalizado", + "thinkingModeCustomDesc": "Substitua cada pedido por um orçamento fixo de token de pensamento que você define abaixo.", + "thinkingModeAdaptive": "Adaptável", + "thinkingModeAdaptiveDesc": "Escalar o orçamento de pensamento a partir de um esforço base utilizando a contagem de mensagens, ferramentas e comprimento do prompt.", "auto": "Combo Automático", "autoDesc": "Pool de roteamento inteligente (Otimizado)", "custom": "Personalizado", @@ -7239,7 +7176,7 @@ "howPricingWorks": "Como funciona o preço", "cacheWrite": "Gravação em cache", "unsaved": "não salvo", - "resetDefaults": "__MISSING__:Reset defaults", + "resetDefaults": "Restaurar predefinições", "saveProvider": "Salvar provedor", "model": "Modelo", "models": "modelos", @@ -7419,13 +7356,13 @@ "compressionPreserveSystemNever": "Nunca", "compressionLiveZoneTitle": "Zona Ativa alinhada com a cache", "compressionLiveZoneDesc": "Manter o prefixo de conversa comprimido estável e processar apenas os itens recém-adicionados.", - "compressionExclusionsTitle": "__MISSING__:Compression Exclusions", - "compressionExclusionsDesc": "__MISSING__:Model ids or provider/model patterns that must never be compressed. `*` is the only wildcard (e.g. `openai/*`, `*embedding*`). A matching request passes through byte-identical — no compression engine runs.", - "compressionExclusionsPlaceholder": "__MISSING__:One pattern per line, e.g.\nopenai/text-embedding-3-large\nanthropic/*", - "compressionExclusionsSave": "__MISSING__:Save", - "compressionExclusionsSaved": "__MISSING__:Saved", - "compressionExclusionsCount": "__MISSING__:{count, plural, one {# exclusion} other {# exclusions}} configured", - "compressionExclusionsEmpty": "__MISSING__:No exclusions configured — every model/endpoint is eligible for compression (default behavior).", + "compressionExclusionsTitle": "Exclusões de Compressão", + "compressionExclusionsDesc": "IDs de modelo ou padrões de fornecedor/modelo que nunca devem ser comprimidos. `*` é o único caractere curinga (por exemplo, `openai/*`, `*embedding*`). Um pedido correspondente passa por byte-idêntico — nenhum motor de compressão é executado.", + "compressionExclusionsPlaceholder": "Um padrão por linha, por exemplo: \nopenai/text-embedding-3-large \nanthropic/*", + "compressionExclusionsSave": "Guardar", + "compressionExclusionsSaved": "Guardado", + "compressionExclusionsCount": "{count, plural, one {# exclusão} other {# exclusões}} configuradas", + "compressionExclusionsEmpty": "Sem exclusões configuradas — todos os modelos/pontos finais são elegíveis para compressão (comportamento padrão).", "compressionCavemanConfig": "Configuração do Motor Caveman", "compressionCavemanConfigDesc": "Afina o motor de compressão baseado em regras", "compressionCavemanPanelHint": "O seu estado (ligado/desligado) e nível são definidos no painel:", @@ -8218,16 +8155,7 @@ "cliproxyapiHealth": "Saúde", "cliproxyapiPort": "Porto", "qdrantHost": "Anfitrião", - "qdrantCollection": "Coleção", - "thinkingBudgetIndependenceHint": "__MISSING__:Compression, routing, and token-limit features keep working in every mode. Auto does not mean “auto-show thinking” — it strips client reasoning fields.", - "thinkingModePassthrough": "__MISSING__:Passthrough", - "thinkingModePassthroughDesc": "__MISSING__:Leave client reasoning unchanged (effort, summary, thinking blocks). Required for Codex/Desktop visible thinking. Default.", - "thinkingModeAuto": "__MISSING__:Auto (strip)", - "thinkingModeAutoDesc": "__MISSING__:Strip all client thinking/reasoning fields (reasoning, reasoning_effort, Claude thinking, Gemini thinking_config) and let the provider invent defaults. Can hide thinking panels and break client summary requests.", - "thinkingModeCustom": "__MISSING__:Custom", - "thinkingModeCustomDesc": "__MISSING__:Overwrite every request with a fixed thinking token budget you set below.", - "thinkingModeAdaptive": "__MISSING__:Adaptive", - "thinkingModeAdaptiveDesc": "__MISSING__:Scale thinking budget from a base effort using message count, tools, and prompt length." + "qdrantCollection": "Coleção" }, "contextRtk": { "title": "Motor RTK", @@ -10533,23 +10461,23 @@ "deviceCodeVerificationUrl": "URL de verificação", "deviceCodeYourCode": "Seu código", "deviceCodeWaiting": "Aguardando autorização...", - "googleLoopbackTitle": "__MISSING__:Google sign-in can't complete from this address", - "googleLoopbackWhatHappens": "__MISSING__:Google only releases the authorization code once {redirectUri} is reachable from the browser that approves the sign-in. Here that address points at this computer, not at the OmniRoute server — so the consent screen hangs instead of redirecting, and there is no callback URL to copy.", - "googleLoopbackRecommended": "__MISSING__:Recommended — run this on your own computer, then paste the result below:", - "googleLoopbackHelperNote": "__MISSING__:It opens the Google consent locally (where 127.0.0.1 works) and prints a one-line omniroute-cred-v1.… blob. Paste that blob into the Step 2 field below — it accepts a credential blob as well as a callback URL.", - "googleLoopbackTunnelLabel": "__MISSING__:Or forward the dashboard port over SSH and reload OmniRoute through the tunnel:", - "googleLoopbackTunnelNote": "__MISSING__:Replace {userPlaceholder} with your SSH username, keep the terminal open, then open {localUrl} and connect again from there.", - "googleLoopbackHeadlessAlt": "__MISSING__:For fully headless use with no local callback at all, configure your own Google OAuth credentials plus a public base URL.", + "googleLoopbackTitle": "O início de sessão do Google não pode ser concluído a partir deste endereço", + "googleLoopbackWhatHappens": "O Google só libera o código de autorização uma vez que {redirectUri} é acessível a partir do navegador que aprova o início de sessão. Aqui, esse endereço aponta para este computador, não para o servidor OmniRoute — por isso, a tela de consentimento fica pendurada em vez de redirecionar, e não há URL de callback para copiar.", + "googleLoopbackRecommended": "Recomendado — execute isto no seu próprio computador e cole o resultado abaixo:", + "googleLoopbackHelperNote": "Abre o consentimento do Google localmente (onde 127.0.0.1 funciona) e imprime um blob omniroute-cred-v1.… de uma linha. Cole esse blob no campo da Etapa 2 abaixo — aceita um blob de credencial, bem como uma URL de callback.", + "googleLoopbackTunnelLabel": "Ou encaminhe a porta do painel através do SSH e recarregue o OmniRoute através do túnel:", + "googleLoopbackTunnelNote": "Substitua {userPlaceholder} pelo seu nome de utilizador SSH, mantenha o terminal aberto, depois abra {localUrl} e conecte-se novamente a partir daí.", + "googleLoopbackHeadlessAlt": "Para utilização totalmente sem cabeça, sem qualquer callback local, configure as suas próprias credenciais do Google OAuth e uma URL base pública.", "remoteAccessInfo": "Acesso remoto: Como você está acessando o OmniRoute remotamente, após a autorização você verá uma página de erro (localhost não encontrado). Isso é normal – basta copiar o URL completo da barra de endereço do seu navegador e colá-lo abaixo.", - "loopbackMismatchTitle": "__MISSING__:Sign-in can't complete from this address", - "loopbackMismatchWhatHappened": "__MISSING__:What's happening", - "loopbackMismatchExplanation": "__MISSING__:After you approve the login, {providerName} always sends the browser back to {redirectUri}. That address points at the computer running this browser, not at the OmniRoute server — so the authorization code never reaches OmniRoute and the provider fails the sign-in without showing an error.", - "loopbackMismatchHowToFix": "__MISSING__:How to fix it", - "loopbackMismatchStep1": "__MISSING__:On this computer, open a terminal and start an SSH tunnel to the OmniRoute server:", - "loopbackMismatchStep1Note": "__MISSING__:Replace {userPlaceholder} with your SSH username. Keep this terminal open until the connection shows as active — both ports are needed: one serves the dashboard, the other receives the callback.", - "loopbackMismatchStep2": "__MISSING__:In this browser, reopen OmniRoute through the tunnel:", - "loopbackMismatchStep3": "__MISSING__:Then connect {providerName} again from the new tab. The callback now reaches the server and the login completes normally.", - "loopbackMismatchAlternative": "__MISSING__:No SSH access? If this provider offers a token import tab, connect with a token instead — that path doesn't use a loopback callback.", + "loopbackMismatchTitle": "O início de sessão não pode ser concluído a partir deste endereço", + "loopbackMismatchWhatHappened": "O que está a acontecer", + "loopbackMismatchExplanation": "Depois de aprovar o login, {providerName} envia sempre o navegador de volta para {redirectUri}. Esse endereço aponta para o computador que está a correr este navegador, não para o servidor OmniRoute — por isso, o código de autorização nunca chega ao OmniRoute e o provedor falha o login sem mostrar um erro.", + "loopbackMismatchHowToFix": "Como corrigir isso", + "loopbackMismatchStep1": "Neste computador, abra um terminal e inicie um túnel SSH para o servidor OmniRoute:", + "loopbackMismatchStep1Note": "Substitua {userPlaceholder} pelo seu nome de utilizador SSH. Mantenha este terminal aberto até a conexão aparecer como ativa — ambas as portas são necessárias: uma serve o painel, a outra recebe o callback.", + "loopbackMismatchStep2": "Neste navegador, reabra o OmniRoute através do túnel:", + "loopbackMismatchStep3": "Em seguida, conecte {providerName} novamente a partir da nova aba. O callback agora chega ao servidor e o login é concluído normalmente.", + "loopbackMismatchAlternative": "Sem acesso SSH? Se este fornecedor oferecer uma aba de importação de token, conecte-se com um token em vez disso — esse caminho não utiliza um callback de loopback.", "step1OpenUrl": "Etapa 1: abra este URL em seu navegador", "copy": "Copiar", "step2PasteCallback": "Etapa 2: cole o URL de retorno de chamada ou o código de autorização aqui", @@ -12630,7 +12558,7 @@ "danger": "Perigo", "requiresRestart": "Requer reinício", "source": "Origem", - "ccDiscoveryAliasesEnvWarning": "__MISSING__:Active via environment variable (EXPOSE_CC_DISCOVERY_ALIASES) — this overrides any dashboard toggle below.", + "ccDiscoveryAliasesEnvWarning": "Ativo através da variável de ambiente (EXPOSE_CC_DISCOVERY_ALIASES) — isto substitui qualquer alternância de painel abaixo.", "resetFlag": "Repor {label} para a predefinição", "reset": "Repor", "loadFailed": "Falha ao carregar os sinalizadores de funcionalidades", @@ -13703,11 +13631,5 @@ "hint": "Quando ativado, os modelos descobertos aparecem nas seleções do provedor em todo o OmniRoute.", "updateFailed": "Falha ao atualizar (HTTP {status})", "networkError": "Erro de rede — não foi possível atualizar a configuração de exposição do fornecedor" - }, - "capabilityFilter": { - "visionMismatch": "O fornecedor não suporta visão para este pedido de imagem", - "toolsMismatch": "O fornecedor não suporta a chamada de ferramentas", - "structuredOutputMismatch": "O fornecedor não suporta saída estruturada", - "contextWindowMismatch": "A solicitação excede a janela de contexto do fornecedor" } -} \ No newline at end of file +} diff --git a/src/i18n/messages/ro.json b/src/i18n/messages/ro.json index 4647d24819..d0c93437d6 100644 --- a/src/i18n/messages/ro.json +++ b/src/i18n/messages/ro.json @@ -6821,8 +6821,17 @@ "chars": "{count} caractere", "thinkingBudgetTitle": "Gândirea bugetului", "thinkingBudgetDesc": "Controlați utilizarea simbolurilor de raționament AI pentru toate solicitările", + "thinkingBudgetIndependenceHint": "Funcțiile de compresie, rutare și limită de token-uri continuă să funcționeze în fiecare mod. Auto nu înseamnă „gândire auto-afişată” — elimină câmpurile de raționare ale clientului.", "passthrough": "trecere", "passthroughDesc": "Fără modificări — clientul controlează bugetul de gândire", + "thinkingModePassthrough": "Passthrough", + "thinkingModePassthroughDesc": "Lăsați raționamentul clientului neschimbat (efort, rezumat, blocuri de gândire). Necesare pentru gândirea vizibilă Codex/Desktop. Implicit.", + "thinkingModeAuto": "Auto (strip)", + "thinkingModeAutoDesc": "Elimină toate câmpurile de gândire/raționare ale clientului (raționare, efort_raționare, gândirea Claude, gândirea Gemini_config) și lasă furnizorul să inventeze valori implicite. Poate ascunde panourile de gândire și poate întrerupe cererile de sumarizare ale clientului.", + "thinkingModeCustom": "Personalizat", + "thinkingModeCustomDesc": "Suprascrie fiecare cerere cu un buget fix de tokeni de gândire pe care îl stabilești mai jos.", + "thinkingModeAdaptive": "Adaptiv", + "thinkingModeAdaptiveDesc": "Scalarea bugetului de gândire de la un efort de bază folosind numărul de mesaje, instrumente și lungimea promptului.", "auto": "Auto", "autoDesc": "Eliminați toate configurațiile de gândire - lăsați furnizorul să decidă", "custom": "Personalizat", @@ -8146,16 +8155,7 @@ "cliproxyapiHealth": "Sănătate", "cliproxyapiPort": "Port", "qdrantHost": "Gazdă", - "qdrantCollection": "Colecție", - "thinkingBudgetIndependenceHint": "__MISSING__:Compression, routing, and token-limit features keep working in every mode. Auto does not mean “auto-show thinking” — it strips client reasoning fields.", - "thinkingModePassthrough": "__MISSING__:Passthrough", - "thinkingModePassthroughDesc": "__MISSING__:Leave client reasoning unchanged (effort, summary, thinking blocks). Required for Codex/Desktop visible thinking. Default.", - "thinkingModeAuto": "__MISSING__:Auto (strip)", - "thinkingModeAutoDesc": "__MISSING__:Strip all client thinking/reasoning fields (reasoning, reasoning_effort, Claude thinking, Gemini thinking_config) and let the provider invent defaults. Can hide thinking panels and break client summary requests.", - "thinkingModeCustom": "__MISSING__:Custom", - "thinkingModeCustomDesc": "__MISSING__:Overwrite every request with a fixed thinking token budget you set below.", - "thinkingModeAdaptive": "__MISSING__:Adaptive", - "thinkingModeAdaptiveDesc": "__MISSING__:Scale thinking budget from a base effort using message count, tools, and prompt length." + "qdrantCollection": "Colecție" }, "contextRtk": { "title": "RTK Engine", diff --git a/src/i18n/messages/ru.json b/src/i18n/messages/ru.json index 63eb532891..86be068570 100644 --- a/src/i18n/messages/ru.json +++ b/src/i18n/messages/ru.json @@ -6821,8 +6821,17 @@ "chars": "{count} символов", "thinkingBudgetTitle": "Думая о бюджете", "thinkingBudgetDesc": "Контролируйте использование токенов рассуждения ИИ во всех запросах", + "thinkingBudgetIndependenceHint": "Функции сжатия, маршрутизации и ограничения токенов продолжают работать в каждом режиме. Авто не означает «авто-показ мышления» — он удаляет поля рассуждений клиента.", "passthrough": "Сквозное прохождение", "passthroughDesc": "Никаких изменений — клиент контролирует продуманный бюджет", + "thinkingModePassthrough": "Пропускной режим", + "thinkingModePassthroughDesc": "Оставить обоснование клиента без изменений (усилия, резюме, блоки мышления). Обязательно для видимого мышления Codex/Desktop. По умолчанию.", + "thinkingModeAuto": "Авто (строка)", + "thinkingModeAutoDesc": "Удалите все поля мышления/рассуждения клиента (reasoning, reasoning_effort, Claude thinking, Gemini thinking_config) и позвольте провайдеру придумать значения по умолчанию. Можно скрыть панели мышления и нарушить запросы на сводку клиента.", + "thinkingModeCustom": "Пользовательский", + "thinkingModeCustomDesc": "Перезапишите каждый запрос с фиксированным бюджетом токенов на мышление, который вы установили ниже.", + "thinkingModeAdaptive": "Адаптивный", + "thinkingModeAdaptiveDesc": "Масштабируйте бюджет на мышление от базовых усилий, используя количество сообщений, инструменты и длину подсказки.", "auto": "Авто", "autoDesc": "Удалите всю конфигурацию мышления — пусть решает провайдер", "custom": "Пользовательский", @@ -8146,16 +8155,7 @@ "cliproxyapiHealth": "Здоровье", "cliproxyapiPort": "Порт", "qdrantHost": "Хост", - "qdrantCollection": "Коллекция", - "thinkingBudgetIndependenceHint": "__MISSING__:Compression, routing, and token-limit features keep working in every mode. Auto does not mean “auto-show thinking” — it strips client reasoning fields.", - "thinkingModePassthrough": "__MISSING__:Passthrough", - "thinkingModePassthroughDesc": "__MISSING__:Leave client reasoning unchanged (effort, summary, thinking blocks). Required for Codex/Desktop visible thinking. Default.", - "thinkingModeAuto": "__MISSING__:Auto (strip)", - "thinkingModeAutoDesc": "__MISSING__:Strip all client thinking/reasoning fields (reasoning, reasoning_effort, Claude thinking, Gemini thinking_config) and let the provider invent defaults. Can hide thinking panels and break client summary requests.", - "thinkingModeCustom": "__MISSING__:Custom", - "thinkingModeCustomDesc": "__MISSING__:Overwrite every request with a fixed thinking token budget you set below.", - "thinkingModeAdaptive": "__MISSING__:Adaptive", - "thinkingModeAdaptiveDesc": "__MISSING__:Scale thinking budget from a base effort using message count, tools, and prompt length." + "qdrantCollection": "Коллекция" }, "contextRtk": { "title": "RTK Engine", diff --git a/src/i18n/messages/sk.json b/src/i18n/messages/sk.json index 072704b676..de0085e0f6 100644 --- a/src/i18n/messages/sk.json +++ b/src/i18n/messages/sk.json @@ -6821,8 +6821,17 @@ "chars": "{count} znakov", "thinkingBudgetTitle": "Myslenie na rozpočet", "thinkingBudgetDesc": "Ovládajte používanie tokenu uvažovania AI vo všetkých požiadavkách", + "thinkingBudgetIndependenceHint": "Funkcie kompresie, smerovania a limitu tokenov fungujú vo všetkých režimoch. Auto neznamená „auto-zobrazenie myslenia“ — odstraňuje polia klientskeho uvažovania.", "passthrough": "Passthrough", "passthroughDesc": "Žiadne zmeny – klient kontroluje rozpočet", + "thinkingModePassthrough": "Prechod", + "thinkingModePassthroughDesc": "Nezmeňte dôvod klienta (úsilie, zhrnutie, myšlienkové bloky). Povinné pre Codex/Desktop viditeľné myslenie. Predvolené.", + "thinkingModeAuto": "Auto (strip)", + "thinkingModeAutoDesc": "Odstráňte všetky polia myslenia/úvah klienta (úvaha, úsilie o úvahu, myslenie Claude, konfigurácia myslenia Gemini) a nechajte poskytovateľa vymyslieť predvolené hodnoty. Môžete skryť panely myslenia a prerušiť požiadavky na zhrnutie klienta.", + "thinkingModeCustom": "Vlastné", + "thinkingModeCustomDesc": "Prepisujte každú požiadavku s pevným rozpočtom na tokeny, ktorý nastavíte nižšie.", + "thinkingModeAdaptive": "Adaptívny", + "thinkingModeAdaptiveDesc": "Zvážte rozpočet na škálovanie na základe základného úsilia pomocou počtu správ, nástrojov a dĺžky výzvy.", "auto": "Auto", "autoDesc": "Odstráňte všetky konfigurácie myslenia - nechajte poskytovateľa rozhodnúť", "custom": "Vlastné", @@ -8146,16 +8155,7 @@ "cliproxyapiHealth": "Zdravie", "cliproxyapiPort": "Port", "qdrantHost": "Host", - "qdrantCollection": "Zbierka", - "thinkingBudgetIndependenceHint": "__MISSING__:Compression, routing, and token-limit features keep working in every mode. Auto does not mean “auto-show thinking” — it strips client reasoning fields.", - "thinkingModePassthrough": "__MISSING__:Passthrough", - "thinkingModePassthroughDesc": "__MISSING__:Leave client reasoning unchanged (effort, summary, thinking blocks). Required for Codex/Desktop visible thinking. Default.", - "thinkingModeAuto": "__MISSING__:Auto (strip)", - "thinkingModeAutoDesc": "__MISSING__:Strip all client thinking/reasoning fields (reasoning, reasoning_effort, Claude thinking, Gemini thinking_config) and let the provider invent defaults. Can hide thinking panels and break client summary requests.", - "thinkingModeCustom": "__MISSING__:Custom", - "thinkingModeCustomDesc": "__MISSING__:Overwrite every request with a fixed thinking token budget you set below.", - "thinkingModeAdaptive": "__MISSING__:Adaptive", - "thinkingModeAdaptiveDesc": "__MISSING__:Scale thinking budget from a base effort using message count, tools, and prompt length." + "qdrantCollection": "Zbierka" }, "contextRtk": { "title": "RTK Engine", diff --git a/src/i18n/messages/sv.json b/src/i18n/messages/sv.json index 654af00958..ece012880e 100644 --- a/src/i18n/messages/sv.json +++ b/src/i18n/messages/sv.json @@ -6821,8 +6821,17 @@ "chars": "{count} tecken", "thinkingBudgetTitle": "Tänkande budget", "thinkingBudgetDesc": "Kontrollera användningen av AI-resonemangstoken över alla förfrågningar", + "thinkingBudgetIndependenceHint": "Komprimering, routing och token-gränsfunktioner fortsätter att fungera i varje läge. Auto betyder inte \"auto-visar tänkande\" — det tar bort klientens resonemangsfält.", "passthrough": "Genomgång", "passthroughDesc": "Inga förändringar – kunden styr tankebudgeten", + "thinkingModePassthrough": "Genomgång", + "thinkingModePassthroughDesc": "Lämna klientens resonemang oförändrat (insats, sammanfattning, tankeblock). Krävs för Codex/Stationär synlighet. Standard.", + "thinkingModeAuto": "Auto (strip)", + "thinkingModeAutoDesc": "Ta bort alla fält för klientens tänkande/resonemang (resonemang, resonemang_insats, Claude tänkande, Gemini tänkande_config) och låt leverantören uppfinna standarder. Kan dölja tänkande paneler och bryta klientens sammanfattningsförfrågningar.", + "thinkingModeCustom": "Anpassad", + "thinkingModeCustomDesc": "Överskriv varje begäran med en fast tänkande tokenbudget som du ställer in nedan.", + "thinkingModeAdaptive": "Adaptiv", + "thinkingModeAdaptiveDesc": "Skala tänkande budget från en grundinsats med hjälp av meddelandekvot, verktyg och längd på uppmaning.", "auto": "Auto", "autoDesc": "Ta bort alla tankeinställningar – låt leverantören bestämma", "custom": "Anpassad", @@ -8146,16 +8155,7 @@ "cliproxyapiHealth": "Hälsa", "cliproxyapiPort": "Port", "qdrantHost": "Värd", - "qdrantCollection": "Samling", - "thinkingBudgetIndependenceHint": "__MISSING__:Compression, routing, and token-limit features keep working in every mode. Auto does not mean “auto-show thinking” — it strips client reasoning fields.", - "thinkingModePassthrough": "__MISSING__:Passthrough", - "thinkingModePassthroughDesc": "__MISSING__:Leave client reasoning unchanged (effort, summary, thinking blocks). Required for Codex/Desktop visible thinking. Default.", - "thinkingModeAuto": "__MISSING__:Auto (strip)", - "thinkingModeAutoDesc": "__MISSING__:Strip all client thinking/reasoning fields (reasoning, reasoning_effort, Claude thinking, Gemini thinking_config) and let the provider invent defaults. Can hide thinking panels and break client summary requests.", - "thinkingModeCustom": "__MISSING__:Custom", - "thinkingModeCustomDesc": "__MISSING__:Overwrite every request with a fixed thinking token budget you set below.", - "thinkingModeAdaptive": "__MISSING__:Adaptive", - "thinkingModeAdaptiveDesc": "__MISSING__:Scale thinking budget from a base effort using message count, tools, and prompt length." + "qdrantCollection": "Samling" }, "contextRtk": { "title": "RTK Engine", diff --git a/src/i18n/messages/sw.json b/src/i18n/messages/sw.json index 81b2a3b5a8..1dbc109a28 100644 --- a/src/i18n/messages/sw.json +++ b/src/i18n/messages/sw.json @@ -6821,8 +6821,17 @@ "chars": "{count} chars", "thinkingBudgetTitle": "Thinking Budget", "thinkingBudgetDesc": "Control AI reasoning token usage across all requests", + "thinkingBudgetIndependenceHint": "Vipengele vya kufinya, uelekezaji, na kikomo cha token vinaendelea kufanya kazi katika kila hali. Auto haitafsiri kama \"kuonyesha mawazo kiotomatiki\" — inafuta maeneo ya mantiki ya mteja.", "passthrough": "Passthrough", "passthroughDesc": "No changes — client controls thinking budget", + "thinkingModePassthrough": "Kupitisha", + "thinkingModePassthroughDesc": "Acha sababu za mteja zisibadilishwe (juhudi, muhtasari, vizuizi vya kufikiri). Inahitajika kwa Codex/Desktop kufikiri kwa wazi. Chaguo la kawaida.", + "thinkingModeAuto": "Auto (strip)", + "thinkingModeAutoDesc": "Ondoa maeneo yote ya kufikiri/kuwaza ya mteja (kuwaza, juhudi za kuwaza, kufikiri kwa Claude, mipangilio ya kufikiri ya Gemini) na umruhusu mtoa huduma kuunda viwango vya kawaida. Inaweza kuficha paneli za kufikiri na kuvunja maombi ya muhtasari wa mteja.", + "thinkingModeCustom": "Mambo Ya Kijadi", + "thinkingModeCustomDesc": "Futa kila ombi kwa bajeti ya tokeni ya kufikiria iliyowekwa hapa chini.", + "thinkingModeAdaptive": "Inayoweza Kujiendesha", + "thinkingModeAdaptiveDesc": "Panga bajeti ya kufikiria kutoka kwa juhudi ya msingi kwa kutumia idadi ya ujumbe, zana, na urefu wa maelekezo.", "auto": "Auto Combo", "autoDesc": "Self-healing smart routing pool (Performance optimized)", "custom": "Custom", @@ -8146,16 +8155,7 @@ "cliproxyapiHealth": "Afya", "cliproxyapiPort": "Bandari", "qdrantHost": "Mwenyeji", - "qdrantCollection": "Mkusanyiko", - "thinkingBudgetIndependenceHint": "__MISSING__:Compression, routing, and token-limit features keep working in every mode. Auto does not mean “auto-show thinking” — it strips client reasoning fields.", - "thinkingModePassthrough": "__MISSING__:Passthrough", - "thinkingModePassthroughDesc": "__MISSING__:Leave client reasoning unchanged (effort, summary, thinking blocks). Required for Codex/Desktop visible thinking. Default.", - "thinkingModeAuto": "__MISSING__:Auto (strip)", - "thinkingModeAutoDesc": "__MISSING__:Strip all client thinking/reasoning fields (reasoning, reasoning_effort, Claude thinking, Gemini thinking_config) and let the provider invent defaults. Can hide thinking panels and break client summary requests.", - "thinkingModeCustom": "__MISSING__:Custom", - "thinkingModeCustomDesc": "__MISSING__:Overwrite every request with a fixed thinking token budget you set below.", - "thinkingModeAdaptive": "__MISSING__:Adaptive", - "thinkingModeAdaptiveDesc": "__MISSING__:Scale thinking budget from a base effort using message count, tools, and prompt length." + "qdrantCollection": "Mkusanyiko" }, "contextRtk": { "title": "RTK Engine", diff --git a/src/i18n/messages/ta.json b/src/i18n/messages/ta.json index f24a60cef2..46844ad9e1 100644 --- a/src/i18n/messages/ta.json +++ b/src/i18n/messages/ta.json @@ -6821,8 +6821,17 @@ "chars": "{count} chars", "thinkingBudgetTitle": "Thinking Budget", "thinkingBudgetDesc": "Control AI reasoning token usage across all requests", + "thinkingBudgetIndependenceHint": "சுருக்கம், வழிமுறை, மற்றும் டோக்கன்-வரம்பு அம்சங்கள் ஒவ்வொரு முறையிலும் செயல்படுகின்றன. ஆட்டோ என்பது \"ஆட்டோ-காணும் சிந்தனை\" என்பதைக் குறிக்கவில்லை - இது கிளையண்ட் காரணம் துறைகளை நீக்குகிறது.", "passthrough": "Passthrough", "passthroughDesc": "No changes — client controls thinking budget", + "thinkingModePassthrough": "பாஸ்த்ரூவ்", + "thinkingModePassthroughDesc": "கிளையனின் காரணங்களை மாற்றாமல் வைக்கவும் (முயற்சி, சுருக்கம், சிந்தனை தடங்கள்). Codex/Desktop காட்சி சிந்தனைக்கு தேவையானது. இயல்பானது.", + "thinkingModeAuto": "ஆட்டோ (ஸ்டிரிப்)", + "thinkingModeAutoDesc": "எல்லா கிளையன்ட் சிந்தனை/காரணம் புலங்களை (காரணம், காரணம்_முயற்சி, கிளோட் சிந்தனை, ஜெமினி சிந்தனை_கொள்கை) அகற்றவும் மற்றும் வழங்குநருக்கு இயல்புகளை உருவாக்க அனுமதிக்கவும். சிந்தனை பலகைகளை மறைக்கவும் மற்றும் கிளையன்ட் சுருக்க கோரிக்கைகளை உடைக்கவும்.", + "thinkingModeCustom": "அனுகூலமான", + "thinkingModeCustomDesc": "கீழே நீங்கள் அமைக்கும் நிலையான சிந்தனை டோக்கன் பட்ஜெட்டை ஒவ்வொரு கோரிக்கையையும் மீறுங்கள்.", + "thinkingModeAdaptive": "அனுகூலமான", + "thinkingModeAdaptiveDesc": "செய்தி எண்ணிக்கை, கருவிகள் மற்றும் உந்துதல் நீளம் பயன்படுத்தி அடிப்படை முயற்சியிலிருந்து எண்ணக்கூடிய பட்ஜெட்டை அளவிடுங்கள்.", "auto": "Auto Combo", "autoDesc": "Self-healing smart routing pool (Performance optimized)", "custom": "Custom", @@ -8146,16 +8155,7 @@ "cliproxyapiHealth": "ஆரோக்கியம்", "cliproxyapiPort": "போர்ட்", "qdrantHost": "விருந்தினர்", - "qdrantCollection": "கலெக்ஷன்", - "thinkingBudgetIndependenceHint": "__MISSING__:Compression, routing, and token-limit features keep working in every mode. Auto does not mean “auto-show thinking” — it strips client reasoning fields.", - "thinkingModePassthrough": "__MISSING__:Passthrough", - "thinkingModePassthroughDesc": "__MISSING__:Leave client reasoning unchanged (effort, summary, thinking blocks). Required for Codex/Desktop visible thinking. Default.", - "thinkingModeAuto": "__MISSING__:Auto (strip)", - "thinkingModeAutoDesc": "__MISSING__:Strip all client thinking/reasoning fields (reasoning, reasoning_effort, Claude thinking, Gemini thinking_config) and let the provider invent defaults. Can hide thinking panels and break client summary requests.", - "thinkingModeCustom": "__MISSING__:Custom", - "thinkingModeCustomDesc": "__MISSING__:Overwrite every request with a fixed thinking token budget you set below.", - "thinkingModeAdaptive": "__MISSING__:Adaptive", - "thinkingModeAdaptiveDesc": "__MISSING__:Scale thinking budget from a base effort using message count, tools, and prompt length." + "qdrantCollection": "கலெக்ஷன்" }, "contextRtk": { "title": "RTK Engine", diff --git a/src/i18n/messages/te.json b/src/i18n/messages/te.json index b209267ea1..0945649c7d 100644 --- a/src/i18n/messages/te.json +++ b/src/i18n/messages/te.json @@ -6821,8 +6821,17 @@ "chars": "{count} chars", "thinkingBudgetTitle": "Thinking Budget", "thinkingBudgetDesc": "Control AI reasoning token usage across all requests", + "thinkingBudgetIndependenceHint": "సంకోచన, మార్గనిర్దేశం, మరియు టోకెన్-సరిహద్దు లక్షణాలు ప్రతి మోడ్‌లో పనిచేస్తున్నాయి. ఆటో అంటే \"ఆటో-చెప్పే ఆలోచన\" కాదు — ఇది క్లయింట్ తర్కం ఫీల్డ్స్‌ను తొలగిస్తుంది.", "passthrough": "Passthrough", "passthroughDesc": "No changes — client controls thinking budget", + "thinkingModePassthrough": "పాస్‌త్రూ", + "thinkingModePassthroughDesc": "క్లయింట్ కారణాలను మార్చకండి (ప్రయత్నం, సారాంశం, ఆలోచన బ్లాక్లు). కోడెక్స్/డెస్క్‌టాప్ దృశ్య ఆలోచనకు అవసరం. డిఫాల్ట్.", + "thinkingModeAuto": "ఆటో (స్ట్రిప్)", + "thinkingModeAutoDesc": "అన్ని క్లయింట్ ఆలోచన/సంగ్రహణ ఫీల్డ్స్ (reasoning, reasoning_effort, Claude thinking, Gemini thinking_config) తొలగించండి మరియు ప్రొవైడర్ డిఫాల్ట్స్‌ను ఆవిష్కరించనివ్వండి. ఆలోచన ప్యానెల్‌లను దాచవచ్చు మరియు క్లయింట్ సారాంశ అభ్యర్థనలను విరామం చేయవచ్చు.", + "thinkingModeCustom": "అనుకూలమైన", + "thinkingModeCustomDesc": "మీరు క్రింద సెట్ చేసిన స్థిరమైన ఆలోచన టోకెన్ బడ్జెట్‌తో ప్రతి అభ్యర్థనను మళ్లీ రాయండి.", + "thinkingModeAdaptive": "అనుకూలమైన", + "thinkingModeAdaptiveDesc": "సందేశాల సంఖ్య, సాధనాలు, మరియు ప్రాంప్ట్ పొడవు ఉపయోగించి ప్రాథమిక శ్రమ నుండి ఆలోచన బడ్జెట్‌ను స్కేల్ చేయండి.", "auto": "Auto Combo", "autoDesc": "Self-healing smart routing pool (Performance optimized)", "custom": "Custom", @@ -8146,16 +8155,7 @@ "cliproxyapiHealth": "ఆరోగ్యం", "cliproxyapiPort": "పోర్ట్", "qdrantHost": "హోస్ట్", - "qdrantCollection": "సేకరణ", - "thinkingBudgetIndependenceHint": "__MISSING__:Compression, routing, and token-limit features keep working in every mode. Auto does not mean “auto-show thinking” — it strips client reasoning fields.", - "thinkingModePassthrough": "__MISSING__:Passthrough", - "thinkingModePassthroughDesc": "__MISSING__:Leave client reasoning unchanged (effort, summary, thinking blocks). Required for Codex/Desktop visible thinking. Default.", - "thinkingModeAuto": "__MISSING__:Auto (strip)", - "thinkingModeAutoDesc": "__MISSING__:Strip all client thinking/reasoning fields (reasoning, reasoning_effort, Claude thinking, Gemini thinking_config) and let the provider invent defaults. Can hide thinking panels and break client summary requests.", - "thinkingModeCustom": "__MISSING__:Custom", - "thinkingModeCustomDesc": "__MISSING__:Overwrite every request with a fixed thinking token budget you set below.", - "thinkingModeAdaptive": "__MISSING__:Adaptive", - "thinkingModeAdaptiveDesc": "__MISSING__:Scale thinking budget from a base effort using message count, tools, and prompt length." + "qdrantCollection": "సేకరణ" }, "contextRtk": { "title": "RTK Engine", diff --git a/src/i18n/messages/th.json b/src/i18n/messages/th.json index 4d648d95d4..e408c398f9 100644 --- a/src/i18n/messages/th.json +++ b/src/i18n/messages/th.json @@ -6821,8 +6821,17 @@ "chars": "{count} ตัวอักษร", "thinkingBudgetTitle": "คิดงบประมาณ", "thinkingBudgetDesc": "ควบคุมการใช้โทเค็นการให้เหตุผลของ AI ในคำขอทั้งหมด", + "thinkingBudgetIndependenceHint": "ฟีเจอร์การบีบอัด การจัดเส้นทาง และการจำกัดโทเค็นยังคงทำงานในทุกโหมด โหมดอัตโนมัติไม่ได้หมายถึง “การแสดงความคิดอัตโนมัติ” — มันจะลบฟิลด์การให้เหตุผลของไคลเอนต์ออก", "passthrough": "ทะลุผ่าน", "passthroughDesc": "ไม่มีการเปลี่ยนแปลง — ลูกค้าควบคุมงบประมาณการคิด", + "thinkingModePassthrough": "ผ่านไป", + "thinkingModePassthroughDesc": "ไม่เปลี่ยนแปลงเหตุผลของลูกค้า (ความพยายาม, สรุป, บล็อกความคิด) จำเป็นสำหรับการมองเห็นของ Codex/Desktop ค่าปริยาย.", + "thinkingModeAuto": "อัตโนมัติ (ลบ)", + "thinkingModeAutoDesc": "ลบฟิลด์การคิด/การให้เหตุผลของลูกค้าทั้งหมด (reasoning, reasoning_effort, Claude thinking, Gemini thinking_config) และให้ผู้ให้บริการสร้างค่าเริ่มต้นเอง สามารถซ่อนแผงการคิดและทำให้คำขอสรุปลูกค้าไม่ทำงานได้", + "thinkingModeCustom": "กำหนดเอง", + "thinkingModeCustomDesc": "เขียนทับคำขอทุกคำด้วยงบประมาณโทเค็นการคิดที่กำหนดไว้ด้านล่าง", + "thinkingModeAdaptive": "ปรับตัว", + "thinkingModeAdaptiveDesc": "ปรับขนาดงบประมาณการคิดจากความพยายามพื้นฐานโดยใช้จำนวนข้อความ, เครื่องมือ, และความยาวของคำสั่ง.", "auto": "อัตโนมัติ", "autoDesc": "ยกเลิกการกำหนดค่าการคิดทั้งหมด — ให้ผู้ให้บริการตัดสินใจ", "custom": "กำหนดเอง", @@ -8146,16 +8155,7 @@ "cliproxyapiHealth": "สุขภาพ", "cliproxyapiPort": "พอร์ต", "qdrantHost": "โฮสต์", - "qdrantCollection": "การรวบรวม", - "thinkingBudgetIndependenceHint": "__MISSING__:Compression, routing, and token-limit features keep working in every mode. Auto does not mean “auto-show thinking” — it strips client reasoning fields.", - "thinkingModePassthrough": "__MISSING__:Passthrough", - "thinkingModePassthroughDesc": "__MISSING__:Leave client reasoning unchanged (effort, summary, thinking blocks). Required for Codex/Desktop visible thinking. Default.", - "thinkingModeAuto": "__MISSING__:Auto (strip)", - "thinkingModeAutoDesc": "__MISSING__:Strip all client thinking/reasoning fields (reasoning, reasoning_effort, Claude thinking, Gemini thinking_config) and let the provider invent defaults. Can hide thinking panels and break client summary requests.", - "thinkingModeCustom": "__MISSING__:Custom", - "thinkingModeCustomDesc": "__MISSING__:Overwrite every request with a fixed thinking token budget you set below.", - "thinkingModeAdaptive": "__MISSING__:Adaptive", - "thinkingModeAdaptiveDesc": "__MISSING__:Scale thinking budget from a base effort using message count, tools, and prompt length." + "qdrantCollection": "การรวบรวม" }, "contextRtk": { "title": "RTK Engine", diff --git a/src/i18n/messages/tr.json b/src/i18n/messages/tr.json index 32b913e251..f70d112a9f 100644 --- a/src/i18n/messages/tr.json +++ b/src/i18n/messages/tr.json @@ -6821,8 +6821,17 @@ "chars": "{count} karakter", "thinkingBudgetTitle": "Düşünme Bütçesi", "thinkingBudgetDesc": "Tüm isteklerde yapay zeka akıl yürütme jetonu kullanımını kontrol edin", + "thinkingBudgetIndependenceHint": "Sıkıştırma, yönlendirme ve token-limit özellikleri her modda çalışmaya devam eder. Otomatik, “otomatik-göster düşüncesi” anlamına gelmez — istemci akıl yürütme alanlarını kaldırır.", "passthrough": "Passthrough Modu", "passthroughDesc": "Değişiklik yapma — düşünme bütçesini istemci kontrol etsin", + "thinkingModePassthrough": "Geçiş", + "thinkingModePassthroughDesc": "Müşteri gerekçesini değiştirmeyin (çaba, özet, düşünce blokları). Codex/Desktop görünür düşünme için gereklidir. Varsayılan.", + "thinkingModeAuto": "Otomatik (şerit)", + "thinkingModeAutoDesc": "Tüm istemci düşünme/akıl yürütme alanlarını (akıl yürütme, akıl_yürütme_gücü, Claude düşüncesi, Gemini düşünce_yapılandırması) kaldırın ve sağlayıcının varsayılanları icat etmesine izin verin. Düşünme panellerini gizleyebilir ve istemci özet isteklerini bozabilirsiniz.", + "thinkingModeCustom": "Özel", + "thinkingModeCustomDesc": "Aşağıda belirlediğiniz sabit düşünce token bütçesi ile her isteği geçersiz kılın.", + "thinkingModeAdaptive": "Uyumlu", + "thinkingModeAdaptiveDesc": "Mesaj sayısı, araçlar ve istem uzunluğunu kullanarak temel çaba üzerinden düşünce bütçesini ölçeklendirin.", "auto": "Otomatik", "autoDesc": "Tüm düşünme yapılandırmalarını kaldırın — kararı sağlayıcı versin", "custom": "Özel", @@ -8146,16 +8155,7 @@ "cliproxyapiHealth": "Sağlık", "cliproxyapiPort": "Port", "qdrantHost": "Ana Bilgisayar", - "qdrantCollection": "Koleksiyon", - "thinkingBudgetIndependenceHint": "__MISSING__:Compression, routing, and token-limit features keep working in every mode. Auto does not mean “auto-show thinking” — it strips client reasoning fields.", - "thinkingModePassthrough": "__MISSING__:Passthrough", - "thinkingModePassthroughDesc": "__MISSING__:Leave client reasoning unchanged (effort, summary, thinking blocks). Required for Codex/Desktop visible thinking. Default.", - "thinkingModeAuto": "__MISSING__:Auto (strip)", - "thinkingModeAutoDesc": "__MISSING__:Strip all client thinking/reasoning fields (reasoning, reasoning_effort, Claude thinking, Gemini thinking_config) and let the provider invent defaults. Can hide thinking panels and break client summary requests.", - "thinkingModeCustom": "__MISSING__:Custom", - "thinkingModeCustomDesc": "__MISSING__:Overwrite every request with a fixed thinking token budget you set below.", - "thinkingModeAdaptive": "__MISSING__:Adaptive", - "thinkingModeAdaptiveDesc": "__MISSING__:Scale thinking budget from a base effort using message count, tools, and prompt length." + "qdrantCollection": "Koleksiyon" }, "contextRtk": { "title": "RTK Engine", diff --git a/src/i18n/messages/uk-UA.json b/src/i18n/messages/uk-UA.json index 2222dad31d..dbd6010a4a 100644 --- a/src/i18n/messages/uk-UA.json +++ b/src/i18n/messages/uk-UA.json @@ -6821,8 +6821,17 @@ "chars": "{count} символів", "thinkingBudgetTitle": "Мислення про бюджет", "thinkingBudgetDesc": "Контролюйте використання маркера міркування AI для всіх запитів", + "thinkingBudgetIndependenceHint": "Функції стиснення, маршрутизації та обмеження токенів продовжують працювати в кожному режимі. Авто не означає \"авто-показ думок\" — він видаляє поля міркувань клієнта.", "passthrough": "Прохідний", "passthroughDesc": "Без змін — клієнт контролює бюджет мислення", + "thinkingModePassthrough": "Пропускний режим", + "thinkingModePassthroughDesc": "Залишити обґрунтування клієнта незмінним (зусилля, резюме, блоки мислення). Обов'язково для видимого мислення Codex/Desktop. За замовчуванням.", + "thinkingModeAuto": "Авто (стрічка)", + "thinkingModeAutoDesc": "Видалити всі поля мислення/міркування клієнта (reasoning, reasoning_effort, Claude thinking, Gemini thinking_config) і дозволити постачальнику вигадати значення за замовчуванням. Можна приховати панелі мислення та зламати запити на підсумок клієнта.", + "thinkingModeCustom": "Користувацький", + "thinkingModeCustomDesc": "Перезапишіть кожен запит з фіксованим бюджетом токенів на мислення, який ви встановили нижче.", + "thinkingModeAdaptive": "Адаптивний", + "thinkingModeAdaptiveDesc": "Масштабуйте бюджет на роздуми з базовими зусиллями, використовуючи кількість повідомлень, інструменти та довжину запиту.", "auto": "Авто", "autoDesc": "Видаліть усі конфігурації мислення — дозвольте постачальнику вирішувати", "custom": "Custom", @@ -8146,16 +8155,7 @@ "cliproxyapiHealth": "Здоров'я", "cliproxyapiPort": "Порт", "qdrantHost": "Хост", - "qdrantCollection": "Колекція", - "thinkingBudgetIndependenceHint": "__MISSING__:Compression, routing, and token-limit features keep working in every mode. Auto does not mean “auto-show thinking” — it strips client reasoning fields.", - "thinkingModePassthrough": "__MISSING__:Passthrough", - "thinkingModePassthroughDesc": "__MISSING__:Leave client reasoning unchanged (effort, summary, thinking blocks). Required for Codex/Desktop visible thinking. Default.", - "thinkingModeAuto": "__MISSING__:Auto (strip)", - "thinkingModeAutoDesc": "__MISSING__:Strip all client thinking/reasoning fields (reasoning, reasoning_effort, Claude thinking, Gemini thinking_config) and let the provider invent defaults. Can hide thinking panels and break client summary requests.", - "thinkingModeCustom": "__MISSING__:Custom", - "thinkingModeCustomDesc": "__MISSING__:Overwrite every request with a fixed thinking token budget you set below.", - "thinkingModeAdaptive": "__MISSING__:Adaptive", - "thinkingModeAdaptiveDesc": "__MISSING__:Scale thinking budget from a base effort using message count, tools, and prompt length." + "qdrantCollection": "Колекція" }, "contextRtk": { "title": "Двигун RTK", diff --git a/src/i18n/messages/ur.json b/src/i18n/messages/ur.json index c6e24a3964..e6b409cff0 100644 --- a/src/i18n/messages/ur.json +++ b/src/i18n/messages/ur.json @@ -6821,8 +6821,17 @@ "chars": "{count} chars", "thinkingBudgetTitle": "Thinking Budget", "thinkingBudgetDesc": "Control AI reasoning token usage across all requests", + "thinkingBudgetIndependenceHint": "کمپریشن، روٹنگ، اور ٹوکن-حد کی خصوصیات ہر موڈ میں کام کرتی رہتی ہیں۔ آٹو کا مطلب \"آٹو-شو سوچ\" نہیں ہے — یہ کلائنٹ کی سوچ کے شعبوں کو ہٹا دیتا ہے۔", "passthrough": "Passthrough", "passthroughDesc": "No changes — client controls thinking budget", + "thinkingModePassthrough": "پاس تھرو", + "thinkingModePassthroughDesc": "کلائنٹ کی وجہ کو بغیر تبدیلی کے چھوڑیں (محنت، خلاصہ، سوچنے کے بلاکس)۔ Codex/Desktop کے نظر آنے والے خیالات کے لیے ضروری۔ ڈیفالٹ۔", + "thinkingModeAuto": "خودکار (اسٹرپ)", + "thinkingModeAutoDesc": "تمام کلائنٹ سوچ/وجوہات کے شعبے (وجوہات، وجوہات کی کوشش، کلود سوچ، جمنائی سوچ_کنفیگ) کو ہٹا دیں اور فراہم کنندہ کو ڈیفالٹس تخلیق کرنے دیں۔ سوچ کے پینلز کو چھپایا جا سکتا ہے اور کلائنٹ کے خلاصے کی درخواستوں کو توڑا جا سکتا ہے۔", + "thinkingModeCustom": "حسب ضرورت", + "thinkingModeCustomDesc": "ہر درخواست کو ایک مقررہ سوچنے والے ٹوکن بجٹ کے ساتھ اووررائٹ کریں جو آپ نیچے سیٹ کرتے ہیں۔", + "thinkingModeAdaptive": "ایڈاپٹو", + "thinkingModeAdaptiveDesc": "پیغام کی تعداد، ٹولز، اور پرامپٹ کی لمبائی کا استعمال کرتے ہوئے بنیادی کوشش سے بجٹ کی پیمائش کریں۔", "auto": "Auto Combo", "autoDesc": "Self-healing smart routing pool (Performance optimized)", "custom": "Custom", @@ -8146,16 +8155,7 @@ "cliproxyapiHealth": "صحت", "cliproxyapiPort": "پورٹ", "qdrantHost": "میزبان", - "qdrantCollection": "اجتماع", - "thinkingBudgetIndependenceHint": "__MISSING__:Compression, routing, and token-limit features keep working in every mode. Auto does not mean “auto-show thinking” — it strips client reasoning fields.", - "thinkingModePassthrough": "__MISSING__:Passthrough", - "thinkingModePassthroughDesc": "__MISSING__:Leave client reasoning unchanged (effort, summary, thinking blocks). Required for Codex/Desktop visible thinking. Default.", - "thinkingModeAuto": "__MISSING__:Auto (strip)", - "thinkingModeAutoDesc": "__MISSING__:Strip all client thinking/reasoning fields (reasoning, reasoning_effort, Claude thinking, Gemini thinking_config) and let the provider invent defaults. Can hide thinking panels and break client summary requests.", - "thinkingModeCustom": "__MISSING__:Custom", - "thinkingModeCustomDesc": "__MISSING__:Overwrite every request with a fixed thinking token budget you set below.", - "thinkingModeAdaptive": "__MISSING__:Adaptive", - "thinkingModeAdaptiveDesc": "__MISSING__:Scale thinking budget from a base effort using message count, tools, and prompt length." + "qdrantCollection": "اجتماع" }, "contextRtk": { "title": "RTK Engine", diff --git a/src/i18n/messages/vi.json b/src/i18n/messages/vi.json index 8c13514a1a..8cb05728d6 100644 --- a/src/i18n/messages/vi.json +++ b/src/i18n/messages/vi.json @@ -6821,8 +6821,17 @@ "chars": "{count} ký tự", "thinkingBudgetTitle": "Ngân sách suy nghĩ", "thinkingBudgetDesc": "Kiểm soát việc OmniRoute viết lại tham số thinking/reasoning của máy khách trước khi gửi upstream. Tách biệt với nén, prompt cache và giới hạn token của API key.", + "thinkingBudgetIndependenceHint": "Nén, định tuyến và giới hạn token vẫn hoạt động ở mọi chế độ. Auto không có nghĩa là “tự động hiện thinking” — nó loại bỏ các trường reasoning của máy khách.", "passthrough": "Chuyển tiếp nguyên trạng", "passthroughDesc": "Không thay đổi — máy khách tự kiểm soát ngân sách suy nghĩ", + "thinkingModePassthrough": "Chuyển tiếp nguyên trạng", + "thinkingModePassthroughDesc": "Giữ nguyên reasoning của máy khách (effort, summary, thinking blocks). Bắt buộc để hiện thinking trên Codex/Desktop. Mặc định.", + "thinkingModeAuto": "Tự động (loại bỏ)", + "thinkingModeAutoDesc": "Loại bỏ mọi trường thinking/reasoning của máy khách (reasoning, reasoning_effort, Claude thinking, Gemini thinking_config) và để nhà cung cấp tự chọn mặc định. Có thể ẩn panel thinking và làm hỏng yêu cầu summary từ máy khách.", + "thinkingModeCustom": "Tùy chỉnh", + "thinkingModeCustomDesc": "Ghi đè mọi yêu cầu bằng ngân sách token thinking cố định bạn đặt bên dưới.", + "thinkingModeAdaptive": "Thích ứng", + "thinkingModeAdaptiveDesc": "Điều chỉnh ngân sách thinking từ mức effort cơ sở theo số tin nhắn, công cụ và độ dài prompt.", "auto": "Kết hợp tự động", "autoDesc": "Nhóm định tuyến thông minh tự khắc phục lỗi (tối ưu hóa hiệu suất)", "custom": "Tùy chỉnh", @@ -8146,16 +8155,7 @@ "cliproxyapiHealth": "Sức Khỏe", "cliproxyapiPort": "Cổng", "qdrantHost": "Máy chủ", - "qdrantCollection": "Bộ Sưu Tập", - "thinkingBudgetIndependenceHint": "Nén, định tuyến và giới hạn token vẫn hoạt động ở mọi chế độ. Auto không có nghĩa là “tự động hiện thinking” — nó loại bỏ các trường reasoning của máy khách.", - "thinkingModePassthrough": "Chuyển tiếp nguyên trạng", - "thinkingModePassthroughDesc": "Giữ nguyên reasoning của máy khách (effort, summary, thinking blocks). Bắt buộc để hiện thinking trên Codex/Desktop. Mặc định.", - "thinkingModeAuto": "Tự động (loại bỏ)", - "thinkingModeAutoDesc": "Loại bỏ mọi trường thinking/reasoning của máy khách (reasoning, reasoning_effort, Claude thinking, Gemini thinking_config) và để nhà cung cấp tự chọn mặc định. Có thể ẩn panel thinking và làm hỏng yêu cầu summary từ máy khách.", - "thinkingModeCustom": "Tùy chỉnh", - "thinkingModeCustomDesc": "Ghi đè mọi yêu cầu bằng ngân sách token thinking cố định bạn đặt bên dưới.", - "thinkingModeAdaptive": "Thích ứng", - "thinkingModeAdaptiveDesc": "Điều chỉnh ngân sách thinking từ mức effort cơ sở theo số tin nhắn, công cụ và độ dài prompt." + "qdrantCollection": "Bộ Sưu Tập" }, "contextRtk": { "title": "RTK Engine", diff --git a/src/i18n/messages/zh-CN.json b/src/i18n/messages/zh-CN.json index efd8112e3e..3d8de6f6b2 100644 --- a/src/i18n/messages/zh-CN.json +++ b/src/i18n/messages/zh-CN.json @@ -6821,8 +6821,17 @@ "chars": "{count} 字符", "thinkingBudgetTitle": "思考预算", "thinkingBudgetDesc": "控制所有请求中 AI 推理令牌的使用", + "thinkingBudgetIndependenceHint": "压缩、路由和令牌限制功能在每种模式下都能正常工作。自动并不意味着“自动显示思维”——它会剥离客户端推理字段。", "passthrough": "直通", "passthroughDesc": "没有变化——客户控制思维预算", + "thinkingModePassthrough": "直通", + "thinkingModePassthroughDesc": "保持客户端推理不变(努力、摘要、思维块)。Codex/Desktop 可见思维所需。默认。", + "thinkingModeAuto": "自动(剥离)", + "thinkingModeAutoDesc": "剥离所有客户端思考/推理字段(reasoning, reasoning_effort, Claude thinking, Gemini thinking_config),让提供者自行设定默认值。可以隐藏思考面板并中断客户端摘要请求。", + "thinkingModeCustom": "自定义", + "thinkingModeCustomDesc": "用您在下面设置的固定思维令牌预算覆盖每个请求。", + "thinkingModeAdaptive": "自适应", + "thinkingModeAdaptiveDesc": "根据消息数量、工具和提示长度,从基础工作量扩展思维预算。", "auto": "自动", "autoDesc": "丢弃所有思考配置,由提供者自行决定", "custom": "定制", @@ -8146,16 +8155,7 @@ "cliproxyapiHealth": "健康", "cliproxyapiPort": "端口", "qdrantHost": "主机", - "qdrantCollection": "集合", - "thinkingBudgetIndependenceHint": "__MISSING__:Compression, routing, and token-limit features keep working in every mode. Auto does not mean “auto-show thinking” — it strips client reasoning fields.", - "thinkingModePassthrough": "__MISSING__:Passthrough", - "thinkingModePassthroughDesc": "__MISSING__:Leave client reasoning unchanged (effort, summary, thinking blocks). Required for Codex/Desktop visible thinking. Default.", - "thinkingModeAuto": "__MISSING__:Auto (strip)", - "thinkingModeAutoDesc": "__MISSING__:Strip all client thinking/reasoning fields (reasoning, reasoning_effort, Claude thinking, Gemini thinking_config) and let the provider invent defaults. Can hide thinking panels and break client summary requests.", - "thinkingModeCustom": "__MISSING__:Custom", - "thinkingModeCustomDesc": "__MISSING__:Overwrite every request with a fixed thinking token budget you set below.", - "thinkingModeAdaptive": "__MISSING__:Adaptive", - "thinkingModeAdaptiveDesc": "__MISSING__:Scale thinking budget from a base effort using message count, tools, and prompt length." + "qdrantCollection": "集合" }, "contextRtk": { "title": "命令输出过滤引擎", diff --git a/src/i18n/messages/zh-TW.json b/src/i18n/messages/zh-TW.json index 3277e27a9b..488312f384 100644 --- a/src/i18n/messages/zh-TW.json +++ b/src/i18n/messages/zh-TW.json @@ -6821,8 +6821,17 @@ "chars": "{count} 字元", "thinkingBudgetTitle": "思考預算", "thinkingBudgetDesc": "控制所有請求中 AI 推理權杖的使用", + "thinkingBudgetIndependenceHint": "壓縮、路由和令牌限制功能在每種模式下都能正常運作。自動並不意味著「自動顯示思考」——它會刪除客戶端推理字段。", "passthrough": "直通", "passthroughDesc": "沒有變化——客戶控制思維預算", + "thinkingModePassthrough": "直通", + "thinkingModePassthroughDesc": "保持客戶推理不變(努力、摘要、思考區塊)。Codex/Desktop 可見思考所需。預設。", + "thinkingModeAuto": "自動 (剝離)", + "thinkingModeAutoDesc": "刪除所有客戶思考/推理欄位(推理、推理努力、Claude 思考、Gemini thinking_config),讓提供者自行創建預設值。可以隱藏思考面板並中斷客戶摘要請求。", + "thinkingModeCustom": "自訂", + "thinkingModeCustomDesc": "用您在下面設置的固定思考令牌預算覆蓋每個請求。", + "thinkingModeAdaptive": "自適應", + "thinkingModeAdaptiveDesc": "根據消息數量、工具和提示長度,從基本工作量擴展思考預算。", "auto": "自動", "autoDesc": "丟棄所有思考設定,由提供者自行決定", "custom": "定製", @@ -8146,16 +8155,7 @@ "cliproxyapiHealth": "健康", "cliproxyapiPort": "埠", "qdrantHost": "主機", - "qdrantCollection": "集合", - "thinkingBudgetIndependenceHint": "__MISSING__:Compression, routing, and token-limit features keep working in every mode. Auto does not mean “auto-show thinking” — it strips client reasoning fields.", - "thinkingModePassthrough": "__MISSING__:Passthrough", - "thinkingModePassthroughDesc": "__MISSING__:Leave client reasoning unchanged (effort, summary, thinking blocks). Required for Codex/Desktop visible thinking. Default.", - "thinkingModeAuto": "__MISSING__:Auto (strip)", - "thinkingModeAutoDesc": "__MISSING__:Strip all client thinking/reasoning fields (reasoning, reasoning_effort, Claude thinking, Gemini thinking_config) and let the provider invent defaults. Can hide thinking panels and break client summary requests.", - "thinkingModeCustom": "__MISSING__:Custom", - "thinkingModeCustomDesc": "__MISSING__:Overwrite every request with a fixed thinking token budget you set below.", - "thinkingModeAdaptive": "__MISSING__:Adaptive", - "thinkingModeAdaptiveDesc": "__MISSING__:Scale thinking budget from a base effort using message count, tools, and prompt length." + "qdrantCollection": "集合" }, "contextRtk": { "title": "RTK 引擎", diff --git a/stryker.conf.json b/stryker.conf.json index dbbf0c7446..1214fc37f8 100644 --- a/stryker.conf.json +++ b/stryker.conf.json @@ -232,6 +232,7 @@ "tests/unit/gemini-web-missing-browser-3516.test.ts", "tests/unit/grok-cli-oauth.test.ts", "tests/unit/guardrails-api-3496.test.ts", + "tests/unit/guardrails/visionBridge-responses-9597.test.ts", "tests/unit/headroom-codex-quota-snapshot-6379.test.ts", "tests/unit/headroom-proxy-lifecycle.test.ts", "tests/unit/idempotency-fusion-collision.test.ts", diff --git a/tests/unit/cli-env-inline-comment-10100.test.ts b/tests/unit/cli-env-inline-comment-10100.test.ts index 2e3b41a725..4a3959c701 100644 --- a/tests/unit/cli-env-inline-comment-10100.test.ts +++ b/tests/unit/cli-env-inline-comment-10100.test.ts @@ -2,6 +2,7 @@ import test from "node:test"; import assert from "node:assert/strict"; import fs from "node:fs"; import path from "node:path"; +import { parseEnvValue } from "../../bin/cli/utils/parseEnvValue.mjs"; // #10100 — the .env loader kept inline comments inside values, so the shipped // `QUOTA_STORE_DRIVER=sqlite # sqlite | redis` line produced the literal value @@ -9,36 +10,6 @@ import path from "node:path"; // user annotating `QUOTA_STORE_DRIVER=redis # ...` silently got SQLite with no // warning (the existing warning lives inside the `redis` branch). -const LOADER = path.resolve("bin/omniroute.mjs"); - -/** - * The loader is a CLI entrypoint with side effects on import, so exercise the - * pure helper by extracting it from source rather than importing the module. - */ -function loadParseEnvValue(): (raw: string) => string { - const source = fs.readFileSync(LOADER, "utf8"); - const start = source.indexOf("function parseEnvValue("); - assert.ok(start > -1, "parseEnvValue should exist in bin/omniroute.mjs"); - // Walk to the end of the function body. - let depth = 0; - let end = start; - for (let i = source.indexOf("{", start); i < source.length; i++) { - if (source[i] === "{") depth++; - else if (source[i] === "}") { - depth--; - if (depth === 0) { - end = i + 1; - break; - } - } - } - return new Function(`${source.slice(start, end)}; return parseEnvValue;`)() as ( - raw: string - ) => string; -} - -const parseEnvValue = loadParseEnvValue(); - test("an unquoted inline comment is stripped", () => { assert.equal(parseEnvValue("sqlite # sqlite | redis"), "sqlite"); assert.equal(parseEnvValue("redis # sqlite | redis"), "redis"); diff --git a/tests/unit/free-tier-providers-wave1-a.test.ts b/tests/unit/free-tier-providers-wave1-a.test.ts index 2ad3b23f41..652e7a5772 100644 --- a/tests/unit/free-tier-providers-wave1-a.test.ts +++ b/tests/unit/free-tier-providers-wave1-a.test.ts @@ -48,8 +48,22 @@ for (const { entry, id, alias, chatUrl, modelsUrl } of providers) { assert.equal(entry.modelsUrl, modelsUrl); assert.equal(entry.passthroughModels, true); }); +} +// zylo-api and unorouter rely on the live catalog with no static seed (#9085). +for (const { entry, id } of providers.filter((p) => p.id !== "poolside")) { test(`${id} relies on its live catalog without invented static model ids`, () => { assert.deepEqual(entry.models, []); }); } + +// Poolside ships the two authenticated-probe models (#10216) as static seeds — +// they are the exact IDs the live catalog returns (authenticated probe 2026-08-07, +// #9085), not invented. Assert them explicitly so a future catalog change is a +// deliberate update, not a silent drift. +test("poolside ships the probed Laguna Preview models, not invented ids", () => { + const models = poolsideProvider.models; + assert.ok(Array.isArray(models) && models.length > 0, "poolside should seed its probed catalog"); + const ids = models.map((m) => m.id); + assert.deepEqual(ids, ["poolside/laguna-xs-2.1", "poolside/laguna-s-2.1"]); +}); diff --git a/tests/unit/pack-artifact-policy.test.ts b/tests/unit/pack-artifact-policy.test.ts index d44f0c31e8..a7e73bb656 100644 --- a/tests/unit/pack-artifact-policy.test.ts +++ b/tests/unit/pack-artifact-policy.test.ts @@ -201,6 +201,7 @@ test("findMissingArtifactPaths flags missing root runtime files in the tarball", "bin/cli/data-dir.mjs", "bin/cli/program.mjs", "bin/cli/utils/ensureAndroidCacheDir.mjs", + "bin/cli/utils/parseEnvValue.mjs", "bin/cli/utils/storageKeyProvision.mjs", "bin/cli/utils/versionFastPath.mjs", "bin/mcp-server.mjs", From 587e53a3c1f4488d683ba70a2fd5ecae767e4e43 Mon Sep 17 00:00:00 2001 From: adevwithpurpose Date: Fri, 14 Aug 2026 08:57:19 +0500 Subject: [PATCH 02/11] fix(compression): cap countTextTokens at 50k chars and strip base64 data URIs (#10118) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes #10117 — countTextTokens can block the worker event loop for tens of seconds when a Codex request carries a large base64 image payload, wedging /healthz and every concurrent request. - Strip base64 image data URIs before encoding (images are not text) - Fast-path length guard: over 50k chars, skip the near-quadratic pure-JS tokenizer and return the chars/4 heuristic Co-authored-by: adevwithpurpose Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com> --- src/shared/utils/tiktokenCounter.ts | 34 +++++++++++++++++++++++++++-- tests/unit/tiktoken-counter.test.ts | 31 ++++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 2 deletions(-) diff --git a/src/shared/utils/tiktokenCounter.ts b/src/shared/utils/tiktokenCounter.ts index ec6af38913..5f4354f045 100644 --- a/src/shared/utils/tiktokenCounter.ts +++ b/src/shared/utils/tiktokenCounter.ts @@ -21,6 +21,29 @@ export function tokenizerContextFromBody(body: unknown): TokenizerContext { const encoders = new Map(); +/** + * Above this many characters the exact tokenizer is skipped in favor of the + * char-heuristic (chars/4). js-tiktoken's pure-JS encoder is near-quadratic on + * large inputs — a 10 MB base64 image payload can block the event loop for + * tens of seconds (OmniRoute worker wedge incident). Token counting is used for + * compression stats/estimates only, so a heuristic on oversized inputs is + * acceptable and keeps the loop responsive. + */ +const MAX_EXACT_TOKEN_COUNT_CHARS = 50_000; + +/** + * Base64 data URIs (e.g. OpenAI-style `image_url.url`) must not be tokenized: + * they are image payloads, not text. Matching a data URI of any `image/*` + * media type and stripping it keeps the count accurate (the raw bytes of an + * image are not meaningful "text" tokens) while avoiding the quadratic encode + * cost on large attachments. + */ +const BASE64_DATA_URI_RE = /data:image\/[a-z0-9.+-]+;base64,[A-Za-z0-9+/=]+/gi; + +function stripBase64DataUris(text: string): string { + return text.replace(BASE64_DATA_URI_RE, ""); +} + function normalize(value: unknown): string { return typeof value === "string" ? value.trim().toLowerCase() : ""; } @@ -60,12 +83,19 @@ function getEncoder(encoding: TokenizerEncoding): Tiktoken { * Existing callers retain cl100k_base; Codex callers may pass provider/model context * to use o200k_base. * Defensive: never throws in a counting path — falls back to a char heuristic. + * Oversized inputs (over 50k chars) and base64 image data URIs are never + * tokenized: the encoder is near-quadratic on large strings and would block the + * event loop (worker wedge regression). */ export function countTextTokens(text: string, context?: TokenizerContext): number { if (!text || typeof text !== "string") return 0; + const stripped = stripBase64DataUris(text); + if (stripped.length > MAX_EXACT_TOKEN_COUNT_CHARS) { + return Math.ceil(stripped.length / 4); + } try { - return getEncoder(resolveTokenizerEncoding(context)).encode(text).length; + return getEncoder(resolveTokenizerEncoding(context)).encode(stripped).length; } catch { - return Math.ceil(text.length / 4); + return Math.ceil(stripped.length / 4); } } diff --git a/tests/unit/tiktoken-counter.test.ts b/tests/unit/tiktoken-counter.test.ts index 110618d1b0..d3263dfd31 100644 --- a/tests/unit/tiktoken-counter.test.ts +++ b/tests/unit/tiktoken-counter.test.ts @@ -40,3 +40,34 @@ test("countTextTokens is additive-ish and monotonic for longer text", () => { assert.ok(long > short); assert.ok(short > 0); }); + +test("countTextTokens fast-paths strings over 50k chars without tokenizing (worker wedge regression)", () => { + const big = "user: please review the attached patch\ntext: ".repeat(40_000); + const start = performance.now(); + const tokens = countTextTokens(big); + const elapsed = performance.now() - start; + assert.equal(tokens, Math.ceil(big.length / 4)); + assert.ok(elapsed < 1000, `fast path took ${elapsed.toFixed(0)}ms`); +}); + +test("countTextTokens strips base64 data URIs before tokenizing (images not counted as text)", () => { + const png = + "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8BQDwAEhQGAhKmMIQAAAABJRU5ErkJggg=="; + const b64 = png.repeat(60); + const withImage = countTextTokens( + `{"image_url":{"url":"data:image/png;base64,${b64}"}}`, + { provider: "codex" } + ); + const stripped = countTextTokens('{"image_url":{"url":""}}', { provider: "codex" }); + assert.equal(withImage, stripped); +}); + +test("countTextTokens does not tokenize huge base64 image payloads (wedge repro)", () => { + const b64 = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8BQDwAEhQGAhKmMIQAAAABJRU5ErkJggg=="; + const body = `{"image_url":{"url":"data:image/png;base64,${b64.repeat(14_000)}"}}`; + const start = performance.now(); + const tokens = countTextTokens(body); + const elapsed = performance.now() - start; + assert.ok(tokens < 1000, `base64 payload inflates token count to ${tokens}`); + assert.ok(elapsed < 1000, `took ${elapsed.toFixed(0)}ms`); +}); From 8417ace4b37144c65ca99147548c53a1e8b033ae Mon Sep 17 00:00:00 2001 From: Xiangzhe <32761048+xz-dev@users.noreply.github.com> Date: Fri, 14 Aug 2026 11:57:23 +0800 Subject: [PATCH 03/11] feat(codex): add OAuth fingerprint convergence modes (#10243) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(deps): bump nanoid, dompurify for 2 new Dependabot alerts (#189, #190) Bumps: nanoid ^3.3.17 (was transitive, now overridden), dompurify ^3.4.13 (with monaco-editor scoped override). Closes Dependabot #189, #190. Remaining #182-#188 (js-yaml + mermaid) already closed by #9651 merge — awaiting Dependabot re-scan. npm audit → 0 vulnerabilities. * fix(repo): harden .gitignore to also ignore a _tasks symlink (/_tasks) _tasks is a SEPARATE nested git repo (gitignored). The pattern _tasks/ (trailing slash) ignores only a directory, not a SYMLINK named _tasks. A self-referential _tasks symlink can slip in via git add -A and, once pulled, checkout materializes it over the real _tasks repo (destroying plans/specs/hands-off). Anchored /_tasks ignores the symlink too, preventing re-capture. * feat(codex): converge OAuth fingerprints * test(codex): preserve identity assertions * fix(codex): preserve explicit off identity * fix(codex): close fingerprint transport gaps --------- Co-authored-by: diegosouzapw Co-authored-by: Diego Rodrigues de Sa e Souza Co-authored-by: diegosouzapw Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com> --- config/quality/file-size-baseline.json | 4 +- open-sse/config/codexIdentity.ts | 408 +++++++++++++++--- open-sse/executors/codex.ts | 24 +- scripts/dev/responses-ws-proxy.mjs | 11 + scripts/dev/v1-ws-bridge.mjs | 12 + .../modals/CodexFingerprintFields.tsx | 86 ++++ .../components/modals/EditConnectionModal.tsx | 63 +-- .../providers/[id]/providerPageHelpers.ts | 41 +- .../api/internal/codex-responses-ws/route.ts | 11 +- src/lib/providers/requestDefaults.ts | 5 + src/shared/validation/providerSpecificData.ts | 15 + tests/integration/chat-pipeline.test.ts | 34 +- tests/unit/codex-connection-edit-6562.test.ts | 45 +- .../codex-fingerprint-convergence.test.ts | 373 ++++++++++++++++ .../codex-responses-ws-fingerprint.test.ts | 59 +++ tests/unit/executor-codex.test.ts | 59 +-- .../provider-specific-data-schema.test.ts | 21 + 17 files changed, 1103 insertions(+), 168 deletions(-) create mode 100644 src/app/(dashboard)/dashboard/providers/[id]/components/modals/CodexFingerprintFields.tsx create mode 100644 tests/unit/codex-fingerprint-convergence.test.ts create mode 100644 tests/unit/codex-responses-ws-fingerprint.test.ts diff --git a/config/quality/file-size-baseline.json b/config/quality/file-size-baseline.json index 64c5e75c8e..bbdc9d16f0 100644 --- a/config/quality/file-size-baseline.json +++ b/config/quality/file-size-baseline.json @@ -1,4 +1,5 @@ { + "_rebaseline_2026_08_13_10243_codex_fingerprint_merge": "PR #10243 (xz-dev, Codex OAuth fingerprint convergence) merge into release/v3.8.50: src/app/(dashboard)/dashboard/providers/[id]/providerPageHelpers.ts crossed the 1000-line new-file cap for the first time (974 on base, 997 on the PR's own branch, 1013 after merging + prettier reflow) purely from combining two independent, already-legitimate feature additions that landed on the same shared UI-helper file — this PR's own Codex fingerprint-mode select/toggle wiring (CODEX_FINGERPRINT_MODE_VALUES, getCodexFingerprintModeLabel, CodexFingerprintModeValue) plus #8949's unrelated Codex account-service-tier helpers merged concurrently on release/v3.8.50. Neither addition alone crosses the cap; git's line-level auto-merge does not detect a threshold crossing. Not modularized as part of this conflict-resolution merge commit (out of scope — this is a merge, not a feature change). Covered by the PR's own tests/unit/codex-fingerprint-convergence.test.ts, tests/unit/executor-codex.test.ts, tests/unit/provider-specific-data-schema.test.ts (all passing post-merge).", "_rebaseline_2026_08_09_8984_api_key_cache_mode": "PR #8984 own growth during the 2026-08-09 rebase: src/lib/db/apiKeys.ts 1529->1545 (+16 = the per-key apiKeys.cacheDefaultMode column + its row parsers and cascade wiring; additive at the existing connection write/read chokepoints). Covered by tests/unit/chatcore-semantic-cache.test.ts. (chatCore.ts stays at the pre-existing base-red ceiling — upstream tip already exceeds the frozen 5042, this PR only adds +2 on top; not re-bumped per the no-inherit-ratchet rule.)", "_rebaseline_2026_08_09_9207_breaker_halfopen_recovery": "PR #9207 own growth during the 2026-08-09 rebase: open-sse/services/accountFallback.ts 1978->2020 (+42 = recordProviderSuccess now also transitions the provider circuit breaker from HALF_OPEN to CLOSED when a request succeeds, so the breaker is not stuck half-open after repeated failures; the transition and its reset wiring grow the existing provider-success path, not extractable). Covered by tests/unit/provider-breaker-halfopen-recovery.test.ts.", "_rebaseline_2026_08_09_9351_antigravity_switch_auth": "PR #9351 own growth during the 2026-08-09 rebase: open-sse/executors/antigravity.ts 1528->1536 (+8 = switchAuth threaded out of tryResolveRetryFromErrorBody into handleAntigravityRateLimit's short-retry guard, so a decide429 switch decision beats the 60s same-account sleep; cohesive at the existing resolve chokepoint, not extractable). Covered by tests/unit/antigravity-429-switch-auth.test.ts.", @@ -444,7 +445,8 @@ "src/shared/constants/providers/apikey/gateways.ts": 1250, "open-sse/vendor/codex-chatgpt-web/bridge.ts": 1387, "_rebaseline_2026_08_11_v3850_merge_storm_provider_registry": "DRIFT do merge-storm 2026-08-11 (99 PRs mergeados no release/v3.8.50). AddApiKeyModal.tsx (PR #8949 ChatGPT Web provider) e useProviderConnections.ts/ModelSelectModal.tsx (PRs #9011 combo test-all, #9499 image combos) = UI nova legitima acima do cap; gateways.ts = god-file de catalogo de providers que cresceu com PRs #9009/#9421/#9468/#9594 (qualquer split arriscaria corromper o merge de novo — o proprio PR #9421 quebrou o arquivo); bridge.ts (PR #8949) = ponte Chromium vendored; proxyFetch.ts 1207->1220 = drift herdado de merges. Owner autorizou rebaseline com anotacao (2026-08-11).", - "src/lib/modelCapabilities.ts": 1006 + "src/lib/modelCapabilities.ts": 1006, + "src/app/(dashboard)/dashboard/providers/[id]/providerPageHelpers.ts": 1014 }, "_rebaseline_base_2026_08_10_proxyfetch": "Base-red fix (green-prs sweep, issue #9985): open-sse/utils/proxyFetch.ts 1207 > cap 1000 — new proxied-TLS fetch helper introduced by the Fal reference-image work. Owner-authorized quick rebaseline to green; structural slim tracked for v3.9.0.", "_rebaseline_2026_07_27_v3849_train2": "Merge-train 2 (7 PRs) — owner-approved 2026-07-27. Single entry: chatCore.ts 4955->5006 (#8595, Responses multi-turn image compaction before the context hard-reject). Genuine irreducible growth at the existing compaction chokepoint in handleChatCore — the PR adds a last-resort retry against the concrete budget plus the estimateFinalInputTokens helper, both wired at the pre-existing call site rather than a new branch. Covered by tests/unit/8560-responses-image-compaction.test.ts (4 tests).", diff --git a/open-sse/config/codexIdentity.ts b/open-sse/config/codexIdentity.ts index 7a52f5a0f1..bc45fa1cf6 100644 --- a/open-sse/config/codexIdentity.ts +++ b/open-sse/config/codexIdentity.ts @@ -3,81 +3,410 @@ import { createHash, randomUUID } from "node:crypto"; import { normalizeCodexSessionId } from "./codexClient.ts"; const CODEX_INSTALLATION_SALT = "omniroute-codex-installation"; +const CODEX_SESSION_SEED_PREFIX = "omniroute:codex-session-id:v1:"; +const CODEX_THREAD_SEED_PREFIX = "omniroute:codex-thread-id:v1:"; const UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i; +export const CODEX_FINGERPRINT_MODES = ["off", "device", "session", "full"] as const; +export type CodexFingerprintMode = (typeof CODEX_FINGERPRINT_MODES)[number]; +export const CODEX_FINGERPRINT_MODE_KEY = "codexFingerprintMode"; + export type CodexClientIdentity = { + mode: CodexFingerprintMode; + installationId: string; sessionId: string; + threadId: string; turnId: string; windowId: string; - installationId: string; + turnStartedAtUnixMs: number; +}; + +type CodexIdentityOptions = { + mode?: CodexFingerprintMode; + accountKey?: string | null; + isOAuth?: boolean; }; function normalizeUuid(value: unknown): string | null { return typeof value === "string" && UUID_PATTERN.test(value.trim()) ? value.trim() : null; } -function uuidFromStableValue(value: string): string { +function nonEmptyString(value: unknown): string | null { + if (typeof value !== "string") return null; + const normalized = value.trim(); + return normalized || null; +} + +/** Keep the historical installation-id layout so existing accounts stay stable. */ +function uuidFromLegacyInstallationValue(value: string): string { const hash = createHash("sha256").update(value).digest("hex"); return `${hash.slice(0, 8)}-${hash.slice(8, 12)}-4${hash.slice(13, 16)}-a${hash.slice(17, 20)}-${hash.slice(20, 32)}`; } +/** RFC4122 v4 from SHA-256. Same seed → same UUID. */ +export function deriveStableUUIDv4(seed: string): string { + const digest = createHash("sha256").update(seed).digest(); + const bytes = Buffer.from(digest.subarray(0, 16)); + bytes[6] = (bytes[6] & 0x0f) | 0x40; + bytes[8] = (bytes[8] & 0x3f) | 0x80; + return [ + bytes.subarray(0, 4).toString("hex"), + bytes.subarray(4, 6).toString("hex"), + bytes.subarray(6, 8).toString("hex"), + bytes.subarray(8, 10).toString("hex"), + bytes.subarray(10, 16).toString("hex"), + ].join("-"); +} + +function accountSeed( + providerSpecificData?: Record | null, + accountKey?: string | null +): string { + return ( + nonEmptyString(accountKey) || + nonEmptyString(providerSpecificData?.connectionId) || + nonEmptyString(providerSpecificData?.workspaceId) || + nonEmptyString(providerSpecificData?.accountId) || + nonEmptyString(providerSpecificData?.email) || + "default" + ); +} + +function readNamedHeader( + headers: Headers | Record | null | undefined, + name: string +): string { + if (!headers) return ""; + if (headers instanceof Headers) return headers.get(name)?.trim() || ""; + const wanted = name.toLowerCase(); + for (const [key, value] of Object.entries(headers)) { + if (key.toLowerCase() === wanted && typeof value === "string" && value.trim()) { + return value.trim(); + } + } + return ""; +} + +export function isCodexOAuthCredentials( + credentials?: { + accessToken?: unknown; + refreshToken?: unknown; + } | null +): boolean { + return Boolean( + nonEmptyString(credentials?.accessToken) || nonEmptyString(credentials?.refreshToken) + ); +} + +export function getCodexFingerprintMode( + providerSpecificData?: Record | null, + isOAuth = true +): CodexFingerprintMode { + if (!isOAuth) return "off"; + const raw = ( + nonEmptyString(providerSpecificData?.[CODEX_FINGERPRINT_MODE_KEY]) || + nonEmptyString(providerSpecificData?.codex_fingerprint_mode) || + "" + ).toLowerCase(); + return (CODEX_FINGERPRINT_MODES as readonly string[]).includes(raw) + ? (raw as CodexFingerprintMode) + : "session"; +} + export function getCodexInstallationId( - providerSpecificData?: Record | null + providerSpecificData?: Record | null, + accountKey?: string | null ): string { const explicit = normalizeUuid(providerSpecificData?.codexInstallationId); if (explicit) return explicit; - const stableSource = - typeof providerSpecificData?.workspaceId === "string" && providerSpecificData.workspaceId.trim() - ? providerSpecificData.workspaceId.trim() - : typeof providerSpecificData?.accountId === "string" && providerSpecificData.accountId.trim() - ? providerSpecificData.accountId.trim() - : typeof providerSpecificData?.email === "string" && providerSpecificData.email.trim() - ? providerSpecificData.email.trim() - : "default"; + const legacyStableSource = + nonEmptyString(providerSpecificData?.workspaceId) || + nonEmptyString(providerSpecificData?.accountId) || + nonEmptyString(providerSpecificData?.email); + if (legacyStableSource) { + return uuidFromLegacyInstallationValue(`${CODEX_INSTALLATION_SALT}:${legacyStableSource}`); + } - return uuidFromStableValue(`${CODEX_INSTALLATION_SALT}:${stableSource}`); + return deriveStableUUIDv4( + `${CODEX_INSTALLATION_SALT}:${accountSeed(providerSpecificData, accountKey)}` + ); } +export function getCodexConvergedSessionId( + providerSpecificData?: Record | null, + accountKey?: string | null +): string { + return deriveStableUUIDv4( + `${CODEX_SESSION_SEED_PREFIX}${accountSeed(providerSpecificData, accountKey)}` + ); +} + +export function getCodexConvergedThreadId( + clientSessionId: string | null, + providerSpecificData?: Record | null, + accountKey?: string | null +): string { + if (!nonEmptyString(clientSessionId)) return ""; + return deriveStableUUIDv4( + `${CODEX_THREAD_SEED_PREFIX}${accountSeed(providerSpecificData, accountKey)}:${clientSessionId}` + ); +} + +export function getCodexClientSessionId( + headers: Headers | Record | null | undefined +): string | null { + return ( + normalizeCodexSessionId(readNamedHeader(headers, "session-id")) || + normalizeCodexSessionId(readNamedHeader(headers, "session_id")) || + null + ); +} + +/** + * One identity object for every carrier in one upstream turn. + * accountKey may be the OmniRoute connection id; it is never sent upstream. + */ export function createCodexClientIdentity( - sessionId: string | null, - providerSpecificData?: Record | null + clientSessionId: string | null, + providerSpecificData?: Record | null, + options: CodexIdentityOptions = {} ): CodexClientIdentity | null { - const normalizedSessionId = normalizeCodexSessionId(sessionId); - if (!normalizedSessionId) return null; + const mode = + options.mode ?? getCodexFingerprintMode(providerSpecificData, options.isOAuth ?? true); + if (mode === "off") return null; + + const installationId = getCodexInstallationId(providerSpecificData, options.accountKey); + if (mode === "device") { + return { + mode, + installationId, + sessionId: "", + threadId: "", + turnId: "", + windowId: "", + turnStartedAtUnixMs: Date.now(), + }; + } + + const sessionId = getCodexConvergedSessionId(providerSpecificData, options.accountKey); + const threadId = + mode === "full" + ? sessionId + : getCodexConvergedThreadId(clientSessionId, providerSpecificData, options.accountKey) || + sessionId; + return { - sessionId: normalizedSessionId, + mode, + installationId, + sessionId, + threadId, turnId: randomUUID(), - windowId: `${normalizedSessionId}:0`, - installationId: getCodexInstallationId(providerSpecificData), + windowId: `${threadId}:0`, + turnStartedAtUnixMs: Date.now(), }; } +function isCompactRequestEndpoint(path: unknown): boolean { + if (typeof path !== "string") return false; + const normalized = path.trim().toLowerCase().replace(/\\/g, "/"); + return normalized === "/compact" || /(?:^|\/)responses\/compact(?:\/|$)/.test(normalized); +} + +const CODEX_IDENTITY_HEADER_NAMES = [ + "session-id", + "session_id", + "thread-id", + "thread_id", + "x-client-request-id", + "x-codex-installation-id", + "x-codex-window-id", + "x-codex-turn-metadata", +] as const; + +type CodexCredentialIdentityInput = { + connectionId?: string; + requestEndpointPath?: string; + accessToken?: unknown; + refreshToken?: unknown; + providerSpecificData?: Record | null; +}; + +export function resolveCodexOriginalIdentityHeaders(input: { + credentials?: CodexCredentialIdentityInput | null; + clientHeaders?: Headers | Record | null; +}): Record | null { + const credentials = input.credentials; + if (!credentials || isCompactRequestEndpoint(credentials.requestEndpointPath)) return null; + const providerSpecificData = credentials.providerSpecificData ?? null; + if ( + !isCodexOAuthCredentials(credentials) || + getCodexFingerprintMode(providerSpecificData, true) !== "off" + ) { + return null; + } + + const result: Record = {}; + for (const name of CODEX_IDENTITY_HEADER_NAMES) { + const value = readNamedHeader(input.clientHeaders, name); + if (value) result[name] = value; + } + return Object.keys(result).length > 0 ? result : null; +} + +/** One identity for headers, body, nested metadata, and WS payload. Compact skips. */ +export function resolveCodexFingerprintIdentity(input: { + credentials?: CodexCredentialIdentityInput | null; + clientHeaders?: Headers | Record | null; + body?: unknown; +}): CodexClientIdentity | null { + const credentials = input.credentials; + if (!credentials || isCompactRequestEndpoint(credentials.requestEndpointPath)) return null; + + const providerSpecificData = credentials.providerSpecificData ?? null; + const isOAuth = isCodexOAuthCredentials(credentials); + if (getCodexFingerprintMode(providerSpecificData, isOAuth) === "off") return null; + + return createCodexClientIdentity( + getCodexClientSessionId(input.clientHeaders), + providerSpecificData, + { + accountKey: credentials.connectionId ?? null, + isOAuth, + } + ); +} + +export function withCodexFingerprintCredentials( + credentials: T, + clientHeaders?: Headers | Record | null, + body?: unknown +): T { + const identity = resolveCodexFingerprintIdentity({ credentials, clientHeaders, body }); + const original = resolveCodexOriginalIdentityHeaders({ credentials, clientHeaders }); + if (!identity && !original) return credentials; + return { + ...credentials, + providerSpecificData: { + ...(credentials.providerSpecificData || {}), + ...(identity ? { codexClientIdentity: identity } : {}), + ...(original ? { codexOriginalIdentityHeaders: original } : {}), + }, + }; +} + +function mergeTurnMetadata( + raw: unknown, + identity: CodexClientIdentity, + includeSessionFields: boolean +): string { + let metadata: Record = {}; + let hadExisting = false; + if (typeof raw === "string" && raw.trim()) { + try { + const parsed = JSON.parse(raw); + if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) { + metadata = parsed as Record; + hadExisting = true; + } + } catch { + // Keep non-JSON metadata only when we do not need a complete carrier. + } + } + + if (!hadExisting && includeSessionFields) { + metadata.thread_source = "user"; + metadata.sandbox = "none"; + } + + metadata.installation_id = identity.installationId; + if (includeSessionFields) { + metadata.session_id = identity.sessionId; + metadata.thread_id = identity.threadId || identity.sessionId; + metadata.turn_id = identity.turnId; + metadata.window_id = identity.windowId; + metadata.turn_started_at_unix_ms = identity.turnStartedAtUnixMs; + } + return JSON.stringify(metadata); +} + +export function applyCodexOriginalIdentityHeaders( + headers: Record, + original?: Record | null +): void { + if (!original) return; + for (const name of CODEX_IDENTITY_HEADER_NAMES) { + const value = original[name]; + if (typeof value === "string" && value) headers[name] = value; + } +} + export function applyCodexClientIdentityHeaders( headers: Record, identity?: CodexClientIdentity | null ): void { if (!identity) return; + + headers["x-codex-installation-id"] = identity.installationId; + if (identity.mode === "device") { + if (headers["x-codex-turn-metadata"] !== undefined) { + headers["x-codex-turn-metadata"] = mergeTurnMetadata( + headers["x-codex-turn-metadata"], + identity, + false + ); + } + return; + } + + headers["session-id"] = identity.sessionId; headers["session_id"] = identity.sessionId; - headers["x-client-request-id"] = identity.sessionId; + headers["thread-id"] = identity.threadId || identity.sessionId; + headers["x-client-request-id"] = identity.threadId || identity.sessionId; headers["x-codex-window-id"] = identity.windowId; - headers["x-codex-turn-metadata"] = JSON.stringify({ - session_id: identity.sessionId, - thread_source: "user", - turn_id: identity.turnId, - sandbox: "none", - }); + headers["x-codex-turn-metadata"] = mergeTurnMetadata( + headers["x-codex-turn-metadata"], + identity, + true + ); +} + +export function applyCodexClientMetadata( + body: Record, + identity?: CodexClientIdentity | null +): void { + if (!identity) return; + + const existing = + body.client_metadata && + typeof body.client_metadata === "object" && + !Array.isArray(body.client_metadata) + ? { ...(body.client_metadata as Record) } + : {}; + existing["x-codex-installation-id"] = identity.installationId; + + if (identity.mode !== "device") { + existing.session_id = identity.sessionId; + existing.thread_id = identity.threadId || identity.sessionId; + existing.turn_id = identity.turnId; + existing["x-codex-window-id"] = identity.windowId; + } + + if (existing["x-codex-turn-metadata"] !== undefined) { + existing["x-codex-turn-metadata"] = mergeTurnMetadata( + existing["x-codex-turn-metadata"], + identity, + identity.mode !== "device" + ); + } + + body.client_metadata = existing; } /** * #3697: detect the Codex CLI as the request *client* (not the routed provider) from * request headers, so the model-echo shim can fire regardless of which upstream provider * ultimately serves the request (e.g. `codex/gpt-5.5-xhigh` routed through a combo). - * Mirrors the `originator`/User-Agent detection proven in `isCodexModelCatalogClient` - * (PR #3481, `src/app/api/v1/models/catalogRequest.ts`) — Codex CLI sends an `originator` - * header of `codex_exec`/`codex_cli_rs` and a matching `codex_*` User-Agent — but works off - * a plain headers bag (`Headers` or a header-name→value record) instead of a `Request`, - * since chatCore's `clientRawRequest.headers` is not always a `Request`. */ export function isCodexOriginatedHeaders( headers: Headers | Record | null | undefined @@ -132,20 +461,3 @@ export function isVerifiedNativeCodexRequest( ): boolean { return isCodexOriginatedHeaders(headers) && hasNativeCodexTurnBinding(body); } - -export function applyCodexClientMetadata( - body: Record, - identity?: CodexClientIdentity | null -): void { - if (!identity) return; - const existing = - body.client_metadata && - typeof body.client_metadata === "object" && - !Array.isArray(body.client_metadata) - ? (body.client_metadata as Record) - : {}; - body.client_metadata = { - ...existing, - "x-codex-installation-id": identity.installationId, - }; -} diff --git a/open-sse/executors/codex.ts b/open-sse/executors/codex.ts index c2e1f6b199..93e5a2fe16 100644 --- a/open-sse/executors/codex.ts +++ b/open-sse/executors/codex.ts @@ -27,8 +27,9 @@ import { import { applyCodexClientIdentityHeaders, applyCodexClientMetadata, - createCodexClientIdentity, + applyCodexOriginalIdentityHeaders, type CodexClientIdentity, + withCodexFingerprintCredentials, } from "../config/codexIdentity.ts"; import { getAccessToken } from "../services/tokenRefresh.ts"; import { sanitizeResponsesInputItems } from "../services/responsesInputSanitizer.ts"; @@ -765,23 +766,11 @@ export class CodexExecutor extends BaseExecutor { input.model ); const requestInput = requestBody === input.body ? input : { ...input, body: requestBody }; - const sessionId = this.getPromptCacheSessionId( + const credentials = withCodexFingerprintCredentials( requestInput.credentials, - requestInput.body as Record | null + requestInput.clientHeaders, + requestInput.body ); - const identity = createCodexClientIdentity( - sessionId, - requestInput.credentials?.providerSpecificData ?? null - ); - const credentials = identity - ? { - ...requestInput.credentials, - providerSpecificData: { - ...(requestInput.credentials?.providerSpecificData || {}), - codexClientIdentity: identity, - }, - } - : requestInput.credentials; const nextInput = { ...requestInput, credentials }; if (!isCodexResponsesWebSocketRequired(nextInput.model, nextInput.credentials)) { @@ -1054,6 +1043,8 @@ export class CodexExecutor extends BaseExecutor { } const clientIdentity = credentials?.providerSpecificData?.codexClientIdentity as CodexClientIdentity | null | undefined; + const originalIdentityHeaders = credentials?.providerSpecificData + ?.codexOriginalIdentityHeaders as Record | null | undefined; // Originator header — identifies the client type to the Codex backend. // Ref: openai/codex login/src/auth/default_client.rs DEFAULT_ORIGINATOR = "codex_cli_rs" @@ -1066,6 +1057,7 @@ export class CodexExecutor extends BaseExecutor { if (cacheSessionId) { headers["session_id"] = cacheSessionId; } + applyCodexOriginalIdentityHeaders(headers, originalIdentityHeaders); applyCodexClientIdentityHeaders(headers, clientIdentity); return headers; diff --git a/scripts/dev/responses-ws-proxy.mjs b/scripts/dev/responses-ws-proxy.mjs index 7e2a5fbc15..9255d268ff 100644 --- a/scripts/dev/responses-ws-proxy.mjs +++ b/scripts/dev/responses-ws-proxy.mjs @@ -317,6 +317,17 @@ function getAuthHeaders(requestUrl, requestHeaders) { if (isText(requestHeaders["x-forwarded-for"])) { headers["x-forwarded-for"] = requestHeaders["x-forwarded-for"]; } + for (const key of [ + "session-id", + "session_id", + "x-codex-installation-id", + "x-codex-window-id", + "x-codex-turn-metadata", + "originator", + "user-agent", + ]) { + if (isText(requestHeaders[key])) headers[key] = requestHeaders[key]; + } return headers; } diff --git a/scripts/dev/v1-ws-bridge.mjs b/scripts/dev/v1-ws-bridge.mjs index 3653bd159f..05d9e31010 100644 --- a/scripts/dev/v1-ws-bridge.mjs +++ b/scripts/dev/v1-ws-bridge.mjs @@ -185,6 +185,18 @@ function getForwardHeaders(requestUrl, requestHeaders) { headers.origin = origin; } + for (const key of [ + "session-id", + "session_id", + "x-codex-installation-id", + "x-codex-window-id", + "x-codex-turn-metadata", + "originator", + "user-agent", + ]) { + if (isText(requestHeaders[key])) headers[key] = requestHeaders[key]; + } + return headers; } diff --git a/src/app/(dashboard)/dashboard/providers/[id]/components/modals/CodexFingerprintFields.tsx b/src/app/(dashboard)/dashboard/providers/[id]/components/modals/CodexFingerprintFields.tsx new file mode 100644 index 0000000000..9d13462cfb --- /dev/null +++ b/src/app/(dashboard)/dashboard/providers/[id]/components/modals/CodexFingerprintFields.tsx @@ -0,0 +1,86 @@ +import { Select, Toggle } from "@/shared/components"; +import { type CodexServiceTier } from "@/lib/providers/requestDefaults"; +import { + CODEX_ACCOUNT_SERVICE_TIER_VALUES, + CODEX_FINGERPRINT_MODE_VALUES, + CODEX_REASONING_STRENGTH_OPTIONS, + getCodexFingerprintModeLabel, + getCodexServiceTierLabel, + providerText, + type CodexFingerprintModeValue, +} from "../../providerPageHelpers"; + +type Translator = Parameters[0]; + +export function CodexConnectionFields({ + t, + reasoningEffort, + serviceTier, + fingerprintMode, + openaiStoreEnabled, + showFingerprintMode, + onChange, +}: { + t: Translator; + reasoningEffort: string; + serviceTier: CodexServiceTier; + fingerprintMode: CodexFingerprintModeValue; + openaiStoreEnabled: boolean; + showFingerprintMode: boolean; + onChange: (patch: { + codexReasoningEffort?: string; + codexServiceTier?: CodexServiceTier; + codexFingerprintMode?: CodexFingerprintModeValue; + codexOpenaiStoreEnabled?: boolean; + }) => void; +}) { + return ( +
+ ({ + value, + label: getCodexServiceTierLabel(t, value), + }))} + onChange={(event) => onChange({ codexServiceTier: event.target.value as CodexServiceTier })} + hint={providerText( + t, + "codexServiceTierDescription", + "Default uses the normal Codex tier. Priority shows as Fast; Flex uses the flex service tier when available." + )} + /> + {showFingerprintMode && ( + setFormData({ ...formData, codexReasoningEffort: e.target.value })} - hint={t("defaultThinkingStrengthHint")} - /> -