fix(oauth): merge release/v3.8.49 and fix vi.json i18n translations

This commit is contained in:
diegosouzapw
2026-07-26 10:49:15 -03:00
456 changed files with 19268 additions and 5803 deletions

View File

@@ -1027,7 +1027,7 @@ GITHUB_OAUTH_CLIENT_ID=Iv1.b507a08c87ecfe98
# Used by: open-sse/executors/base.ts — buildHeaders() dynamic lookup.
# Update these when providers release new CLI versions to avoid blocks.
CLAUDE_USER_AGENT="claude-cli/2.1.207 (external, cli)"
CLAUDE_USER_AGENT="claude-cli/2.1.219 (external, cli)"
# Disable the deterministic tool-name cloak applied on both Anthropic-bound paths
# (executors/base.ts native OAuth + executors/cliproxyapi.ts CLIProxyAPI) —

View File

@@ -477,6 +477,7 @@ jobs:
cache: npm
- uses: ./.github/actions/npm-ci-retry
- run: node scripts/i18n/check-glossary-consistency.mjs --locale=zh-CN
- run: node scripts/i18n/check-glossary-consistency.mjs --locale=zh-TW
# D4 (plano mestre testes+CI): a matrix de ~40 jobs de <1min por idioma saturava sozinha
# a concorrência de jobs da conta (Free = 20 slots, compartilhados entre TODOS os repos)
@@ -496,7 +497,7 @@ jobs:
- uses: actions/checkout@v7
with:
persist-credentials: false
- uses: actions/setup-python@v6
- uses: actions/setup-python@v7
with:
python-version: "3.12"
- name: Validate all languages
@@ -907,7 +908,7 @@ jobs:
# (if-no-files-found: warn) — Sonar consumes the same file.
- name: Upload coverage to Codecov (informational)
if: always()
uses: codecov/codecov-action@0fb7174895f61a3b6b78fc075e0cd60383518dac # v5
uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0
with:
files: coverage/lcov.info
token: ${{ secrets.CODECOV_TOKEN }}

View File

@@ -22,10 +22,10 @@ jobs:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- uses: github/codeql-action/init@7188fc363630916deb702c7fdcf4e481b751f97a # v4.37.1
- uses: github/codeql-action/init@e4fba868fa4b1b91e1fdab776edc8cfbe6e9fb81 # v4.37.3
with:
languages: javascript-typescript
queries: security-extended
- uses: github/codeql-action/analyze@7188fc363630916deb702c7fdcf4e481b751f97a # v4.37.1
- uses: github/codeql-action/analyze@e4fba868fa4b1b91e1fdab776edc8cfbe6e9fb81 # v4.37.3
with:
category: "/language:javascript-typescript"

View File

@@ -53,7 +53,7 @@ jobs:
if curl -sf http://localhost:20128/api/monitoring/health >/dev/null; then echo up; break; fi
sleep 2
done
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: "3.12"
- run: pip install schemathesis

View File

@@ -90,7 +90,7 @@ jobs:
if curl -sf http://localhost:20128/api/monitoring/health >/dev/null; then echo up; break; fi
sleep 2
done
- uses: actions/setup-python@v6
- uses: actions/setup-python@v7
if: steps.gate.outputs.run == 'true'
with: { python-version: "3.12" }
- run: pip install garak

View File

@@ -35,7 +35,7 @@ jobs:
if curl -sf http://localhost:20128/api/monitoring/health >/dev/null; then echo "server up"; break; fi
sleep 2
done
- uses: actions/setup-python@v6
- uses: actions/setup-python@v7
with: { python-version: "3.12" }
- name: Install schemathesis
run: pip install schemathesis

View File

@@ -26,7 +26,7 @@ jobs:
persist-credentials: false
- name: Run analysis
uses: ossf/scorecard-action@v2.4.3
uses: ossf/scorecard-action@v2.4.4
with:
results_file: results.sarif
results_format: sarif

View File

@@ -78,18 +78,15 @@ export function registerBackup(program) {
if (exitCode !== 0) process.exit(exitCode);
});
// Legacy: `omniroute backup` without subcommand still creates a backup
// Legacy: `omniroute backup` without a subcommand still creates a backup
// (documented as the canonical usage in USER_GUIDE.md / CLI-TOOLS.md /
// AGENT-SKILLS.md). No flags are declared here — declaring the same
// option names as `create`/`auto enable` here previously shadowed them
// (#8512), and no doc shows `omniroute backup` invoked with flags.
backup.action(async (opts) => {
const exitCode = await runBackupCommand(opts);
if (exitCode !== 0) process.exit(exitCode);
});
backup
.option("--name <name>", t("backup.nameOpt"))
.option("--cloud", t("backup.cloudOpt"))
.option("--encrypt", t("backup.encryptOpt"))
.option("--key-file <path>", t("backup.keyFileOpt"))
.option("--exclude <pattern>", t("backup.excludeOpt"), (v, prev = []) => [...prev, v], [])
.option("--retention <n>", t("backup.retentionOpt"), parseInt);
}
export function registerRestore(program) {

View File

@@ -26,6 +26,7 @@ function wantsProviderSetup(opts) {
async function resolvePassword(opts, prompt, nonInteractive) {
if (opts.password) return opts.password;
if (process.env.INITIAL_PASSWORD) return process.env.INITIAL_PASSWORD;
if (nonInteractive) return "";
const answer = await prompt.ask("Set an admin password now? [y/N]", "N");

View File

@@ -5,15 +5,34 @@ import { ensureSettingsSchema, hashManagementPassword, updateSettings } from "./
async function loadSqlite() {
if (process.versions.bun) {
return (await import("bun:sqlite")).Database;
return { Database: (await import("bun:sqlite")).Database };
}
try {
return (await import("better-sqlite3")).default;
} catch {
throw new Error("better-sqlite3 is not installed. Run npm install before using setup.");
return { Database: (await import("better-sqlite3")).default };
} catch (error) {
return { error };
}
}
// #7586: unlike the real server (src/lib/db/adapters/driverFactory.ts::tryOpenSync),
// this CLI helper historically had NO fallback beyond better-sqlite3 — so on any
// machine where better-sqlite3's native binary is unavailable (Windows without a
// prebuilt addon, etc.), every `omniroute doctor` DB check reported a false FAIL
// even when the actual server was healthy via its own (correct) driver cascade.
// Reuse that same cascade here instead of re-deriving it.
async function openWithSyncDriverFallback(dbPath, options, importError) {
try {
const { tryOpenSync } = await import("../../src/lib/db/adapters/driverFactory.ts");
const adapter = tryOpenSync(dbPath, options);
if (adapter) {
return adapter;
}
} catch {
// fall through to the original better-sqlite3 error below
}
throw createSqliteNativeError(importError);
}
function openBunSqlite(Database, dbPath, options) {
const raw = new Database(dbPath, options);
const prepare = (sql) => {
@@ -91,19 +110,25 @@ export function createSqliteNativeError(error) {
}
async function openSqliteDatabase(dbPath, options = {}) {
const Database = await loadSqlite();
const loaded = await loadSqlite();
if (process.versions.bun) {
if (options.fileMustExist && !fs.existsSync(dbPath)) {
throw new Error(`SQLite file does not exist: ${dbPath}`);
}
options = options.readonly
const bunOptions = options.readonly
? { readonly: true }
: { readwrite: true, create: options.fileMustExist !== true };
try {
return openBunSqlite(loaded.Database, dbPath, bunOptions);
} catch (error) {
throw createSqliteNativeError(error);
}
}
if (loaded.error) {
return openWithSyncDriverFallback(dbPath, options, loaded.error);
}
try {
return process.versions.bun
? openBunSqlite(Database, dbPath, options)
: new Database(dbPath, options);
return new loaded.Database(dbPath, options);
} catch (error) {
throw createSqliteNativeError(error);
}

View File

@@ -0,0 +1 @@
- feat(db): persist caller session tag into call_logs for per-session cost attribution (#8249)

View File

@@ -0,0 +1 @@
- feat(api): quota-aware fallback routing for web-fetch providers (#8297)

View File

@@ -0,0 +1 @@
- feat(providers): map upstream reasoning-level metadata in openai-compatible discovery (#8347)

View File

@@ -0,0 +1 @@
- **feat(adobe-firefly):** reference-image attach for generate + OpenAI `/v1/images/edits` support (follow-up to #8006). Uploads sources to Firefly storage (`POST /v2/storage/image`), then submits `referenceBlobs` on 3P generate-async (nano multi-ref `usage:general`; gpt-image `usage:subject`). Wire matches live `firefly.adobe.com` captures. Also routes built-in edits to the same path (up to 4 refs).

View File

@@ -0,0 +1 @@
- fix(providers): expose a base-URL override for Kimi/Moonshot so CN-region API keys (issued on platform.kimi.com / moonshot.cn) can be pointed at api.moonshot.cn instead of being rejected by the international host (#7447)

View File

@@ -0,0 +1 @@
- fix(sse): stop stream readiness from treating a choices-less mid-stream error frame as a successful stream, so combo can fail over instead of returning zero `choices` (#7503)

View File

@@ -0,0 +1 @@
- fix(cli): fall back to the node:sqlite driver cascade in `bin/cli/sqlite.mjs` so `omniroute doctor` no longer reports a false "FAIL Database"/"FAIL Storage/encryption" on machines without a working better-sqlite3 native binary (#7586)

View File

@@ -0,0 +1 @@
- fix(api): expose Responses-API-format (OpenAI/Codex) chat models on every VS Code Ollama-compatible listing route, not just `/models` (#7587)

View File

@@ -0,0 +1 @@
- fix(backend): stop `buildClientRawRequest` deep-cloning the whole request body on every chat request (#7847) — every consumer of `clientRawRequest.body` is observability and keeps at most a bounded copy, so the unbounded clone retained ~41x more than anything used it (3.19 MiB vs 0.08 MiB on a 3.05 MiB / 729-message agent request). Also makes `cloneBoundedForLog` idempotent: arrays, objects and strings all exceeded their own bounds once the truncation marker was added, so re-bounding an already bounded payload silently dropped a further item and misreported the original length

View File

@@ -0,0 +1 @@
- fix(sse): copy the combo attempt body shallowly instead of deep-cloning it per target (#7847) — the deep clone cost 9.53 MiB at 3 targets and scaled linearly with the target count (31.78 MiB at 10) on a 3.05 MiB agent request, while the isolation it provided only ever needed to contain top-level scalar writes. Also fixes a real cross-target leak in round-robin, which copied the body only when the reasoning buffer changed `max_tokens` and otherwise shared the caller's object, so a Background Task Redirection on one target rewrote `body.model` for the next

View File

@@ -0,0 +1 @@
- fix(sse): estimate the combo fallback-compression trigger from the request object instead of `JSON.stringify(...)` (#7847) — the string path charged an inline base64 image as if every character were prose (~50k tokens instead of ~1.2k on a 200 KB image), falsely tripping compression on requests nowhere near the context window; the same over-count #8368/#8401 fixed elsewhere. Adds `jsonLength()`, an exact serialized-length walker (property-tested against `JSON.stringify`), and uses it for the readiness-timeout and token estimates so a multi-megabyte body is no longer materialized as a string just to be measured

View File

@@ -0,0 +1 @@
- fix(providers): repoint the zai-web executor at chat.z.ai's current v2 chat-completions endpoint, fixing model-independent 404s (#8014)

View File

@@ -0,0 +1 @@
- **fix(providers):** path-shaped multimodal model ids (e.g. `cp/cline-pass/kimi-k3`) resolve native vision via leaf/registry metadata instead of triggering Vision Bridge ([#8032](https://github.com/diegosouzapw/OmniRoute/issues/8032)) — thanks @Prudhvivuda

View File

@@ -0,0 +1 @@
- fix(translator): set `status: "completed"` on translated OpenAI Responses `input` items so strict Responses-compatible upstreams stop rejecting them with 400 MissingParameter input.status (#8083)

View File

@@ -0,0 +1 @@
- **fix(i18n):** Restore brand/model proper nouns (Claude, OpenAI, Anthropic, Gemini, MiniMax, etc.) in zh-CN and zh-TW — replace Chinese phonetic/translation forms (克劳德/打开Ai/人择/双子座) with original English, unify "provider" translation to "供应商/供應商", and apply zh-TW localized terminology (網路/設定/檔案/新增/啟用/搜尋/儲存) instead of mainland defaults (#8355 — thanks @ikelvingo).

View File

@@ -0,0 +1 @@
- fix(api): estimate inline base64 image tokens instead of counting the data URL as text so it does not falsely exceed the context window (#8368)

View File

@@ -0,0 +1 @@
- fix(backend): stop prompt-cache affinity from silently reordering an explicit priority combo across models (#8370)

View File

@@ -0,0 +1 @@
- fix(api): accept a missing status query-param on GET /api/plugins instead of rejecting null with Invalid status value (#8374)

View File

@@ -0,0 +1 @@
- fix(resilience): treat an unreachable-proxy ECONNREFUSED as a circuit-breaker event so combo fails over instead of hitting the 503 max-retry limit (#8376)

View File

@@ -0,0 +1 @@
- fix(backend): make disabling the global per-key proxy toggle override existing per-key proxy assignments (#8385)

View File

@@ -0,0 +1 @@
- fix(dashboard): persist compression engine detail settings (Headroom / session dedup / CCR) instead of dropping them on save (#8388)

View File

@@ -0,0 +1 @@
- fix(plugins): fire registered+active plugin hooks (onRequest/onResponse/onError) during proxying instead of never invoking them (#8395)

View File

@@ -0,0 +1 @@
- fix(resilience): cap the connection cooldown after a 429 burst so combo fallback is not blacked out past the real rate-limit window (#8396)

View File

@@ -0,0 +1 @@
- fix(api): reach synced model_capabilities rows for canonical provider ids that only appear as an alias in MODELS_DEV_PROVIDER_MAP, e.g. codex/claude (#8429)

View File

@@ -0,0 +1 @@
- fix(providers): stop marking a multi-quota-window provider exhausted when only some windows are depleted (LIMIT-200 snapshot eviction drops idle healthy windows) (#8431)

View File

@@ -0,0 +1 @@
- fix(backend): compute AgentBridge diagnose `dnsConfigured` per-agent instead of hard-coded to Antigravity hosts (#8466)

View File

@@ -0,0 +1 @@
- **fix(providers):** OpencodeExecutor honors Extra API Keys rotation via `resolveEffectiveKey` (empty primary + extras no longer omit Authorization) ([#8467](https://github.com/diegosouzapw/OmniRoute/issues/8467)) — thanks @Prudhvivuda

View File

@@ -0,0 +1 @@
- fix(sse): stop combo's "all targets failed" response from attaching one target's retry-after window to an unrelated target's error message (#8486)

View File

@@ -0,0 +1 @@
- fix(providers): persist a runtime-discovered Antigravity projectId back onto the connection so it survives token refreshes and restarts instead of being rediscovered or lost (#8491)

View File

@@ -0,0 +1 @@
- fix(cli): `backup create` / `backup auto enable` — option shadowing by the parent `backup` command removed; all flags (`--cloud`, `--encrypt`, `--retention`, `--name`, `--exclude`, `--key-file`) now reach the subcommand handler with their actual values instead of being silently discarded

View File

@@ -0,0 +1 @@
- fix(api): surface a non-blocking warning + startup scan when a combo name shadows a real model id, instead of silently routing with zero signal (#8530)

View File

@@ -0,0 +1 @@
- **fix(kiro):** support profileless Builder ID quota, preserve CLI auth identity, stabilize social OAuth polling, and use the live model catalog ([#8565](https://github.com/diegosouzapw/OmniRoute/pull/8565)) — thanks @nguyenha935

View File

@@ -0,0 +1 @@
- **chore(quality):** rebaseline complexity (2130→2183) and cognitive-complexity (951→968) across the v3.8.49 `/merge-prs` queue-drain. The first step (→2169/→956) cleared inherited base drift measured on the pristine release tip (the PR→release fast-path never ratchets these). The second step (→2183/→968) absorbs the aggregate own-growth of the 41-PR merge-train (each PR under-ceiling individually; the combined batch adds +14/+12). Owner-approved (2026-07-25); structural shrink tracked in [#3501](https://github.com/diegosouzapw/OmniRoute/issues/3501).

View File

@@ -0,0 +1 @@
- **chore(combo):** extract 8 pure error predicates and quota status helpers (`clampPercent`, `quotaRemainingPercentFromQuota`, `normalizeConnectionStatus`, `hasFutureRateLimitUntil`, `getConnectionStatusQuotaCutoffReason`, `isContextOverflow400`, `isParamValidation400`, `isModelScoped400`) from `open-sse/services/combo.ts` into `open-sse/services/combo/comboPredicates.ts` — pure move, zero behavior change; `combo.ts` shrinks from 3,651 to 3,554 lines while maintaining backward-compatible re-exports.

View File

@@ -0,0 +1 @@
- chore(validation): decompose `src/lib/providers/validation.ts` (→ 442 lines) by extracting the web-cookie, kiro and specialty inline validators into `validation/*` leaves — behavior-preserving move; the specialty validators that captured `isLocal` from the enclosing closure now take it as an explicit parameter, with the host dispatcher passing it at each call site

View File

@@ -0,0 +1 @@
- chore(token-refresh): decompose `open-sse/services/tokenRefresh.ts` (999 → 724 lines) by extracting the rotation-map, CAS guard and circuit-breaker refresh logic into `tokenRefresh/*` leaves — behavior-preserving move; `tokenRefresh.ts` still re-exports the moved symbols so the public surface is unchanged

View File

@@ -0,0 +1 @@
- chore(usage): decompose `open-sse/services/usage.ts` (999 → 253 lines) by extracting the crof, nanogpt, qoder, opencode, deepseek, bailian, vertex, xiaomi-mimo, xai and github usage fetchers into `usage/*` leaves — behavior-preserving move, the file is now a thin provider→fetcher dispatcher and the public import surface is unchanged

View File

@@ -0,0 +1 @@
- chore(perf): add `npm run bench:heap-body` — a deterministic benchmark that attributes retained V8 heap to each request-body copy on the chat path (entry log clone, combo per-target clone, token-estimation string), reproducing the #7847 incident shape (3.05 MiB / 729 messages / 86 tools) so the clone-amplification work can be justified and regression-guarded with numbers instead of intuition

View File

@@ -0,0 +1 @@
- chore(ci): resync the stale `no-explicit-any` suppression count for `tests/unit/proxy-registry.test.ts` (frozen at 55, actual 54 since #8447) — ESLint was failing the whole run with "There are suppressions left that do not occur anymore", turning `npm run lint` red on `release/v3.8.49` for every PR branched off it

View File

@@ -1,7 +1,8 @@
{
"_comment": "Catraca de complexidade (check-complexity.mjs, ESLint core rules complexity>=15 e max-lines-per-function>80 sobre src+open-sse+electron+bin via eslint.complexity.config.mjs). Conta total de violacoes; so pode cair. --update ratcheta.",
"_rebaseline_2026_07_20_owner_night_drain": "Owner-approved (chat, 2026-07-20 ~00:50): 2072->2130. The day's 17 merged PRs consumed the entire slack (tip at 2069/2072); queue PRs #6973(+4)/#7662(+2)/#7719(+1) plus the #7744/#7779 reworks were collectively blocked. Owner chose a wide margin for the remainder of the v3.8.49 cycle instead of per-PR extraction.",
"count": 2130,
"_rebaseline_2026_07_25b_v3849_mergetrain_owngrowth": "Owner-approved (chat, 2026-07-25): 2169->2183 (+14). v3.8.49 /merge-prs 41-PR merge-train aggregate own-growth: measured 2183 on the combined boarded tree (tip ac15014ca7) vs 2169 on the pristine release tip. Each boarded PR sits under the ceiling individually, but the combined batch adds +14 (new branches in #8378 chatCore contextLimit / #8432 cursor native_todo / #8476 combo input-bound / #8526 combo select-all modals / etc — the pre-screen-flagged complexity-growth set). Same merge-burst-inherited-drift class as the notes below; owner chose absorbing the ceiling over per-PR helper-extraction churn. Structural shrink stays debt (#3501); tighten via --update next cycle.",
"_rebaseline_2026_07_25_v3849_mergequeue_drain": "Owner-approved (chat, 2026-07-25): 2130->2169 (+39). v3.8.49 /merge-prs queue-drain: the cycle's merge burst (the 8 base-red slices + owner PRs + parallel-session merges #8500-8508) accrued inherited cyclomatic drift the fast-path PR->release never ratchets (check:complexity does not run on PR->release). Measured 2169 on the pristine release tip 4053e2314a alone (BEFORE any queue PR boards) — so the entire +39 is base drift already on the tip, not any queued PR's own growth. Every merge-ready PR in the queue was tripping Fast Quality Gates on this shared base-red. Owner approved raising the ceiling to the measured tip value so the ~34-PR merge-train lands without per-PR helper-extraction churn. Structural shrink stays debt (#3501); tighten via --update next cycle.",
"count": 2183,
"_rebaseline_2026_07_19_v3849_fix_sweep_cluster": "2059->2072 (owner-approved, 2026-07-19). /fix-prs validation-train sweep: a cluster of otherwise-clean contributor PRs (#6973/#7683/#7662/#7672/#7633/#7767, each +1/+2 cyclomatic own-growth from new provider/auth/combo branches) collectively pushed the count from tip 2056 to 2068. Individually all but #6973 sit under the old 2059 baseline; combined they exceed it. The tip had only 3 units of slack (2056 vs 2059), so every new-feature PR was tripping the ratchet (this was the 4th such block of the day after #7695/#7747/#7768). Owner approved raising the ceiling to 2072 = combined-cluster 2068 + 4 units headroom, so the cluster lands without per-PR helper-extraction churn and near-term feature PRs have breathing room. Measured 2068 on the 9-PR combined probe tree. Structural shrink stays debt (#3501); tighten via --update next cycle.",
"_rebaseline_2026_07_18_pr7360_quota_visibility_resync": "2058->2059 (+1 vs recorded ceiling; measured 2056 fresh on release tip cab9e5f0c alone, so this ceiling still carries 2 units of un-banked slack from prior shrinkage — real regression from this merge is 2056->2059, +3). PR #7360 (JxnLexn) release-resync: merging origin/release/v3.8.49 to resolve the 3-file conflict (ConnectionRow.tsx/ConnectionsListPanel.tsx/useProviderConnections.ts) unions two already-compliant features in the same already-oversized god-component: release's confirm-delete-account wiring (#7361) and this PR's per-connection quota-visibility wiring. Diffed release-tip-only vs merged violation lists (scripts dumped via getComplexityEslintReport): most entries are the SAME pre-existing violations shifted a few lines (ConnectionRow/getStatusPresentation/inferErrorType — no count change) or marginally bigger (ConnectionRow function complexity 85->86, ConnectionsListPanel function 498->510 lines) from the two ConnectionRow call sites each gaining both PRs' multi-line JSX props. The 2 genuinely NEW crossings are the 'no tag' and 'tagged groups' .map() render callbacks in ConnectionsListPanel.tsx (83 and 85 lines, was <=80 on both parents individually) tipping over 80 lines specifically because both PRs' props land on the same call sites. No new logic was written during the resync itself (only import-statement unions); the growth is inherent to combining the two already-reviewed feature branches. Structural shrink tracked in #3501. Tighten via --update next cycle (true floor is 2056, not 2058).",
"_rebaseline_2026_07_17_v3849_ownerprs_providers": "2056->2058 (+2). v3.8.49 owner-PR merge campaign own-growth: the new provider handlers/dispatch branches merged this cycle (freetheai/felo/notion/segmind/deepinfra/novita/msdesigner image+video handlers, each adding a format-dispatch guard) pushed cyclomatic violations 2056->2058. Fast-gates PR->release do not run the complexity ratchet, so this surfaced only on re-sync. Spread across the new leaf handlers (not a single extractable function); measured on the release tip. Structural shrink tracked in #3501.",

View File

@@ -4,11 +4,6 @@
"count": 1
}
},
"open-sse/executors/claudeIdentity.ts": {
"@typescript-eslint/no-explicit-any": {
"count": 2
}
},
"open-sse/executors/cliproxyapi.ts": {
"@typescript-eslint/no-explicit-any": {
"count": 1
@@ -415,11 +410,6 @@
"count": 1
}
},
"src/shared/components/KiroSocialOAuthModal.tsx": {
"react-hooks/exhaustive-deps": {
"count": 1
}
},
"src/shared/components/LanguageSelector.tsx": {
"@next/next/no-img-element": {
"count": 1
@@ -890,11 +880,6 @@
"count": 8
}
},
"tests/unit/claude-to-openai-think-close-5123.test.ts": {
"@typescript-eslint/no-explicit-any": {
"count": 2
}
},
"tests/unit/cli-a2a-invoke-commands.test.ts": {
"@typescript-eslint/no-explicit-any": {
"count": 16
@@ -1947,7 +1932,7 @@
},
"tests/unit/proxy-registry.test.ts": {
"@typescript-eslint/no-explicit-any": {
"count": 55
"count": 54
}
},
"tests/unit/proxy-resolution-status-filter.test.ts": {

View File

@@ -1,4 +1,5 @@
{
"_rebaseline_2026_07_25_8499_ts7_result_union_predicates": "PR #8499 (backryun, chore/ts7-types-executor-scattered) own growth: muse-spark-web.ts 1396->1405 (+9, irreducible). Under this workspace's `strictNullChecks: false`, the boolean-literal discriminant on `GraphqlResult` (`{ ok: true } | { ok: false; error: string }`) narrows the positive `.ok===true` branch but leaves `!result.ok` at the full union under TS7, making `.error` unreachable to the checker at the two call sites (warmup, mode-switch). Fixed by adding a single `isGraphqlFailure()` type-predicate helper (doc comment + 3-line body) reused at both call sites instead of duplicating the predicate inline — not extractable to a shared module without splitting a single-file executor's local narrowing helper out of its own file. Covered by the existing muse-spark-web executor test suite (no behavior change, pure narrowing fix).",
"_rebaseline_2026_07_22_8131_windowshide_cloudflared_spawn": "PR #8167 (Dingding-leo, fix/windows-hide-child-process, #8131) own growth: src/lib/cloudflaredTunnel.ts 934->935 (+1, irreducible call-site wiring — the single `windowsHide: true` option added to the existing cloudflared spawn() options object so no transient conhost.exe/cmd console window flashes open on Windows). Covered by the pre-merge-fix regression test tests/unit/windows-hide-child-process-spawns-8131.test.ts (added for the two additional spawn() sites the PR missed: ServiceSupervisor.ts, versionManager/processManager.ts) plus the windowsHide assertion added to tests/unit/services/installers/runNpm-shell-5379.test.ts (installers/utils.ts buildNpmExecOptions).",
"_rebaseline_2026_07_22_8006_adobe_firefly_media_provider": "PR #8006 (artickc, feat/adobe-firefly-media) own growth: adds Adobe Firefly as a media-only (image + video) provider — unofficial IMS/cookie-session bridge for firefly.adobe.com covering IMS cookie->access_token exchange, discovery-catalog fallback, credits/balance usage, and submit+poll dispatch for both image (nano-banana/gpt-image families) and video (Sora 2/Veo 3.1/Kling 3.0) generation, with 408-under-load retry handling. New leaf open-sse/services/adobeFireflyClient.ts frozen at 1958 (>>cap 800) — a single self-contained upstream client (mirrors the qoderCli.ts precedent for a new provider client that is legitimately large on day one: IMS auth, cookie/JWT normalization, payload builders for 2 media types x multiple model families, SSE-less submit/poll state machine, error sanitization); not extractable without scattering a single upstream integration across artificial module boundaries mid-PR. open-sse/config/imageRegistry.ts (existing, previously under cap) grows 800->821 (+21, the new adobe-firefly IMAGE_PROVIDERS entry + models list, additive registry data at the existing registry chokepoint). src/lib/usage/providerLimits.ts 1000->1003 (+3, adobe-firefly/firefly added to the existing apikey-usage-fetcher allowlist, irreducible call-site wiring mirroring the sibling #7994 PromptQL/HyperAgent entries in the same PR group). Covered by tests/unit/adobe-firefly.test.ts (35/35). Structural shrink tracked in #3501.",
"_rebaseline_2026_07_22_7994_hyperagent_web_provider": "PR #7994 (artickc, feat/hyperagent-web) own growth: adds HyperAgent (hyperagent.com) as a new unofficial web-cookie chat provider, reverse-engineered from live SPA captures (thread/session SSE flow, credits/usage endpoint). New leaf open-sse/executors/hyperagent.ts frozen at 937 (>cap 800) — single self-contained executor covering cookie auth, SSE parsing (text/session_start/session_end/done events), and a sticky thread/session cache for multi-turn continuity; not extractable without splitting the executor mid-request-flow (mirrors the sseParser.ts/muse-spark-web.ts precedent for new provider executors that exceed cap on day one). src/lib/usage/providerLimits.ts 1000->1003 (+3, irreducible call-site wiring adding hyperagent/ha to the existing USAGE_FETCHER_PROVIDERS-style allowlist at the chokepoint other web-cookie providers already extend). Covered by tests/unit/executor-hyperagent.test.ts (16/16). Structural shrink tracked in #3501.",
@@ -175,7 +176,7 @@
"open-sse/executors/duckduckgo-web.ts": 925,
"open-sse/executors/grok-web.ts": 1873,
"open-sse/executors/hyperagent.ts": 937,
"open-sse/executors/muse-spark-web.ts": 1396,
"open-sse/executors/muse-spark-web.ts": 1405,
"open-sse/executors/perplexity-web.ts": 1032,
"open-sse/handlers/audioSpeech.ts": 1061,
"open-sse/handlers/chatCore.ts": 5125,
@@ -186,7 +187,8 @@
"open-sse/handlers/videoGeneration.ts": 1275,
"_rebaseline_2026_07_22_8010_codex_responses_engine": "PR #8010 (@JxnLexn) own growth: open-sse/mcp-server/schemas/tools.ts 1497->1505 (+8 = threading the new \"codex-responses\" literal into the compressionConfigureInput strategy/autoTriggerMode Zod enums and setCompressionEngineInput engine enum, mirroring the existing rtk/omniglyph enum entries; no new tool). open-sse/services/compression/strategySelector.ts 1043->1054 (+11 = one new `if (mode === \"codex-responses\")` dispatch branch in runCompression that delegates 100% to the new codexResponsesEngine.apply, mirroring the existing rtk single-mode dispatch, plus threading config.codexResponsesConfig.preserveToolNames into the shared adaptBodyForCompression call at the 3 existing call sites). src/lib/db/compression.ts (untracked, new-file cap 800) 794->845 (+51 = normalizeCodexResponsesConfig, mirroring the existing normalizeRtkConfig normalizer, plus registering \"codex-responses\" in the COMPRESSION_MODES/STACKED_PIPELINE_ENGINE_IDS/SINGLE_MODE_ENGINE sets and the getCompressionSettings load/save switch) — added to the baseline at its current size. All three are cohesive dispatch/normalizer wiring at existing chokepoints (mirroring the prior compression-mode rebaselines #6534/#6556), not extractable without hiding the mode-dispatch boundary. Covered by tests/unit/compression/codex-responses.test.ts (6) + omniglyph-registries.test.ts/types.test.ts (22, updated for the new mode).",
"_rebaseline_2026_07_22_8034_compression_exclusions_persistence": "#8034 (compression exclusions) own growth: src/lib/db/compression.ts 845->850 (+5 = threading the new compressionExclusions field through the existing getCompressionSettings/saveCompressionSettings load/save switch over the shared key_value compression namespace — no new table, no raw SQL). Mirrors the prior compression-field rebaselines (#8010 codex-responses normalizer at the same chokepoint); the load/save switch is a single dispatch boundary, not extractable without hiding it. Covered by the PR's 8 node:test + 3 vitest cases.",
"src/lib/db/compression.ts": 866,
"_rebaseline_2026_07_24_8388_compression_detail_persist": "#8388 (compression engine DETAIL settings — Headroom/session-dedup/CCR — dropped on save) own growth: src/lib/db/compression.ts 866->872 (+6 = irreducible call-site wiring at the existing getCompressionSettings/updateCompressionSettings chokepoint: one import line, one `...buildDetailConfigDefaults()` spread in the seed config, and one `case \"sessionDedup\": case \"ccr\": applyDetailConfigUpdate(config, key, parsed); break;` load-switch case, mirroring the existing headroom/#8056 case immediately above it). The actual normalizer logic (normalizeSessionDedupConfig/normalizeCcrConfig, matching SESSION_DEDUP_SCHEMA/CCR_SCHEMA bounds) was EXTRACTED into a new leaf src/lib/db/compressionDetailNormalizers.ts (well under cap) so this frozen file only carries the minimal dispatch wiring. Covered by tests/unit/8388-compression-detail-persist.test.ts (schema-accept + full DB save->reload round-trip for both new sub-objects, plus a no-regression assertion on the existing headroom round-trip).",
"src/lib/db/compression.ts": 872,
"open-sse/mcp-server/schemas/tools.ts": 1505,
"open-sse/mcp-server/server.ts": 1555,
"open-sse/mcp-server/tools/advancedTools.ts": 1120,
@@ -194,8 +196,9 @@
"_rebaseline_2026_07_22_8213_gemini_tpm_quota_cooldown_wait": "PR #8213 (hartmark, fix/gemini-tpm-quota-cooldown-wait) own growth: open-sse/services/accountFallback.ts 1857->1932 on the merged tip (release 1892 incl #8050 +35, plus this PR own growth +40); measured against the PR own merge-base was 1857->1898 (+41 — the release tip separately carries an unrelated +34 from #8050's antigravity 404 model-not-found lockout scoping, which this PR's branch does not include and this entry does not cover). Own growth is the Gemini TPM-ceiling classification + cooldown-wait wiring feeding into the combo cooldown-wait state machine (rate-limit wedge recovery) introduced by this PR's commit series. Irreducible additions at the existing account-fallback/model-lockout chokepoint. Covered by the PR's own gemini-rate-limit-tracker and TPM-ceiling benchmark test additions.",
"_rebaseline_2026_07_23_8252_combo_400_advance": "#8252 (@RaviTharuma) own growth: accountFallback.ts 1932->1940 (+8) + combo.ts 3604->3630 (+26) — advance combo on model-scoped 400s wrapped as invalid/Bad-Request. Irreducible wiring at existing account-fallback + combo dispatch chokepoints. Covered by combo-model-scoped-400-advance.test.ts.",
"_rebaseline_2026_07_23_8247_8248_model_unhealthy": "#8247+#8248 own growth: accountFallback.ts 1940->1941 (+1, irreducible import statement only — the substantive #8248 DEGRADED-pattern classifier was extracted into open-sse/config/errorConfig.ts, which has ample headroom, instead of growing this frozen file; #8247's fix is a single existing-line condition change, net zero lines). Scoping the credits-exhausted 403/429 branch to isCompatibleProvider() (per-model-quota openai/anthropic-compatible-* nicknames) so it stays model-scoped instead of terminalling the whole connection, and classifying NVIDIA NIM 'Function ... DEGRADED' 400 bodies as model-access-denied instead of a raw passthrough 400. Covered by tests/unit/8247-accountfallback-model-unhealthy.test.ts and tests/unit/8248-accountfallback-nvidia-degraded.test.ts.",
"open-sse/services/accountFallback.ts": 1941,
"open-sse/services/adobeFireflyClient.ts": 1958,
"open-sse/services/accountFallback.ts": 1966,
"open-sse/services/adobeFireflyClient.ts": 2317,
"_rebaseline_2026_07_25_adobe_firefly_reference_images": "Follow-up to #8006: storage upload + referenceBlobs for image/video and /v1/images/edits dispatch. adobeFireflyClient.ts 1958->2317 (+upload helpers, extract sources, resolve blob ids). Note: 2317 not 2316 — check-file-size.mjs counts LOC via split(\"\\n\").length (counts the trailing-newline empty element), which is 1 higher than `wc -l` on a file ending in \\n; the PR's original entry (2316) was measured with wc -l and undercounted by 1 against the actual gate.",
"open-sse/services/batchProcessor.ts": 915,
"open-sse/services/browserBackedChat.ts": 850,
"open-sse/services/claudeCodeCompatible.ts": 1202,
@@ -204,7 +207,8 @@
"_rebaseline_2026_06_24_quota_share_strategy": "Dedicated quota-share strategy (Phase 3 #9): combo.ts 3180->3190 (+10 = one new `else if (strategy === \"quota-share\")` dispatch branch in handleComboChat that delegates 100% to selectQuotaShareTarget + its log line, plus the import). All the new logic lives OUT of the god-file in two new leaves under open-sse/services/combo/: quotaShareInflight.ts (in-flight counter with TTL/lease, ~150 LOC <cap) and quotaShareStrategy.ts (per-model bucket gating via isBucketSaturated + DRR proportional to weight + P2C over in-flight, ~240 LOC <cap). Only the dispatch wiring is irreducible at the existing combo strategy chokepoint (mirrors the headroom/reset-aware/reset-window/context-optimized branches); not extractable without hiding the call site. ZERO existing strategy cases were modified — only this branch was added, and the qtSd/ combos switched from fill-first to quota-share in src/lib/quota/quotaCombos.ts. Covered by tests/unit/quota-share-strategy.test.ts (gating, DRR fairness, P2C in-flight, fail-open, activation). Structural shrink of combo.ts tracked in #3501.",
"_rebaseline_2026_06_24_task_aware_routing": "Task-aware routing strategy (port PR #2045, OmniRoute #4945): combo.ts 3190->3225 (+35) = one new `else if (strategy === \"task-aware\")` dispatch branch delegating 100% to selectTaskAwareTarget + its imports/log lines. All scoring/classification logic lives OUT of the god-file in the new leaf open-sse/services/taskAwareRouting.ts (553 LOC <cap). Only the dispatch wiring is irreducible at the existing combo strategy chokepoint (mirrors quota-share/headroom/reset-aware branches). ZERO existing strategy cases modified. Covered by tests/unit/combo-task-aware.test.ts (35 tests). Structural shrink of combo.ts tracked in #3501.",
"_rebaseline_2026_07_22_8213_combo_cooldown_wait_recording": "PR #8213 (hartmark, fix/gemini-tpm-quota-cooldown-wait) own growth: open-sse/services/combo.ts 3548->3604 (+56, entirely this PR's diff — no other commit touched this file between the PR's merge-base and the release tip). Fixes combo cooldown-wait state recording so a bogus 503 is no longer crystallized when the cooldown-wait vars reset every setTry, adds an OpenAI-format SSE error frame path for combo-exhausted rejections (capturing request body + attempted models), and gives an abandoned per-target dispatch its own timeout instead of leaking a permanent 'pending' dashboard entry. Irreducible additions at the existing handleComboChat dispatch/retry chokepoint (mirrors the prior quota-share/headroom/task-aware strategy-branch precedents already frozen in this file). Covered by the PR's own combo-config + Gemini TPM-ceiling benchmark test additions.",
"open-sse/services/combo.ts": 3630,
"_rebaseline_2026_07_25_8476_combo_input_bound_homogeneous_scope": "PR #8476 (herjarsa, fix/8375-8459-combo-image-fixes, #8375) own growth: open-sse/services/combo.ts 3642->3679 (+37 net: +29 the PR's own isInputBoundFailure short-circuit for deterministic context_length_exceeded/context_window_exceeded failures, +8 a /green-prs pre-merge fix scoping that short-circuit to homogeneous remainders only — the shipped code fired unconditionally on ANY target, regressing the intentional heterogeneous-combo fallback #6637/isContextOverflow400 protects, exactly as flagged by this PR's own review evidence but never actually implemented in the branch). The fix compares orderedTargets[i+1..] modelStr against the failing target's modelStr at the existing executeTarget dispatch chokepoint (mirrors the sameProviderNext precedent a few lines below) — irreducible call-site wiring, not extractable without hiding the dispatch boundary. Covered by tests/unit/combo-input-bound-failure-8375.test.ts (homogeneous pool still short-circuits) and the new tests/unit/combo-input-bound-heterogeneous-8375.test.ts (heterogeneous combo now correctly falls through to the larger-context target).",
"open-sse/services/combo.ts": 3679,
"_rebaseline_2026_06_26_fidelity_gate_extraction": "Milestone-B fidelity-gate wiring residual: bodyToText+gateAdvance extracted to fidelityGateStep.ts (889->854, -35), but the StackOptions.fidelityGate field, the `const fidelityGate` reads at the two stacked-loop dispatch chokepoints, and the import of FidelityGateConfig are irreducible wiring that cannot leave strategySelector without an architectural refactor of the pre-existing stacked pipeline. Net: 889->854 (+6 vs the pre-Milestone-B frozen 848). Covered by tests/unit/compression/*.test.ts (940 pass).",
"_rebaseline_2026_06_28_5243_risk_gate_prepass": "PR #5243 (compression risk-gate pre-pass) own growth: open-sse/services/compression/strategySelector.ts 854->899 (+45). The three exported entry points (applyCompression/applyStackedCompression/applyStackedCompressionAsync) become thin wrappers over pure-extracted private bodies (runCompression/runStackedCompression/runStackedCompressionAsync) so the risk-gate mask->run->restore wrapper sits strictly OUTSIDE the per-step loop — a single universal integration point. The wrapper logic itself (resolveRiskGate/withRiskGate) lives in the new riskGate/strategyWrap.ts (<cap); the residual growth is the duplicated thin-wrapper signatures + the extracted bodies' dispatch boundary, guarded by a byte-identical parity test (riskGateIntegration). Default off (DEFAULT_COMPRESSION_CONFIG unchanged). Not extractable without hiding the dispatch boundary, mirroring prior compression rebaselines. Structural shrink tracked in #3501.",
"_rebaseline_2026_06_29_5286_memoization": "PR #5286 own growth: strategySelector.ts 899->960 (+61 = the opt-in result-memoization branches in applyCompression/applyCompressionAsync — principal+determinism gate, makeMemoKey lookup/store with model+supportsVision folded into the key, recompute-with-memo-off). Default off (memoizeCompressionResults), so zero behavior change. The memo helpers live in the leaf resultMemo.ts (<cap); the chokepoint wiring here is not extractable. Structural shrink of this hot-path file tracked in #3501.",
@@ -223,7 +227,8 @@
"open-sse/translator/response/gemini-to-openai.ts": 821,
"_rebaseline_2026_07_22_7936_namespace_roundtrip": "#7936 (@RCrushMe, Responses-Chat namespace round-trip identity seam) own growth: open-sse/translator/response/openai-responses.ts 1092->1125 (+33) and open-sse/utils/stream.ts 2814->2869 (+55) — threading the namespace-identity seam through the Responses↔Chat translation + stream paths so tool-call namespaces survive the round-trip. Cohesive translation/stream wiring at existing chokepoints, frozen at new size.",
"_rebaseline_2026_07_22_8210_openrouter_midstream_error": "PR #8210 (hartmark, fix/openrouter-midstream-error-surfacing) own growth: open-sse/translator/response/openai-responses.ts 1137->1163 (+26) measured on the merged tip (release 1137 + this PR own growth). Adds a single new branch inside openaiToOpenAIResponsesResponse() that detects an OpenRouter-style mid-stream aggregator error (HTTP 200 SSE chunk with empty choices + a top-level error object) and surfaces it as state.upstreamError instead of silently falling through to the no-op/awaitingTrailingUsage path, which previously masked the failure as a false empty-success completion and skipped combo fallback. Irreducible call-site addition at the existing chunk-dispatch chokepoint (mirrors the Gemini-to-OpenAI translator's #4177 precedent for the same class of upstream error surfacing). Note: this baseline entry does NOT cover the separate pre-existing +11 drift already on the release tip from #8081/#8162 (1125->1136, unrelated reasoning-placeholder-stripping fix merged after this PR branched) — that drift belongs to the maintainer's rebaseline, not this PR.",
"open-sse/translator/response/openai-responses.ts": 1163,
"_rebaseline_2026_07_24_responses_toolcalls_log_summary": "hartmark, fix/responses-tool-calls-log-summary own growth: open-sse/translator/response/openai-responses.ts 1163->1174 (+11). closeToolCall() now also writes the completed tool call into the shared state.toolCalls Map (already populated by the openai-to-claude / claude-to-openai / gemini-to-openai response translators) so stream.ts's completion-log summary builder (which reads state.toolCalls, not this translator's own funcCallIds/funcNames/funcArgsBuf bookkeeping) reports finish_reason \"tool_calls\" and message.tool_calls for openai->openai-responses translated streams instead of always logging \"stop\" with no tool_calls — the actual client-facing SSE events were already correct; only the persisted call-log summary was wrong. Irreducible call-site addition at the existing tool-call-close chokepoint. Covered by the new regression test in tests/unit/translator-resp-openai-responses.test.ts.",
"open-sse/translator/response/openai-responses.ts": 1174,
"open-sse/utils/cursorAgentProtobuf.ts": 1521,
"_rebaseline_2026_07_23_8143_empty_catch_logging": "#8143 (@chirag127) own growth: open-sse/utils/stream.ts 2869->2887 (+18) — replacing empty catch blocks in the SSE stream subsystem with console.debug logging (Rule #6 silent-swallow fix, issues #8138-#8142). Cohesive logging additions at the existing catch chokepoints, not extractable; frozen at new size. Covered by tests/unit/stream-handler-catch-logging-8143.test.ts.",
"open-sse/utils/stream.ts": 2887,
@@ -251,7 +256,7 @@
"src/app/(dashboard)/dashboard/providers/[id]/hooks/useProviderSettings.ts": 264,
"src/app/(dashboard)/dashboard/providers/[id]/providerPageHelpers.ts": 1054,
"src/app/(dashboard)/dashboard/providers/components/onboarding/ProviderOnboardingWizard.tsx": 948,
"src/app/(dashboard)/dashboard/providers/page.tsx": 1927,
"src/app/(dashboard)/dashboard/providers/page.tsx": 1990,
"src/app/(dashboard)/dashboard/runtime/RuntimePageClient.tsx": 1201,
"src/app/(dashboard)/dashboard/settings/components/AppearanceTab.tsx": 819,
"src/app/(dashboard)/dashboard/settings/components/ComboDefaultsTab.tsx": 903,
@@ -309,10 +314,10 @@
"_rebaseline_2026_07_09_6678_routing_strategy_9router": "#6678 (SeaXen) — 9router-parity Routing Strategy settings card + per-provider/combo sticky-round-robin override. Own growth: ProviderDetailPageClient.tsx 784->786 (single ProviderAccountRoutingCard mount + import), auth.ts 2448->2458 (providerStrategies override resolution: fallbackStrategy/stickyRoundRobinLimit per-provider cascade in getProviderCredentials). Both additive, zero unrelated refactor; new UI/logic lives in new files (ProviderAccountRoutingCard.tsx, RoutingStrategyCard.tsx, rrState.ts::resolveComboStickyRoundRobinLimit). chat.ts value below reflects the current release tip (grown by other concurrent PRs, e.g. #6640), not this PR own change.",
"_rebaseline_2026_07_22_8213_chat_abandoned_target_abort": "PR #8213 (hartmark, fix/gemini-tpm-quota-cooldown-wait) own growth: src/sse/handlers/chat.ts 1794->1860 (+66, measured against the PR's own merge-base — the release tip separately carries an unrelated -5 net shrink from #8013's antigravity callable-catalog alignment, which this PR's branch does not include and this entry does not cover). Adds resolveDispatchClientRawRequest(): merges a per-target modelAbortSignal into clientRawRequest.signal (via mergeAbortSignals) so a combo target abandoned by comboTargetTimeoutMs actually observes its own abort and reaches its cleanup path, instead of hanging forever inside withRateLimit/acquireAccountSemaphore and leaking a permanent 'pending' dashboard entry (live incident, log id 1784418258231-14961a). Also wires combo-exhausted rejection logging to capture request body + attempted models via the new rejectedRequestUsage helper. Irreducible additions at the existing chat dispatch chokepoint. Covered by the PR's own combo-config + integration test additions.",
"_rebaseline_2026_07_23_8127_grok_weekly_quota": "#8127 (@apoapostolov) own growth: src/sse/handlers/chat.ts 1861->1865 (+4) — weekly quota tracking for grok-web wires a quota-fetch hook at the existing dispatch chokepoint. Thin wiring mirroring adjacent provider-quota branches; not extractable. Covered by tests/unit/grok-quota-fetcher.test.ts.",
"src/sse/handlers/chat.ts": 1865,
"src/sse/handlers/chat.ts": 1866,
"_rebaseline_2026_07_20_7779_routingcombo_thread": "PR #7779 own growth: chatHelpers.ts 876->877 (+1, thread routingComboId into executeChatWithBreaker for compression-combo assignment). Frozen so it can only shrink.",
"src/sse/handlers/chatHelpers.ts": 878,
"src/sse/services/auth.ts": 2475,
"src/sse/services/auth.ts": 2486,
"open-sse/executors/default.ts": 890,
"open-sse/translator/request/openai-responses.ts": 902,
"open-sse/executors/kiro.ts": 944,
@@ -322,7 +327,7 @@
"open-sse/executors/huggingchat.ts": 813,
"_rebaseline_2026_07_01_v3843_release_5609": "Rebaseline v3.8.43 (PR #5609 release reconciliation). DRIFT dos 109 commits do ciclo: 8 god-files existentes cresceram (ApiManagerPageClient 2983->3017, combos/page 4594->4608, AddApiKeyModal 868->869, providerPageHelpers 974->996, chat.ts 1635->1647, auth.ts 2401->2403, batchProcessor 828->915, combo.ts 3368->3387) + 2 novos acima do cap (huggingchat.ts 813, tests web-cookie-providers-new 827) + 4 test files cresceram. Modularizacao deferida (blast-radius mid-release); congelado no estado atual p/ o proximo ciclo ratchetar daqui.",
"src/lib/providers/validation/webProvidersA.ts": 809,
"src/lib/tokenHealthCheck.ts": 832,
"src/lib/tokenHealthCheck.ts": 843,
"_rebaseline_2026_07_09_6587_kiro_api_key_auth": "PR #6587 (@strangersp) own growth for Kiro long-lived API-key auth, merged onto v3.8.47 tip: openai-to-kiro.ts 890->912 (+22, auth-header selection for API-key-vs-OAuth-token connections), providerLimits.ts 998->1000 (+2, API-key auth-type branch), translator-openai-to-kiro.test.ts 1234->1257 (+23), providers-page-utils.test.ts 1109->1107 (net -2 after merging with parallel release drift; connectionMatchesProviderCard api_key coverage added), provider-validation-specialty.test.ts 2856->2980 (+124 net after merge with parallel release drift; this PR also removed the file's `@typescript-eslint/no-explicit-any` eslint-suppression entry by fixing all `any` usages, adding typed replacements). Cohesive additive feature growth, well tested; not extractable without splitting the existing chokepoints mid-merge.",
"_rebaseline_2026_07_19_7787_ic2_localdb_reexports": "PR #7787 (IC2 raw connections cache + lazy-decrypt) own growth: localDb.ts 805->807 (gate units, +2). localDb.ts is the re-export-only layer (hard rule #2 — no logic); the PR adds 4 new db/readCache re-exports (touchConnectionLastUsed, getCachedRawProviderConnections, getCachedProviderConnectionById, getCachedProviderNodes) required by existing barrel importers. Irreducible for a re-export list; frozen so it can only shrink.",
"_rebaseline_2026_07_20_7819_autocandidateoverrides_reexport": "PR for #7819 (Level 1+2: read-only auto/* candidate transparency + per-API-key exclusions) own growth: localDb.ts 807->808 (+1). Adds a single `export * from \"./db/autoCandidateOverrides\"` barrel re-export (hard rule #2 — no logic) for the new DB module backing per-apiKey candidate exclusions. Irreducible for a re-export list; frozen so it can only shrink.",
@@ -339,6 +344,8 @@
},
"testCap": 800,
"testFrozen": {
"_rebaseline_2026_07_25_8510_adobe_firefly_reference_images_tests": "#8510 (artickc, feat/adobe-firefly-reference-images) own test growth: tests/unit/adobe-firefly.test.ts 711->871 (+159, entirely this PR's diff — new referenceBlobs upload/dispatch coverage for handleAdobeFireflyImageGeneration, resolveAdobeSourceImageIds, and the storage-upload wire contract). Route-level /v1/images/edits coverage (credentials/rate-limit/4-ref-cap branches added to route.ts) lives in the new tests/unit/8510-adobe-firefly-edits-route.test.ts instead of growing this file further.",
"tests/unit/adobe-firefly.test.ts": 871,
"_rebaseline_2026_07_09_6126_clinepass_dualauth": "#6126 (ClinePass dual-auth) own test growth: oauth-providers-config.test.ts 842->845 (+3: clinepass key/config/required-fields entries reusing the Cline WorkOS flow config, needed after registering clinepass in the oauth.ts PROVIDERS enum).",
"_rebaseline_2026_06_27_5193_antigravity_test": "#5193 own test growth: oauth-providers-config.test.ts 870->873 (+3: antigravity projectId assertion + 50ms tick for the now fire-and-forget onboarding, matching the no-PKCE/no-openid flow).",
"_rebaseline_2026_07_02_5928_base_red": "web-cookie-providers-new.test.ts 845->850: #5928 (test(security) Kimi Web URL host parse, CodeQL #689) grew the file +5 lines and merged into release/v3.8.44 WITHOUT rebaselining, leaving a fast-gates base-red that blocked every subsequent PR->release. Test growth is legitimate (a security regression test); maintainer absorbs the drift here. Frozen at 850.",
@@ -467,5 +474,7 @@
"_rebaseline_2026_07_22_v3849_ownGrowth_merge_batch": "OAuthModal(#7735 grok chooser), muse-spark-web(#7528 WS), combo.ts+combo-routing-engine.test(#7301 cooldown-retry) — pre-existing on tip; PricingTab(#7972), ComboDefaultsTab(#8008/#7973) — this train batch. Legitimate own-growth, owner-approved rebaseline.",
"_rebaseline_2026_07_23_v3849_merge_train_15": "Own-growth do merge-train de 15 PRs (2026-07-23), medido na tip combinada, release pura abaixo do baseline (auth.ts 2448, muse-spark 1393, translator-test 1523). auth.ts 2462->2475 (#8321 cookie-auth 401 cooldown-em-vez-de-terminal + #8324 noauth opencode-zen via proxy — wiring de classificação no chokepoint getProviderCredentials/markAccountUnavailable, não extraível), muse-spark-web.ts 1394->1396 (#8298 sanitizeErrorMessage runtime repairs isolados do #8177), tests/unit/translator-openai-to-gemini.test.ts 1553->1616 (#8312 cobertura do cap de thinking budget no path budget_tokens explícito). Owner-approved. Frozen; shrink estrutural em #3501.",
"_rebaseline_2026_07_22_providerLimits_webcookie_chain": "providerLimits.ts 1003->1005: own-growth from web-cookie provider usage-fetcher entries (#7994/#8006/#8027 chain) landing after the prior rebaseline.",
"_rebaseline_2026_07_22_8056_headroom_minrows": "#8056 (@RaviTharuma, persist Headroom minRows) own growth: src/lib/db/compression.ts 850->866 (+16 HeadroomConfig+DEFAULT_HEADROOM_CONFIG+normalize/store in get/updateCompressionSettings) and open-sse/services/compression/strategySelector.ts 1054->1060 (+6 merge settings.headroom into stacked stepConfig). Cohesive settings-persistence + stacked-merge wiring at existing chokepoints, frozen at new size."
"_rebaseline_2026_07_22_8056_headroom_minrows": "#8056 (@RaviTharuma, persist Headroom minRows) own growth: src/lib/db/compression.ts 850->866 (+16 HeadroomConfig+DEFAULT_HEADROOM_CONFIG+normalize/store in get/updateCompressionSettings) and open-sse/services/compression/strategySelector.ts 1054->1060 (+6 merge settings.headroom into stacked stepConfig). Cohesive settings-persistence + stacked-merge wiring at existing chokepoints, frozen at new size.",
"_rebaseline_2026_07_25_v3849_basered_filesize": "Base-red unblock (2026-07-25): check:file-size was failing on release/v3.8.49 at its own HEAD (36f8fd10), so the quality.yml fast-gates job was red for EVERY PR->release regardless of content — growth inherited from already-merged PRs, with no offending PR branch left to fix (same situation as _rebaseline_2026_07_02_5798_release_green). Prod frozen raised to the current base values: src/lib/tokenHealthCheck.ts 832->841, src/sse/handlers/chat.ts 1865->1866, src/sse/services/auth.ts 2475->2486, open-sse/services/accountFallback.ts 1941->1966, open-sse/services/combo.ts 3630->3642. accountFallback.ts was first frozen here at 1960 (the base value at 36f8fd10) and re-measured to 1966 at base tip 1cafd328c a few hours later — the same inherited drift this entry exists for, since check:file-size does not run on the PR->release fast path and so accrues unmeasured between release rebaselines. These files remain frozen and cannot grow further; any in-flight PR that adds lines to them (e.g. #8482 touches accountFallback.ts and combo.ts) bumps its own entry as usual. The release captain rebaseline-at-release supersedes this note.",
"_rebaseline_2026_07_25_v3849_basered_filesize_2": "Base-red unblock (2026-07-25, second pass): after _rebaseline_2026_07_25_v3849_basered_filesize (measured at 36f8fd10) two more already-merged PRs grew frozen files on release/v3.8.49, so check:file-size — and with it the whole Fast Quality Gates job — is red for EVERY PR->release again, with no offending PR branch left to fix. src/lib/tokenHealthCheck.ts 841->843 (#8426 4528fc455, excludes local CLI providers from expiration) and src/app/(dashboard)/dashboard/providers/page.tsx 1927->1990 (#8349 58ab8b1d2, scroll-position restore on provider-card back-navigation). Trust-but-verify: both values measured on the pristine release tip 30709255 with no working-tree changes. Same situation and remedy as _rebaseline_2026_07_02_5798_release_green. Structural reduction of providers/page.tsx stays tracked separately — it is a 1990-line page, not something to extract inside a base-repair PR."
}

View File

@@ -123,7 +123,9 @@
"_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."
},
"cognitiveComplexity": {
"value": 951,
"value": 968,
"_rebaseline_2026_07_25b_v3849_mergetrain_owngrowth": "Owner-approved (chat, 2026-07-25): 956->968 (+12). v3.8.49 /merge-prs 41-PR merge-train aggregate own-growth: measured 968 on the combined boarded tree (tip ac15014ca7) vs 956 on the pristine release tip. The batch's new over-threshold functions come from the pre-screen-flagged complexity-growth set (#8378/#8432/#8476/#8526 etc); each PR is under-ceiling alone, the combined batch adds +12. Same merge-burst class as the notes below; owner chose ceiling-absorb over per-PR extraction. Structural shrink tracked in #3501; tighten via --update next cycle.",
"_rebaseline_2026_07_25_v3849_mergequeue_drain": "Owner-approved (chat, 2026-07-25): 951->956 (+5). v3.8.49 /merge-prs queue-drain: inherited cognitive-complexity drift from the cycle's merge burst (base-red slices + owner PRs + parallel-session merges #8500-8508); check:cognitive-complexity does not run on PR->release fast-gates, so it accrued unmeasured. Measured 956 on the pristine release tip 4053e2314a alone (BEFORE any queue PR boards) — the entire +5 is base drift already on the tip, reddening Fast Quality Gates for every merge-ready PR. Owner approved raising the ceiling to the measured tip value so the ~34-PR merge-train lands without per-PR extraction churn. Structural shrink tracked in #3501; tighten via --update next cycle.",
"_rebaseline_2026_07_10_gcf_v3_2": "885->888 (+3). PR feat/headroom-gcf-v3.2-nested-flattening: own growth from re-vendoring the GCF (Headroom) codec to spec v3.2 (nested flattening). The new over-threshold functions are the vendored v3.2 flatten/unflatten walk in open-sse/services/compression/engines/headroom/gcf/{generic,decode_generic}.ts. Imported third-party code kept byte-faithful to upstream gcf-typescript; measured 888 with the update vs 885 on the pristine origin/release/v3.8.47 tip. Guarded by tests/unit/compression/headroom-smartcrusher.test.ts (deep-nested case). Structural shrink belongs upstream in gcf.",
"_rebaseline_2026_07_12_v3847_mergetrain_burst": "885->890 (+5). v3.8.47 /merge-prs merge-train batch (23 merge-ready PRs) inherited drift: cognitive-complexity does NOT run on PR->release fast-gates, so incidental growth accrued unmeasured across the batch. Measured 890 on the combined merge-train tip (5d980352d) vs 885 on the pristine release tip 1b7a9150e. #6838 (headroom gcf codec re-vendor) accounts for +3 (its own baseline bump to 888, superseded here by this later 890 rebaseline which already covers it); the remaining +2 is parallel-batch drift across the other 22 PRs. Owner-approved rebaseline (merge-burst reconciliation, same class as the v3.8.46/v3.8.44 notes below). Tighten via --update next cycle.",
"_rebaseline_2026_07_09_6587_kiro_api_key_auth": "884->885 (+1). PR #6587 (@strangersp) own growth: open-sse/services/usage/kiro.ts gains ONE new over-threshold function — getKiroUsage grew from a single fetch to a 3-endpoint fallback chain (codewhisperer-get / codewhisperer-post / q-get) with per-attempt auth-header selection (tokentype: API_KEY vs Bearer-only), needed so usage/quota lookups work for the new long-lived-API-key auth path in addition to the existing OAuth path (measured: 0 violations on release tip -> 1 violation, complexity 33, at open-sse/services/usage/kiro.ts). Covered by tests/unit/kiro-iam-profilearn-usage.test.ts (tokentype header selection, friendly auth-expired/rejected-token messages). Cohesive multi-endpoint-fallback logic at an existing usage chokepoint; not extractable without splitting the fallback loop mid-merge. Structural shrink tracked in #3501.",

View File

@@ -209,14 +209,13 @@ on). Without a `max_concurrent` cap the behavior is unchanged.
### Combo cooldown-aware retry
For quota-share and `auto` combos, a request that would crystallize a 429 for a
SHORT transient cooldown waits it out and re-dispatches instead of returning
the 429 — this covers Gemini-class TPM/RPM windows (~60s retry-after) on a
multi-model `auto` combo, e.g. both targets of a 2-model combo hitting a
per-model rate limit. Bounded by `comboCooldownWait` (`enabled`, `maxWaitMs`
65s, `maxAttempts` 2, `budgetMs` 130s, hard ceiling 90s) in **Settings →
Resilience**. It never waits on `quota_exhausted` (locked until midnight) or
auth/not-found reasons.
For every combo strategy (when enabled), a request that would crystallize a 429
for a SHORT transient cooldown waits it out and re-dispatches instead of
returning the 429 — this covers Gemini-class TPM/RPM windows (~60s retry-after)
on multi-model combos, e.g. both targets of a 2-model combo hitting a per-model
rate limit. Bounded by `comboCooldownWait` (`enabled`, `maxWaitMs`, `maxAttempts`,
`budgetMs`) in **Settings → Resilience**. It never waits on `quota_exhausted`
(locked until midnight) or auth/not-found reasons.
---

View File

@@ -1,7 +1,7 @@
---
title: "Claude Code CLI — Configuration with OmniRoute"
version: 3.8.40
lastUpdated: 2026-06-28
lastUpdated: 2026-07-24
---
# Claude Code CLI — Configuration with OmniRoute
@@ -140,10 +140,20 @@ extra flags needed. Override per-invocation with `--remote` / `--api-key`.
handles this for you.
**`/model` picker is empty / missing gateway models** — needs Claude Code
v2.1.129+ and `CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY=1`. Only `claude*` /
v2.1.219+ and `CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY=1`. Only `claude*` /
`anthropic*` model IDs appear in the picker; force any other model with
`ANTHROPIC_MODEL=<id>` (this is what profiles do).
**`400 Ambiguous model 'claude-…'`** — Claude Code always sends **unprefixed**
model IDs (e.g. `claude-opus-4-8`), so when both the Claude Code (`cc/…`) and
Claude (`claude/…`) providers are connected the bare id matches two routes and
OmniRoute refuses to guess. Fix it either way: pin a prefixed id with
`ANTHROPIC_MODEL=cc/claude-opus-4-8`, or enable **Prefer Claude Code for
unprefixed Claude models** — the toggle on the Claude provider page, or
`OMNIROUTE_PREFER_CLAUDE_CODE_FOR_UNPREFIXED_CLAUDE_MODELS=true` (default off;
see [Environment](../reference/ENVIRONMENT.md)) — which routes bare `claude-*`
IDs to Claude Code instead. Explicit provider prefixes always win.
**Auth errors** — the profile holds no token. Use `omniroute launch --profile`
(injects it) or export `ANTHROPIC_AUTH_TOKEN`.

View File

@@ -572,7 +572,7 @@ For the full environment variable reference, see the [README](../README.md).
**GitHub Copilot (`gh/`)** — OAuth: `gh/gpt-5.5`, `gh/gpt-5.4`, `gh/gpt-5.4-mini`, `gh/gpt-5-mini`, `gh/gpt-5.3-codex`, `gh/claude-opus-4.7`, `gh/claude-opus-4.6`, `gh/claude-opus-4-5-20251101`, `gh/claude-sonnet-4.6`, `gh/claude-sonnet-4.5`, `gh/claude-haiku-4.5`, `gh/gemini-3.1-pro-preview`, `gh/gemini-3-flash-preview`, `gh/oswe-vscode-prime`
**Kiro (`kr/`)** — FREE OAuth: `kr/auto-kiro`, `kr/claude-opus-4.7`, `kr/claude-opus-4.6`, `kr/claude-sonnet-4.6`, `kr/claude-sonnet-4.5`, `kr/claude-haiku-4.5`, `kr/deepseek-3.2`, `kr/minimax-m2.5`, `kr/minimax-m2.1`, `kr/glm-5`, `kr/qwen3-coder-next`
**Kiro (`kr/`)** — FREE OAuth: use the live catalog shown under **Dashboard → Providers → Kiro → Available Models**. Availability depends on the account and plan.
**Qoder (`if/`)** — FREE OAuth: `if/qwen3.8-max-preview`, `if/qwen3.7-max`, `if/qwen3.7-plus`, `if/kimi-k3`, `if/kimi-k2.7-code`, `if/glm-5.2`, `if/deepseek-v4-pro`, `if/deepseek-v4-flash`, `if/minimax-m3`

View File

@@ -336,7 +336,7 @@ process.env[`${PROVIDER_ID}_USER_AGENT`]
| Variable | Default Value | When to Update |
| ------------------------ | --------------------------------------------- | ------------------------------------------------------------- |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.145 (external, cli)` | When Anthropic releases a new CLI version |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.219 (external, cli)` | When Anthropic releases a new CLI version |
| `CODEX_USER_AGENT` | `codex-cli/0.132.0 (Windows 10.0.26200; x64)` | When OpenAI updates the Codex CLI |
| `CODEX_CLIENT_VERSION` | `0.131.0` | Override Codex client version independently of full UA string |
| `GITHUB_USER_AGENT` | `GitHubCopilotChat/0.45.1` | When GitHub Copilot Chat updates |

View File

@@ -336,7 +336,7 @@ process.env[`${PROVIDER_ID}_USER_AGENT`]
| Variable | Default Value | When to Update |
| ------------------------ | --------------------------------------------- | ------------------------------------------------------------- |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.145 (external, cli)` | When Anthropic releases a new CLI version |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.219 (external, cli)` | When Anthropic releases a new CLI version |
| `CODEX_USER_AGENT` | `codex-cli/0.132.0 (Windows 10.0.26200; x64)` | When OpenAI updates the Codex CLI |
| `CODEX_CLIENT_VERSION` | `0.131.0` | Override Codex client version independently of full UA string |
| `GITHUB_USER_AGENT` | `GitHubCopilotChat/0.45.1` | When GitHub Copilot Chat updates |

View File

@@ -336,7 +336,7 @@ process.env[`${PROVIDER_ID}_USER_AGENT`]
| Variable | Default Value | When to Update |
| ------------------------ | --------------------------------------------- | ------------------------------------------------------------- |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.145 (external, cli)` | When Anthropic releases a new CLI version |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.219 (external, cli)` | When Anthropic releases a new CLI version |
| `CODEX_USER_AGENT` | `codex-cli/0.132.0 (Windows 10.0.26200; x64)` | When OpenAI updates the Codex CLI |
| `CODEX_CLIENT_VERSION` | `0.131.0` | Override Codex client version independently of full UA string |
| `GITHUB_USER_AGENT` | `GitHubCopilotChat/0.45.1` | When GitHub Copilot Chat updates |

View File

@@ -336,7 +336,7 @@ process.env[`${PROVIDER_ID}_USER_AGENT`]
| Variable | Default Value | When to Update |
| ------------------------ | --------------------------------------------- | ------------------------------------------------------------- |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.145 (external, cli)` | When Anthropic releases a new CLI version |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.219 (external, cli)` | When Anthropic releases a new CLI version |
| `CODEX_USER_AGENT` | `codex-cli/0.132.0 (Windows 10.0.26200; x64)` | When OpenAI updates the Codex CLI |
| `CODEX_CLIENT_VERSION` | `0.131.0` | Override Codex client version independently of full UA string |
| `GITHUB_USER_AGENT` | `GitHubCopilotChat/0.45.1` | When GitHub Copilot Chat updates |

View File

@@ -336,7 +336,7 @@ process.env[`${PROVIDER_ID}_USER_AGENT`]
| Variable | Default Value | When to Update |
| ------------------------ | --------------------------------------------- | ------------------------------------------------------------- |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.145 (external, cli)` | When Anthropic releases a new CLI version |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.219 (external, cli)` | When Anthropic releases a new CLI version |
| `CODEX_USER_AGENT` | `codex-cli/0.132.0 (Windows 10.0.26200; x64)` | When OpenAI updates the Codex CLI |
| `CODEX_CLIENT_VERSION` | `0.131.0` | Override Codex client version independently of full UA string |
| `GITHUB_USER_AGENT` | `GitHubCopilotChat/0.45.1` | When GitHub Copilot Chat updates |

View File

@@ -336,7 +336,7 @@ process.env[`${PROVIDER_ID}_USER_AGENT`]
| Variable | Default Value | When to Update |
| ------------------------ | --------------------------------------------- | ------------------------------------------------------------- |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.145 (external, cli)` | When Anthropic releases a new CLI version |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.219 (external, cli)` | When Anthropic releases a new CLI version |
| `CODEX_USER_AGENT` | `codex-cli/0.132.0 (Windows 10.0.26200; x64)` | When OpenAI updates the Codex CLI |
| `CODEX_CLIENT_VERSION` | `0.131.0` | Override Codex client version independently of full UA string |
| `GITHUB_USER_AGENT` | `GitHubCopilotChat/0.45.1` | When GitHub Copilot Chat updates |

View File

@@ -336,7 +336,7 @@ process.env[`${PROVIDER_ID}_USER_AGENT`]
| Variable | Default Value | When to Update |
| ------------------------ | --------------------------------------------- | ------------------------------------------------------------- |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.145 (external, cli)` | When Anthropic releases a new CLI version |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.219 (external, cli)` | When Anthropic releases a new CLI version |
| `CODEX_USER_AGENT` | `codex-cli/0.132.0 (Windows 10.0.26200; x64)` | When OpenAI updates the Codex CLI |
| `CODEX_CLIENT_VERSION` | `0.131.0` | Override Codex client version independently of full UA string |
| `GITHUB_USER_AGENT` | `GitHubCopilotChat/0.45.1` | When GitHub Copilot Chat updates |

View File

@@ -336,7 +336,7 @@ process.env[`${PROVIDER_ID}_USER_AGENT`]
| Variable | Default Value | When to Update |
| ------------------------ | --------------------------------------------- | ------------------------------------------------------------- |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.145 (external, cli)` | When Anthropic releases a new CLI version |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.219 (external, cli)` | When Anthropic releases a new CLI version |
| `CODEX_USER_AGENT` | `codex-cli/0.132.0 (Windows 10.0.26200; x64)` | When OpenAI updates the Codex CLI |
| `CODEX_CLIENT_VERSION` | `0.131.0` | Override Codex client version independently of full UA string |
| `GITHUB_USER_AGENT` | `GitHubCopilotChat/0.45.1` | When GitHub Copilot Chat updates |

View File

@@ -336,7 +336,7 @@ process.env[`${PROVIDER_ID}_USER_AGENT`]
| Variable | Default Value | When to Update |
| ------------------------ | --------------------------------------------- | ------------------------------------------------------------- |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.145 (external, cli)` | When Anthropic releases a new CLI version |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.219 (external, cli)` | When Anthropic releases a new CLI version |
| `CODEX_USER_AGENT` | `codex-cli/0.132.0 (Windows 10.0.26200; x64)` | When OpenAI updates the Codex CLI |
| `CODEX_CLIENT_VERSION` | `0.131.0` | Override Codex client version independently of full UA string |
| `GITHUB_USER_AGENT` | `GitHubCopilotChat/0.45.1` | When GitHub Copilot Chat updates |

View File

@@ -336,7 +336,7 @@ process.env[`${PROVIDER_ID}_USER_AGENT`]
| Variable | Default Value | When to Update |
| ------------------------ | --------------------------------------------- | ------------------------------------------------------------- |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.145 (external, cli)` | When Anthropic releases a new CLI version |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.219 (external, cli)` | When Anthropic releases a new CLI version |
| `CODEX_USER_AGENT` | `codex-cli/0.132.0 (Windows 10.0.26200; x64)` | When OpenAI updates the Codex CLI |
| `CODEX_CLIENT_VERSION` | `0.131.0` | Override Codex client version independently of full UA string |
| `GITHUB_USER_AGENT` | `GitHubCopilotChat/0.45.1` | When GitHub Copilot Chat updates |

View File

@@ -336,7 +336,7 @@ process.env[`${PROVIDER_ID}_USER_AGENT`]
| Variable | Default Value | When to Update |
| ------------------------ | --------------------------------------------- | ------------------------------------------------------------- |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.145 (external, cli)` | When Anthropic releases a new CLI version |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.219 (external, cli)` | When Anthropic releases a new CLI version |
| `CODEX_USER_AGENT` | `codex-cli/0.132.0 (Windows 10.0.26200; x64)` | When OpenAI updates the Codex CLI |
| `CODEX_CLIENT_VERSION` | `0.131.0` | Override Codex client version independently of full UA string |
| `GITHUB_USER_AGENT` | `GitHubCopilotChat/0.45.1` | When GitHub Copilot Chat updates |

View File

@@ -336,7 +336,7 @@ process.env[`${PROVIDER_ID}_USER_AGENT`]
| Variable | Default Value | When to Update |
| ------------------------ | --------------------------------------------- | ------------------------------------------------------------- |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.145 (external, cli)` | When Anthropic releases a new CLI version |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.219 (external, cli)` | When Anthropic releases a new CLI version |
| `CODEX_USER_AGENT` | `codex-cli/0.132.0 (Windows 10.0.26200; x64)` | When OpenAI updates the Codex CLI |
| `CODEX_CLIENT_VERSION` | `0.131.0` | Override Codex client version independently of full UA string |
| `GITHUB_USER_AGENT` | `GitHubCopilotChat/0.45.1` | When GitHub Copilot Chat updates |

View File

@@ -336,7 +336,7 @@ process.env[`${PROVIDER_ID}_USER_AGENT`]
| Variable | Default Value | When to Update |
| ------------------------ | --------------------------------------------- | ------------------------------------------------------------- |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.145 (external, cli)` | When Anthropic releases a new CLI version |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.219 (external, cli)` | When Anthropic releases a new CLI version |
| `CODEX_USER_AGENT` | `codex-cli/0.132.0 (Windows 10.0.26200; x64)` | When OpenAI updates the Codex CLI |
| `CODEX_CLIENT_VERSION` | `0.131.0` | Override Codex client version independently of full UA string |
| `GITHUB_USER_AGENT` | `GitHubCopilotChat/0.45.1` | When GitHub Copilot Chat updates |

View File

@@ -336,7 +336,7 @@ process.env[`${PROVIDER_ID}_USER_AGENT`]
| Variable | Default Value | When to Update |
| ------------------------ | --------------------------------------------- | ------------------------------------------------------------- |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.145 (external, cli)` | When Anthropic releases a new CLI version |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.219 (external, cli)` | When Anthropic releases a new CLI version |
| `CODEX_USER_AGENT` | `codex-cli/0.132.0 (Windows 10.0.26200; x64)` | When OpenAI updates the Codex CLI |
| `CODEX_CLIENT_VERSION` | `0.131.0` | Override Codex client version independently of full UA string |
| `GITHUB_USER_AGENT` | `GitHubCopilotChat/0.45.1` | When GitHub Copilot Chat updates |

View File

@@ -336,7 +336,7 @@ process.env[`${PROVIDER_ID}_USER_AGENT`]
| Variable | Default Value | When to Update |
| ------------------------ | --------------------------------------------- | ------------------------------------------------------------- |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.145 (external, cli)` | When Anthropic releases a new CLI version |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.219 (external, cli)` | When Anthropic releases a new CLI version |
| `CODEX_USER_AGENT` | `codex-cli/0.132.0 (Windows 10.0.26200; x64)` | When OpenAI updates the Codex CLI |
| `CODEX_CLIENT_VERSION` | `0.131.0` | Override Codex client version independently of full UA string |
| `GITHUB_USER_AGENT` | `GitHubCopilotChat/0.45.1` | When GitHub Copilot Chat updates |

View File

@@ -336,7 +336,7 @@ process.env[`${PROVIDER_ID}_USER_AGENT`]
| Variable | Nilai Default | Kapan Diperbarui |
| ------------------------ | --------------------------------------------- | ----------------------------------------------------------------- |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.145 (external, cli)` | Saat Anthropic merilis versi CLI baru |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.219 (external, cli)` | Saat Anthropic merilis versi CLI baru |
| `CODEX_USER_AGENT` | `codex-cli/0.132.0 (Windows 10.0.26200; x64)` | Saat OpenAI memperbarui CLI Codex |
| `CODEX_CLIENT_VERSION` | `0.131.0` | Override versi klien Codex secara independen dari string UA penuh |
| `GITHUB_USER_AGENT` | `GitHubCopilotChat/0.45.1` | Saat GitHub Copilot Chat diperbarui |

View File

@@ -336,7 +336,7 @@ process.env[`${PROVIDER_ID}_USER_AGENT`]
| Variable | Default Value | When to Update |
| ------------------------ | --------------------------------------------- | ------------------------------------------------------------- |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.145 (external, cli)` | When Anthropic releases a new CLI version |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.219 (external, cli)` | When Anthropic releases a new CLI version |
| `CODEX_USER_AGENT` | `codex-cli/0.132.0 (Windows 10.0.26200; x64)` | When OpenAI updates the Codex CLI |
| `CODEX_CLIENT_VERSION` | `0.131.0` | Override Codex client version independently of full UA string |
| `GITHUB_USER_AGENT` | `GitHubCopilotChat/0.45.1` | When GitHub Copilot Chat updates |

View File

@@ -336,7 +336,7 @@ process.env[`${PROVIDER_ID}_USER_AGENT`]
| Variable | Default Value | When to Update |
| ------------------------ | --------------------------------------------- | ------------------------------------------------------------- |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.145 (external, cli)` | When Anthropic releases a new CLI version |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.219 (external, cli)` | When Anthropic releases a new CLI version |
| `CODEX_USER_AGENT` | `codex-cli/0.132.0 (Windows 10.0.26200; x64)` | When OpenAI updates the Codex CLI |
| `CODEX_CLIENT_VERSION` | `0.131.0` | Override Codex client version independently of full UA string |
| `GITHUB_USER_AGENT` | `GitHubCopilotChat/0.45.1` | When GitHub Copilot Chat updates |

View File

@@ -336,7 +336,7 @@ process.env[`${PROVIDER_ID}_USER_AGENT`]
| Variable | Default Value | When to Update |
| ------------------------ | --------------------------------------------- | ------------------------------------------------------------- |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.145 (external, cli)` | When Anthropic releases a new CLI version |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.219 (external, cli)` | When Anthropic releases a new CLI version |
| `CODEX_USER_AGENT` | `codex-cli/0.132.0 (Windows 10.0.26200; x64)` | When OpenAI updates the Codex CLI |
| `CODEX_CLIENT_VERSION` | `0.131.0` | Override Codex client version independently of full UA string |
| `GITHUB_USER_AGENT` | `GitHubCopilotChat/0.45.1` | When GitHub Copilot Chat updates |

View File

@@ -336,7 +336,7 @@ process.env[`${PROVIDER_ID}_USER_AGENT`]
| Variable | Default Value | When to Update |
| ------------------------ | --------------------------------------------- | ------------------------------------------------------------- |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.145 (external, cli)` | When Anthropic releases a new CLI version |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.219 (external, cli)` | When Anthropic releases a new CLI version |
| `CODEX_USER_AGENT` | `codex-cli/0.132.0 (Windows 10.0.26200; x64)` | When OpenAI updates the Codex CLI |
| `CODEX_CLIENT_VERSION` | `0.131.0` | Override Codex client version independently of full UA string |
| `GITHUB_USER_AGENT` | `GitHubCopilotChat/0.45.1` | When GitHub Copilot Chat updates |

View File

@@ -336,7 +336,7 @@ process.env[`${PROVIDER_ID}_USER_AGENT`]
| Variable | Default Value | When to Update |
| ------------------------ | --------------------------------------------- | ------------------------------------------------------------- |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.145 (external, cli)` | When Anthropic releases a new CLI version |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.219 (external, cli)` | When Anthropic releases a new CLI version |
| `CODEX_USER_AGENT` | `codex-cli/0.132.0 (Windows 10.0.26200; x64)` | When OpenAI updates the Codex CLI |
| `CODEX_CLIENT_VERSION` | `0.131.0` | Override Codex client version independently of full UA string |
| `GITHUB_USER_AGENT` | `GitHubCopilotChat/0.45.1` | When GitHub Copilot Chat updates |

View File

@@ -336,7 +336,7 @@ process.env[`${PROVIDER_ID}_USER_AGENT`]
| Variable | Default Value | When to Update |
| ------------------------ | --------------------------------------------- | ------------------------------------------------------------- |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.145 (external, cli)` | When Anthropic releases a new CLI version |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.219 (external, cli)` | When Anthropic releases a new CLI version |
| `CODEX_USER_AGENT` | `codex-cli/0.132.0 (Windows 10.0.26200; x64)` | When OpenAI updates the Codex CLI |
| `CODEX_CLIENT_VERSION` | `0.131.0` | Override Codex client version independently of full UA string |
| `GITHUB_USER_AGENT` | `GitHubCopilotChat/0.45.1` | When GitHub Copilot Chat updates |

View File

@@ -336,7 +336,7 @@ process.env[`${PROVIDER_ID}_USER_AGENT`]
| Variable | Default Value | When to Update |
| ------------------------ | --------------------------------------------- | ------------------------------------------------------------- |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.145 (external, cli)` | When Anthropic releases a new CLI version |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.219 (external, cli)` | When Anthropic releases a new CLI version |
| `CODEX_USER_AGENT` | `codex-cli/0.132.0 (Windows 10.0.26200; x64)` | When OpenAI updates the Codex CLI |
| `CODEX_CLIENT_VERSION` | `0.131.0` | Override Codex client version independently of full UA string |
| `GITHUB_USER_AGENT` | `GitHubCopilotChat/0.45.1` | When GitHub Copilot Chat updates |

View File

@@ -336,7 +336,7 @@ process.env[`${PROVIDER_ID}_USER_AGENT`]
| Variable | Default Value | When to Update |
| ------------------------ | --------------------------------------------- | ------------------------------------------------------------- |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.145 (external, cli)` | When Anthropic releases a new CLI version |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.219 (external, cli)` | When Anthropic releases a new CLI version |
| `CODEX_USER_AGENT` | `codex-cli/0.132.0 (Windows 10.0.26200; x64)` | When OpenAI updates the Codex CLI |
| `CODEX_CLIENT_VERSION` | `0.131.0` | Override Codex client version independently of full UA string |
| `GITHUB_USER_AGENT` | `GitHubCopilotChat/0.45.1` | When GitHub Copilot Chat updates |

View File

@@ -336,7 +336,7 @@ process.env[`${PROVIDER_ID}_USER_AGENT`]
| Variable | Default Value | When to Update |
| ------------------------ | --------------------------------------------- | ------------------------------------------------------------- |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.145 (external, cli)` | When Anthropic releases a new CLI version |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.219 (external, cli)` | When Anthropic releases a new CLI version |
| `CODEX_USER_AGENT` | `codex-cli/0.132.0 (Windows 10.0.26200; x64)` | When OpenAI updates the Codex CLI |
| `CODEX_CLIENT_VERSION` | `0.131.0` | Override Codex client version independently of full UA string |
| `GITHUB_USER_AGENT` | `GitHubCopilotChat/0.45.1` | When GitHub Copilot Chat updates |

View File

@@ -336,7 +336,7 @@ process.env[`${PROVIDER_ID}_USER_AGENT`]
| Variable | Default Value | When to Update |
| ------------------------ | --------------------------------------------- | ------------------------------------------------------------- |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.145 (external, cli)` | When Anthropic releases a new CLI version |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.219 (external, cli)` | When Anthropic releases a new CLI version |
| `CODEX_USER_AGENT` | `codex-cli/0.132.0 (Windows 10.0.26200; x64)` | When OpenAI updates the Codex CLI |
| `CODEX_CLIENT_VERSION` | `0.131.0` | Override Codex client version independently of full UA string |
| `GITHUB_USER_AGENT` | `GitHubCopilotChat/0.45.1` | When GitHub Copilot Chat updates |

View File

@@ -336,7 +336,7 @@ process.env[`${PROVIDER_ID}_USER_AGENT`]
| Variable | Default Value | When to Update |
| ------------------------ | --------------------------------------------- | ------------------------------------------------------------- |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.145 (external, cli)` | When Anthropic releases a new CLI version |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.219 (external, cli)` | When Anthropic releases a new CLI version |
| `CODEX_USER_AGENT` | `codex-cli/0.132.0 (Windows 10.0.26200; x64)` | When OpenAI updates the Codex CLI |
| `CODEX_CLIENT_VERSION` | `0.131.0` | Override Codex client version independently of full UA string |
| `GITHUB_USER_AGENT` | `GitHubCopilotChat/0.45.1` | When GitHub Copilot Chat updates |

View File

@@ -336,7 +336,7 @@ process.env[`${PROVIDER_ID}_USER_AGENT`]
| Variable | Default Value | When to Update |
| ------------------------ | --------------------------------------------- | ------------------------------------------------------------- |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.145 (external, cli)` | When Anthropic releases a new CLI version |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.219 (external, cli)` | When Anthropic releases a new CLI version |
| `CODEX_USER_AGENT` | `codex-cli/0.132.0 (Windows 10.0.26200; x64)` | When OpenAI updates the Codex CLI |
| `CODEX_CLIENT_VERSION` | `0.131.0` | Override Codex client version independently of full UA string |
| `GITHUB_USER_AGENT` | `GitHubCopilotChat/0.45.1` | When GitHub Copilot Chat updates |

View File

@@ -336,7 +336,7 @@ process.env[`${PROVIDER_ID}_USER_AGENT`]
| Variable | Default Value | When to Update |
| ------------------------ | --------------------------------------------- | ------------------------------------------------------------- |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.145 (external, cli)` | When Anthropic releases a new CLI version |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.219 (external, cli)` | When Anthropic releases a new CLI version |
| `CODEX_USER_AGENT` | `codex-cli/0.132.0 (Windows 10.0.26200; x64)` | When OpenAI updates the Codex CLI |
| `CODEX_CLIENT_VERSION` | `0.131.0` | Override Codex client version independently of full UA string |
| `GITHUB_USER_AGENT` | `GitHubCopilotChat/0.45.1` | When GitHub Copilot Chat updates |

View File

@@ -336,7 +336,7 @@ process.env[`${PROVIDER_ID}_USER_AGENT`]
| Variable | Default Value | When to Update |
| ------------------------ | --------------------------------------------- | ------------------------------------------------------------- |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.145 (external, cli)` | When Anthropic releases a new CLI version |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.219 (external, cli)` | When Anthropic releases a new CLI version |
| `CODEX_USER_AGENT` | `codex-cli/0.132.0 (Windows 10.0.26200; x64)` | When OpenAI updates the Codex CLI |
| `CODEX_CLIENT_VERSION` | `0.131.0` | Override Codex client version independently of full UA string |
| `GITHUB_USER_AGENT` | `GitHubCopilotChat/0.45.1` | When GitHub Copilot Chat updates |

View File

@@ -336,7 +336,7 @@ process.env[`${PROVIDER_ID}_USER_AGENT`]
| Variable | Default Value | When to Update |
| ------------------------ | --------------------------------------------- | ------------------------------------------------------------- |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.145 (external, cli)` | When Anthropic releases a new CLI version |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.219 (external, cli)` | When Anthropic releases a new CLI version |
| `CODEX_USER_AGENT` | `codex-cli/0.132.0 (Windows 10.0.26200; x64)` | When OpenAI updates the Codex CLI |
| `CODEX_CLIENT_VERSION` | `0.131.0` | Override Codex client version independently of full UA string |
| `GITHUB_USER_AGENT` | `GitHubCopilotChat/0.45.1` | When GitHub Copilot Chat updates |

View File

@@ -336,7 +336,7 @@ process.env[`${PROVIDER_ID}_USER_AGENT`]
| Variable | Default Value | When to Update |
| ------------------------ | --------------------------------------------- | ------------------------------------------------------------- |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.145 (external, cli)` | When Anthropic releases a new CLI version |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.219 (external, cli)` | When Anthropic releases a new CLI version |
| `CODEX_USER_AGENT` | `codex-cli/0.132.0 (Windows 10.0.26200; x64)` | When OpenAI updates the Codex CLI |
| `CODEX_CLIENT_VERSION` | `0.131.0` | Override Codex client version independently of full UA string |
| `GITHUB_USER_AGENT` | `GitHubCopilotChat/0.45.1` | When GitHub Copilot Chat updates |

View File

@@ -336,7 +336,7 @@ process.env[`${PROVIDER_ID}_USER_AGENT`]
| Variable | Default Value | When to Update |
| ------------------------ | --------------------------------------------- | ------------------------------------------------------------- |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.145 (external, cli)` | When Anthropic releases a new CLI version |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.219 (external, cli)` | When Anthropic releases a new CLI version |
| `CODEX_USER_AGENT` | `codex-cli/0.132.0 (Windows 10.0.26200; x64)` | When OpenAI updates the Codex CLI |
| `CODEX_CLIENT_VERSION` | `0.131.0` | Override Codex client version independently of full UA string |
| `GITHUB_USER_AGENT` | `GitHubCopilotChat/0.45.1` | When GitHub Copilot Chat updates |

View File

@@ -336,7 +336,7 @@ process.env[`${PROVIDER_ID}_USER_AGENT`]
| Variable | Default Value | When to Update |
| ------------------------ | --------------------------------------------- | ------------------------------------------------------------- |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.145 (external, cli)` | When Anthropic releases a new CLI version |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.219 (external, cli)` | When Anthropic releases a new CLI version |
| `CODEX_USER_AGENT` | `codex-cli/0.132.0 (Windows 10.0.26200; x64)` | When OpenAI updates the Codex CLI |
| `CODEX_CLIENT_VERSION` | `0.131.0` | Override Codex client version independently of full UA string |
| `GITHUB_USER_AGENT` | `GitHubCopilotChat/0.45.1` | When GitHub Copilot Chat updates |

View File

@@ -336,7 +336,7 @@ process.env[`${PROVIDER_ID}_USER_AGENT`]
| Variable | Default Value | When to Update |
| ------------------------ | --------------------------------------------- | ------------------------------------------------------------- |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.145 (external, cli)` | When Anthropic releases a new CLI version |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.219 (external, cli)` | When Anthropic releases a new CLI version |
| `CODEX_USER_AGENT` | `codex-cli/0.132.0 (Windows 10.0.26200; x64)` | When OpenAI updates the Codex CLI |
| `CODEX_CLIENT_VERSION` | `0.131.0` | Override Codex client version independently of full UA string |
| `GITHUB_USER_AGENT` | `GitHubCopilotChat/0.45.1` | When GitHub Copilot Chat updates |

View File

@@ -336,7 +336,7 @@ process.env[`${PROVIDER_ID}_USER_AGENT`]
| Variable | Default Value | When to Update |
| ------------------------ | --------------------------------------------- | ------------------------------------------------------------- |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.145 (external, cli)` | When Anthropic releases a new CLI version |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.219 (external, cli)` | When Anthropic releases a new CLI version |
| `CODEX_USER_AGENT` | `codex-cli/0.132.0 (Windows 10.0.26200; x64)` | When OpenAI updates the Codex CLI |
| `CODEX_CLIENT_VERSION` | `0.131.0` | Override Codex client version independently of full UA string |
| `GITHUB_USER_AGENT` | `GitHubCopilotChat/0.45.1` | When GitHub Copilot Chat updates |

View File

@@ -336,7 +336,7 @@ process.env[`${PROVIDER_ID}_USER_AGENT`]
| Variable | Default Value | When to Update |
| ------------------------ | --------------------------------------------- | ------------------------------------------------------------- |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.145 (external, cli)` | When Anthropic releases a new CLI version |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.219 (external, cli)` | When Anthropic releases a new CLI version |
| `CODEX_USER_AGENT` | `codex-cli/0.132.0 (Windows 10.0.26200; x64)` | When OpenAI updates the Codex CLI |
| `CODEX_CLIENT_VERSION` | `0.131.0` | Override Codex client version independently of full UA string |
| `GITHUB_USER_AGENT` | `GitHubCopilotChat/0.45.1` | When GitHub Copilot Chat updates |

View File

@@ -336,7 +336,7 @@ process.env[`${PROVIDER_ID}_USER_AGENT`]
| Variable | Default Value | When to Update |
| ------------------------ | --------------------------------------------- | ------------------------------------------------------------- |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.145 (external, cli)` | When Anthropic releases a new CLI version |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.219 (external, cli)` | When Anthropic releases a new CLI version |
| `CODEX_USER_AGENT` | `codex-cli/0.132.0 (Windows 10.0.26200; x64)` | When OpenAI updates the Codex CLI |
| `CODEX_CLIENT_VERSION` | `0.131.0` | Override Codex client version independently of full UA string |
| `GITHUB_USER_AGENT` | `GitHubCopilotChat/0.45.1` | When GitHub Copilot Chat updates |

View File

@@ -336,7 +336,7 @@ process.env[`${PROVIDER_ID}_USER_AGENT`]
| Variable | Default Value | When to Update |
| ------------------------ | --------------------------------------------- | ------------------------------------------------------------- |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.145 (external, cli)` | When Anthropic releases a new CLI version |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.219 (external, cli)` | When Anthropic releases a new CLI version |
| `CODEX_USER_AGENT` | `codex-cli/0.132.0 (Windows 10.0.26200; x64)` | When OpenAI updates the Codex CLI |
| `CODEX_CLIENT_VERSION` | `0.131.0` | Override Codex client version independently of full UA string |
| `GITHUB_USER_AGENT` | `GitHubCopilotChat/0.45.1` | When GitHub Copilot Chat updates |

View File

@@ -336,7 +336,7 @@ process.env[`${PROVIDER_ID}_USER_AGENT`]
| Variable | Default Value | When to Update |
| ------------------------ | --------------------------------------------- | ------------------------------------------------------------- |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.145 (external, cli)` | When Anthropic releases a new CLI version |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.219 (external, cli)` | When Anthropic releases a new CLI version |
| `CODEX_USER_AGENT` | `codex-cli/0.132.0 (Windows 10.0.26200; x64)` | When OpenAI updates the Codex CLI |
| `CODEX_CLIENT_VERSION` | `0.131.0` | Override Codex client version independently of full UA string |
| `GITHUB_USER_AGENT` | `GitHubCopilotChat/0.45.1` | When GitHub Copilot Chat updates |

View File

@@ -565,7 +565,7 @@ post_install() {
**GitHub Copilot (`gh/`)** — OAuth: `gh/gpt-5.5`, `gh/gpt-5.4`, `gh/gpt-5.4-mini`, `gh/gpt-5-mini`, `gh/gpt-5.3-codex`, `gh/claude-opus-4.7`, `gh/claude-opus-4.6`, `gh/claude-opus-4-5-20251101`, `gh/claude-sonnet-4.6`, `gh/claude-sonnet-4.5`, `gh/claude-haiku-4.5`, `gh/gemini-3.1-pro-preview`, `gh/gemini-3-flash-preview`, `gh/oswe-vscode-prime`
**Kiro (`kr/`)**FREE OAuth: `kr/auto-kiro`, `kr/claude-opus-4.7`, `kr/claude-opus-4.6`, `kr/claude-sonnet-4.6`, `kr/claude-sonnet-4.5`, `kr/claude-haiku-4.5`, `kr/deepseek-3.2`, `kr/minimax-m2.5`, `kr/minimax-m2.1`, `kr/glm-5`, `kr/qwen3-coder-next`
**Kiro (`kr/`)**免费 OAuth:请使用 **控制面板 → 提供商 → Kiro → 可用模型** 中显示的实时目录。可用模型取决于账户和套餐。
**Qoder (`if/`)** — FREE OAuth: `if/kimi-k2-0905`, `if/kimi-k2`, `if/qwen3-coder-plus`, `if/qwen3-max`, `if/qwen3-max-preview`, `if/qwen3-vl-plus`, `if/qwen3-32b`, `if/qwen3-235b-a22b-thinking-2507`, `if/qwen3-235b-a22b-instruct`, `if/qwen3-235b`, `if/deepseek-v3.2`, `if/deepseek-v3`, `if/deepseek-r1`, `if/qoder-rome-30ba3b`

File diff suppressed because it is too large Load Diff

View File

@@ -4,7 +4,7 @@
---
該文件為在此碼庫中使用 Claude Code (claude.ai/code) 提供指導。
該文件為在此程式碼庫中使用 Claude Code (claude.ai/code) 提供指導。
## 快速開始
@@ -26,7 +26,7 @@ npm run check:cycles # 檢測循環依賴
# 單個測試文件Node.js 原生測試運行器 — 大多數測試)
node --import tsx/esm --test tests/unit/your-file.test.ts
# VitestMCP 伺服器autoCombo緩存
# VitestMCP 伺服器autoCombo快取
npm run test:vitest
# 所有測試套件
@@ -37,7 +37,7 @@ npm run test:all
---
## 項目概覽
## 專案概覽
**OmniRoute** — 統一的 AI 代理/路由器。一個端點160+ LLM 提供者,自動回退。
@@ -47,14 +47,14 @@ npm run test:all
| 處理程序 | `open-sse/handlers/` | 請求處理(聊天、嵌入等) |
| 執行器 | `open-sse/executors/` | 特定提供者的 HTTP 調度 |
| 轉換器 | `open-sse/translator/` | 格式轉換OpenAI↔Claude↔Gemini |
| 轉換器 | `open-sse/transformer/` | 應 API ↔ 聊天完成 |
| 服務 | `open-sse/services/` | 組合路由、速率限制、緩存等 |
| 資料庫 | `src/lib/db/` | SQLite 域模45+ 文件55 次遷移) |
| 轉換器 | `open-sse/transformer/` | 應 API ↔ 聊天完成 |
| 服務 | `open-sse/services/` | 組合路由、速率限制、快取等 |
| 資料庫 | `src/lib/db/` | SQLite 域模45+ 文件55 次遷移) |
| 域/策略 | `src/domain/` | 策略引擎、成本規則、回退邏輯 |
| MCP 伺服器 | `open-sse/mcp-server/` | 37 個工具30 基礎 + 3 內存 + 4 技能3 個傳輸,大約 13 個範圍 |
| MCP 伺服器 | `open-sse/mcp-server/` | 37 個工具30 基礎 + 3 記憶 + 4 技能3 個傳輸,大約 13 個範圍 |
| A2A 伺服器 | `src/lib/a2a/` | JSON-RPC 2.0 代理協議 |
| 技能 | `src/lib/skills/` | 可擴展的技能框架 |
| 內存 | `src/lib/memory/` | 持久化對話內存 |
| 記憶 | `src/lib/memory/` | 持久化對話記憶 |
Monorepo: `src/`Next.js 16 應用),`open-sse/`(流媒體引擎工作區),`electron/`(桌面應用),`tests/``bin/`CLI 入口點)。
@@ -66,17 +66,17 @@ Monorepo: `src/`Next.js 16 應用),`open-sse/`(流媒體引擎工作區
客戶端 → /v1/chat/completions (Next.js 路由)
→ CORS → Zod 驗證 → 認證? → 策略檢查 → 提示注入保護
→ handleChatCore() [open-sse/handlers/chatCore.ts]
緩存檢查 → 速率限制 → 組合路由?
→ resolveComboTargets() → 針對每個目標調用 handleSingleModel()
快取檢查 → 速率限制 → 組合路由?
→ resolveComboTargets() → 針對每個目標呼叫 handleSingleModel()
→ translateRequest() → getExecutor() → executor.execute()
→ fetch() 上 → 重試 w/ 回退
應翻譯 → SSE 流或 JSON
→ fetch() 上 → 重試 w/ 回退
應翻譯 → SSE 流或 JSON
→ 如果是 Responses API: responsesTransformer.ts TransformStream
```
API 路由遵循一致的模式:`路由 → CORS 預檢 → Zod 請求體驗證 → 可選認證 (extractApiKey/isValidApiKey) → API 密鑰策略執行 → 處理程序委派 (open-sse)`。沒有全的 Next.js 中間件 — 攔截是路由特定的。
API 路由遵循一致的模式:`路由 → CORS 預檢 → Zod 請求體驗證 → 可選認證 (extractApiKey/isValidApiKey) → API 密鑰策略執行 → 處理程序委派 (open-sse)`。沒有全的 Next.js 中間件 — 攔截是路由特定的。
**組合路由** (`open-sse/services/combo.ts`): 14 種策略優先級、加權、優先填充、輪詢、P2C、隨機、最少使用、成本優化、重置感知、嚴格隨機、自動、lkgp、上下文優化、上下文中繼。每個目標調用 `handleSingleModel()`,該函數用每個目標的錯誤處理和電路斷路器檢查包裝 `handleChatCore()`。有關 9 因子自動組合評分的資訊,請參見 `docs/routing/AUTO-COMBO.md`,有關 3 層彈性的資訊,請參見 `docs/architecture/RESILIENCE_GUIDE.md`
**組合路由** (`open-sse/services/combo.ts`): 14 種策略優先級、加權、優先填充、輪詢、P2C、隨機、最少使用、成本優化、重置感知、嚴格隨機、自動、lkgp、上下文優化、上下文中繼。每個目標呼叫 `handleSingleModel()`,該函數用每個目標的錯誤處理和電路斷路器檢查包裝 `handleChatCore()`。有關 9 因子自動組合評分的資訊,請參見 `docs/routing/AUTO-COMBO.md`,有關 3 層彈性的資訊,請參見 `docs/architecture/RESILIENCE_GUIDE.md`
---
@@ -91,7 +91,7 @@ OmniRoute 有三種相關但不同的臨時故障機制。在調試路由行為
**範圍**: 整個提供者,例如 `glm``openai``anthropic`
**目的**: 停止向一個在上/服務級別反覆失敗的提供者發送流量,以便一個不健康的提供者不會減慢每個請求的速度。
**目的**: 停止向一個在上/服務級別反覆失敗的提供者發送流量,以便一個不健康的提供者不會減慢每個請求的速度。
**實現**:
@@ -104,10 +104,10 @@ OmniRoute 有三種相關但不同的臨時故障機制。在調試路由行為
**狀態**:
- `CLOSED`: 允許正常流量。
- `OPEN`: 提供者暫時被阻止;調用者會收到提供者電路打開的應,或者組合路由跳過到另一個目標。
- `OPEN`: 提供者暫時被阻止;呼叫者會收到提供者電路打開的應,或者組合路由跳過到另一個目標。
- `HALF_OPEN`: 重置超時已過;允許探測請求。成功關閉斷路器,失敗再次打開。
**默認** (`open-sse/config/constants.ts`):
**預設** (`open-sse/config/constants.ts`):
- OAuth 提供者: 閾值 `3`,重置超時 `60s`
- API 密鑰提供者: 閾值 `5`,重置超時 `30s`
@@ -121,7 +121,7 @@ OmniRoute 有三種相關但不同的臨時故障機制。在調試路由行為
不要因正常的帳戶/密鑰/模型錯誤(如大多數 `401``403``429` 情況)而觸發整個提供者斷路器。這些通常屬於連接冷卻或模型鎖定。除非被歸類為終端提供者/帳戶錯誤,否則通用 API 密鑰提供者的 `403` 應該是可恢復的。
斷路器使用懶惰恢復,而不是後定時器。當 `OPEN` 過期時,像 `getStatus()``canExecute()``getRetryAfterMs()` 這樣的讀取會將狀態刷新為 `HALF_OPEN`,以便儀板和組合候選構建器不會永遠排除一個過期的提供者。
斷路器使用懶惰恢復,而不是後定時器。當 `OPEN` 過期時,像 `getStatus()``canExecute()``getRetryAfterMs()` 這樣的讀取會將狀態刷新為 `HALF_OPEN`,以便儀板和組合候選構建器不會永遠排除一個過期的提供者。
### 連接冷卻
@@ -155,11 +155,11 @@ new Date(rateLimitedUntil).getTime() > Date.now();
冷卻也是懶惰的:當 `rateLimitedUntil` 在過去時,連接再次變得合格。在成功使用時,`clearAccountError()` 會清除 `testStatus``rateLimitedUntil`、錯誤欄位和 `backoffLevel`
默認連接冷卻行為:
預設連接冷卻行為:
- OAuth 基礎冷卻: `5s`
- API 密鑰基礎冷卻: `3s`
- API 密鑰 `429` 應優先考慮上重試提示(`Retry-After`、重置頭或可解析的重置文本),如果可用。
- API 密鑰 `429` 應優先考慮上重試提示(`Retry-After`、重置頭或可解析的重置文本),如果可用。
- 重複的可恢復故障使用指數回退:
```ts
@@ -187,26 +187,26 @@ baseCooldownMs * 2 ** failureIndex;
### 調試指導
- 如果一個提供者的所有密鑰都被跳過,請檢查提供者斷路器狀態和每個連接的 `rateLimitedUntil`/`testStatus`
- 如果一個提供者在重置窗口後似乎被永久排除,請檢查碼是否在讀取原始 `state` 而不是使用 `getStatus()`/`canExecute()`
- 如果一個提供者在重置窗口後似乎被永久排除,請檢查程式碼是否在讀取原始 `state` 而不是使用 `getStatus()`/`canExecute()`
- 如果一個提供者密鑰失敗但其他密鑰應該有效,請優先考慮連接冷卻而不是提供者斷路器。
- 如果只有一個模型失敗,請優先考慮模型鎖定而不是連接冷卻。
- 如果一個狀態應該自我恢復,它應該有一個未來的時間戳/重置超時和一個讀取路徑來刷新過期狀態。永久狀態需要手動憑據或設定更改。
## 關鍵約定
### 碼風格
### 程式碼風格
- **2個空格**分號雙引號100字符寬度es5尾隨逗號通過lint-staged和Prettier強制執行
- **導入**:外部 → 內部(`@/``@omniroute/open-sse`)→ 相對
- **命名**:文件=camelCase/kebab組件=PascalCase常量=UPPER_SNAKE
- **ESLint**`no-eval``no-implied-eval``no-new-func` = 在任何地方都報錯;`no-explicit-any` = 在`open-sse/``tests/`中警告
- **TypeScript**`strict: false`目標ES2022esnext解析器為打包器。優先使用顯式類型。
- **TypeScript**`strict: false`目標ES2022esnext解析器為打包器。優先使用顯式類型。
### 資料庫
- **始終**通過`src/lib/db/`域模 — **絕不**在路由或處理程序中編寫原始SQL
- **始終**通過`src/lib/db/`域模 — **絕不**在路由或處理程序中編寫原始SQL
- **絕不**在`src/lib/localDb.ts`中添加邏輯(僅為重新導出層)
- **絕不**從`localDb.ts`進行桶導入 — 而是導入特定的`db/`
- **絕不**從`localDb.ts`進行桶導入 — 而是導入特定的`db/`
- DB單例`getDbInstance()`來自`src/lib/db/core.ts`WAL日誌記錄
- 遷移:`src/lib/db/migrations/` — 版本化的SQL文件冪等在事務中運行
@@ -221,11 +221,11 @@ baseCooldownMs * 2 ** failureIndex;
- **絕不**使用`eval()``new Function()`或隱式eval
- 使用Zod模式驗證所有輸入
- 在靜態存儲中加密憑據AES-256-GCM
-頭部拒絕列表:`src/shared/constants/upstreamHeaders.ts` — 編輯時保持清理、Zod模式和單元測試一致
- **公共上憑據**Gemini/Antigravity/Windsurf風格的OAuth client_id/secret + 從公共CLI提取的Firebase Web密鑰**必須**通過`resolvePublicCred()`嵌入,來自`open-sse/utils/publicCreds.ts` — **絕不**作為字串字面量。請參見`docs/security/PUBLIC_CREDS.md`以獲取強制模式。
- **錯誤應**HTTP / SSE / 執行器 / MCP處理程序**必須**通過`buildErrorBody()``sanitizeErrorMessage()`路由,來自`open-sse/utils/error.ts` — **絕不**將原始`err.stack``err.message`放入應體中。請參見`docs/security/ERROR_SANITIZATION.md`
- **從變量構建的Shell命令**:在調用`exec()`/`spawn()`時,如果腳本需要運行時值,通過`env`選項傳遞自動進行Shell轉義 — **絕不**將不受信任/外部路徑字串插入腳本體中。參考:`src/mitm/cert/install.ts::updateNssDatabases`
- **默認安全庫**[tldrsec/awesome-secure-defaults](https://github.com/tldrsec/awesome-secure-defaults)在添加新的安全敏感表面時優先使用Helmet.js、DOMPurify、ssrf-req-filter、safe-regex、Google Tink而不是自定義實現。
-頭部拒絕列表:`src/shared/constants/upstreamHeaders.ts` — 編輯時保持清理、Zod模式和單元測試一致
- **公共上憑據**Gemini/Antigravity/Windsurf風格的OAuth client_id/secret + 從公共CLI提取的Firebase Web密鑰**必須**通過`resolvePublicCred()`嵌入,來自`open-sse/utils/publicCreds.ts` — **絕不**作為字串字面量。請參見`docs/security/PUBLIC_CREDS.md`以獲取強制模式。
- **錯誤應**HTTP / SSE / 執行器 / MCP處理程序**必須**通過`buildErrorBody()``sanitizeErrorMessage()`路由,來自`open-sse/utils/error.ts` — **絕不**將原始`err.stack``err.message`放入應體中。請參見`docs/security/ERROR_SANITIZATION.md`
- **從變量構建的Shell命令**:在呼叫`exec()`/`spawn()`時,如果腳本需要運行時值,通過`env`選項傳遞自動進行Shell轉義 — **絕不**將不受信任/外部路徑字串插入腳本體中。參考:`src/mitm/cert/install.ts::updateNssDatabases`
- **預設安全庫**[tldrsec/awesome-secure-defaults](https://github.com/tldrsec/awesome-secure-defaults)在添加新的安全敏感表面時優先使用Helmet.js、DOMPurify、ssrf-req-filter、safe-regex、Google Tink而不是自定義實現。
---
@@ -236,9 +236,9 @@ baseCooldownMs * 2 ** failureIndex;
1.`src/shared/constants/providers.ts`中註冊加載時進行Zod驗證
2. 如果需要自定義邏輯,則在`open-sse/executors/`中添加執行器(擴展`BaseExecutor`
3. 如果是非OpenAI格式則在`open-sse/translator/`中添加翻譯器
4. 如果基於OAuth則在`src/lib/oauth/constants/oauth.ts`中添加OAuth設定 — 如果上CLI提供公共client_id/secret則通過`resolvePublicCred()`嵌入(見`docs/security/PUBLIC_CREDS.md`**絕不**作為字面量
4. 如果基於OAuth則在`src/lib/oauth/constants/oauth.ts`中添加OAuth設定 — 如果上CLI提供公共client_id/secret則通過`resolvePublicCred()`嵌入(見`docs/security/PUBLIC_CREDS.md`**絕不**作為字面量
5.`open-sse/config/providerRegistry.ts`中註冊模型
6.`tests/unit/`中編寫測試(如果添加了新的嵌入默認則包括publicCreds形狀斷言
6.`tests/unit/`中編寫測試(如果添加了新的嵌入預設則包括publicCreds形狀斷言
### 添加新API路由
@@ -246,10 +246,10 @@ baseCooldownMs * 2 ** failureIndex;
2. 創建`route.ts`,包含`GET`/`POST`處理程序
3. 遵循模式CORS → Zod主體驗證 → 可選身份驗證 → 處理程序委託
4. 處理程序放在`open-sse/handlers/`中(從那裡導入,而不是內聯)
5. 錯誤應使用`buildErrorBody()` / `errorResponse()`來自`open-sse/utils/error.ts`(自動清理 — 絕不將`err.stack``err.message`原樣放入主體中)。請參見`docs/security/ERROR_SANITIZATION.md`
6. 添加測試 — 包括至少一個斷言,確保錯誤應不洩露堆棧跟蹤(`!body.error.message.includes("at /")`
5. 錯誤應使用`buildErrorBody()` / `errorResponse()`來自`open-sse/utils/error.ts`(自動清理 — 絕不將`err.stack``err.message`原樣放入主體中)。請參見`docs/security/ERROR_SANITIZATION.md`
6. 添加測試 — 包括至少一個斷言,確保錯誤應不洩露堆棧跟蹤(`!body.error.message.includes("at /")`
### 添加新DB模
### 添加新DB模
1. 創建`src/lib/db/yourModule.ts` — 從`./core.ts`導入`getDbInstance`
2. 導出您的域表的CRUD函數
@@ -262,7 +262,7 @@ baseCooldownMs * 2 ** failureIndex;
1.`open-sse/mcp-server/tools/`中添加工具定義包含Zod輸入模式 + 異步處理程序
2. 在工具集中註冊(通過`createMcpServer()`連接)
3. 分配給適當的範圍
4. 編寫測試(工具調用記錄到`mcp_audit`表中)
4. 編寫測試(工具呼叫記錄到`mcp_audit`表中)
### 添加新A2A技能
@@ -283,16 +283,16 @@ baseCooldownMs * 2 ** failureIndex;
### 添加新護欄 / 評估 / 技能 / Webhook事件
- 護欄:`src/lib/guardrails/` → 文`docs/security/GUARDRAILS.md`
- 評估套件:`src/lib/evals/` → 文`docs/frameworks/EVALS.md`
- 技能(沙盒):`src/lib/skills/` → 文`docs/frameworks/SKILLS.md`
- Webhook事件`src/lib/webhookDispatcher.ts` → 文`docs/frameworks/WEBHOOKS.md`
- 護欄:`src/lib/guardrails/` → 文`docs/security/GUARDRAILS.md`
- 評估套件:`src/lib/evals/` → 文`docs/frameworks/EVALS.md`
- 技能(沙盒):`src/lib/skills/` → 文`docs/frameworks/SKILLS.md`
- Webhook事件`src/lib/webhookDispatcher.ts` → 文`docs/frameworks/WEBHOOKS.md`
## 參考文
## 參考文
對於任何非平凡的更改,請先閱讀相應的深入分析:
| 領域 | 文 |
| 領域 | 文 |
| ------------------------------- | ----------------------------------------------------------------- |
| 倉庫導航 | `docs/architecture/REPOSITORY_MAP.md` |
| 架構 | `docs/architecture/ARCHITECTURE.md` |
@@ -301,10 +301,10 @@ baseCooldownMs * 2 ** failureIndex;
| 彈性3種機制 | `docs/architecture/RESILIENCE_GUIDE.md` |
| 推理重放 | `docs/routing/REASONING_REPLAY.md` |
| 技能框架 | `docs/frameworks/SKILLS.md` |
| 內存系統FTS5 + Qdrant | `docs/frameworks/MEMORY.md` |
| 記憶系統FTS5 + Qdrant | `docs/frameworks/MEMORY.md` |
| 雲代理 | `docs/frameworks/CLOUD_AGENT.md` |
| 保護措施PII / 注入 / 視覺) | `docs/security/GUARDRAILS.md` |
| 公共上憑證Gemini等 | `docs/security/PUBLIC_CREDS.md` |
| 公共上憑證Gemini等 | `docs/security/PUBLIC_CREDS.md` |
| 錯誤資訊清理 | `docs/security/ERROR_SANITIZATION.md` |
| 評估 | `docs/frameworks/EVALS.md` |
| 合規 / 審計 | `docs/security/COMPLIANCE.md` |
@@ -333,11 +333,11 @@ baseCooldownMs * 2 ** failureIndex;
| 覆蓋門限 | `npm run test:coverage` (75/75/75/70 — 語句/行/函數/分支) |
| 覆蓋報告 | `npm run coverage:report` |
**PR 規則**:如果您更改了 `src/``open-sse/``electron/``bin/` 中的生產代碼,您必須在同一 PR 中包含或更新測試。
**PR 規則**:如果您更改了 `src/``open-sse/``electron/``bin/` 中的正式程式碼,您必須在同一 PR 中包含或更新測試。
**測試層級偏好**:單元測試優先 → 集成測試(多模或資料庫狀態) → E2E僅限 UI/工作流)。在修復之前或同時將錯誤重現編碼為自動化測試。
**測試層級偏好**:單元測試優先 → 集成測試(多模或資料庫狀態) → E2E僅限 UI/工作流)。在修復之前或同時將錯誤重現編碼為自動化測試。
**Copilot 覆蓋政策**:當 PR 更改生產代碼且覆蓋率低於 75%(語句/行/函數)或 70%(分支)時,不僅僅報告 — 添加或更新測試,重新運行覆蓋門限,然後請求確認。在 PR 報告中包含運行的命令、已更改的測試文件和最終覆蓋結果。
**Copilot 覆蓋政策**:當 PR 更改正式程式碼且覆蓋率低於 75%(語句/行/函數)或 70%(分支)時,不僅僅報告 — 添加或更新測試,重新運行覆蓋門限,然後請求確認。在 PR 報告中包含運行的命令、已更改的測試文件和最終覆蓋結果。
---
@@ -364,10 +364,10 @@ git push -u origin feat/your-feature
## 環境
- **運行時**Node.js ≥20.20.2 <21 || ≥22.22.2 <23 || ≥24 <25, ES Modules
- **TypeScript**5.9+,目標 ES2022 esnext解析器 bundler
- **TypeScript**5.9+,目標 ES2022 esnext解析器 bundler
- **路徑別名**`@/*``src/``@omniroute/open-sse``open-sse/``@omniroute/open-sse/*``open-sse/*`
- **默認埠**20128API + 儀板在同一埠)
- **數據目錄**`DATA_DIR` 環境變量,默認`~/.omniroute/`
- **預設埠**20128API + 儀板在同一埠)
- **數據目錄**`DATA_DIR` 環境變量,預設`~/.omniroute/`
- **關鍵環境變量**`PORT``JWT_SECRET``API_KEY_SECRET``INITIAL_PASSWORD``REQUIRE_API_KEY``APP_LOG_LEVEL`
- 設置:`cp .env.example .env` 然後生成 `JWT_SECRET` (`openssl rand -base64 48`) 和 `API_KEY_SECRET` (`openssl rand -hex 32`)
@@ -379,15 +379,15 @@ git push -u origin feat/your-feature
2. 永遠不要在 `localDb.ts` 中添加邏輯
3. 永遠不要使用 `eval()` / `new Function()` / 隱式 eval
4. 永遠不要直接提交到 `main`
5. 永遠不要在路由中編寫原始 SQL — 使用 `src/lib/db/`
5. 永遠不要在路由中編寫原始 SQL — 使用 `src/lib/db/`
6. 永遠不要在 SSE 流中靜默吞噬錯誤
7. 始終使用 Zod 模式驗證輸入
8. 更改生產代碼時始終包含測試
8. 更改正式程式碼時始終包含測試
9. 覆蓋率必須保持在 ≥75%(語句、行、函數)/ ≥70%(分支)。當前測量:~82%。
10. 在沒有明確操作員批准的情況下,永遠不要繞過 Husky 鉤子(`--no-verify``--no-gpg-sign`)。
11. 永遠不要將公共上 OAuth client_id/secret 或 Firebase Web 密鑰作為字串文字嵌入 — 始終通過 `resolvePublicCred()` 處理(`open-sse/utils/publicCreds.ts`)。參見 `docs/security/PUBLIC_CREDS.md`
12. 永遠不要在 HTTP / SSE / 執行器應中返回原始 `err.stack` / `err.message` — 始終通過 `buildErrorBody()``sanitizeErrorMessage()` 路由(`open-sse/utils/error.ts`)。參見 `docs/security/ERROR_SANITIZATION.md`
13. 永遠不要將外部路徑或運行時值字串插值到傳遞給 `exec()`/`spawn()` 的 shell 腳本中 — 應通過 `env` 選項傳遞。參考:`src/mitm/cert/install.ts::updateNssDatabases`
14. 永遠不要在沒有 (a) 首先檢查上述模式文以查看幫助程序是否適用,以及 (b) 在駁回評論中記錄技術理由的情況下駁回 CodeQL / Secret-Scanning 警報。先例:在已經通過 `sanitizeErrorMessage()` 路由的調用站點上引發的 `js/stack-trace-exposure` 是已知的 CodeQL 限制(自定義清理程序未被識別) — 駁回為 `false positive`,引用 `docs/security/ERROR_SANITIZATION.md`
11. 永遠不要將公共上 OAuth client_id/secret 或 Firebase Web 密鑰作為字串文字嵌入 — 始終通過 `resolvePublicCred()` 處理(`open-sse/utils/publicCreds.ts`)。參見 `docs/security/PUBLIC_CREDS.md`
12. 永遠不要在 HTTP / SSE / 執行器應中返回原始 `err.stack` / `err.message` — 始終通過 `buildErrorBody()``sanitizeErrorMessage()` 路由(`open-sse/utils/error.ts`)。參見 `docs/security/ERROR_SANITIZATION.md`
13. 永遠不要將外部路徑或運行時值字串插值到傳遞給 `exec()`/`spawn()` 的 shell 腳本中 — 應通過 `env` 選項傳遞。參考:`src/mitm/cert/install.ts::updateNssDatabases`
14. 永遠不要在沒有 (a) 首先檢查上述模式文以查看幫助程序是否適用,以及 (b) 在駁回評論中記錄技術理由的情況下駁回 CodeQL / Secret-Scanning 警報。先例:在已經通過 `sanitizeErrorMessage()` 路由的呼叫站點上引發的 `js/stack-trace-exposure` 是已知的 CodeQL 限制(自定義清理程序未被識別) — 駁回為 `false positive`,引用 `docs/security/ERROR_SANITIZATION.md`
15. 永遠不要暴露生成子進程的路由(`/api/mcp/``/api/cli-tools/runtime/`),而不在 `src/server/authz/routeGuard.ts` 中進行 `isLocalOnlyPath()` 分類。迴環強制執行在任何身份驗證檢查之前無條件發生 — 通過隧道洩露的 JWT 不能觸發進程生成。參見 `docs/security/ROUTE_GUARD_TIERS.md`
16. 切勿在提交消息中包含將 AI 助手、LLM 或自動化帳戶作為作者的 `Co-Authored-By` 尾部(例如包含 "Claude"、"GPT"、"Copilot"、"Bot" 的名稱;`anthropic.com` / `openai.com` / 機器人擁有的 `noreply.github.com` 地址上的電子郵件)。這類尾部會將 commit 歸屬路由到 GitHub 上的機器人帳戶,從而在 PR 歷史中隱藏真正的作者 (`diegosouzapw`)。人類協作者——包括 upstream PR 作者和被移植到 OmniRoute 的 issue 報告者——可以並且應該使用標準的 `Co-authored-by: Name <email>` 尾部進行署名upstream-port 工作流(`/port-upstream-features``/port-upstream-issues`)依賴於此。

View File

@@ -35,22 +35,22 @@ echo "API_KEY_SECRET=$(openssl rand -hex 32)" >> .env
開發用的關鍵變數:
| 變數 | 開發環境預設值 | 說明 |
| ---------------------- | ----------------------- | ------------------ |
| `PORT` | `20128` | 伺服器埠號 |
| `NEXT_PUBLIC_BASE_URL` | `http://localhost:20128` | 前端的基礎 URL |
| `JWT_SECRET` | (上方產生) | JWT 簽章密鑰 |
| `INITIAL_PASSWORD` | `CHANGEME` | 首次登入密碼 |
| `APP_LOG_LEVEL` | `info` | 日誌詳細程度 |
| 變數 | 開發環境預設值 | 說明 |
| ---------------------- | ------------------------ | -------------- |
| `PORT` | `20128` | 伺服器埠號 |
| `NEXT_PUBLIC_BASE_URL` | `http://localhost:20128` | 前端的基礎 URL |
| `JWT_SECRET` | (上方產生) | JWT 簽章密鑰 |
| `INITIAL_PASSWORD` | `CHANGEME` | 首次登入密碼 |
| `APP_LOG_LEVEL` | `info` | 日誌詳細程度 |
### 儀表板設定
儀表板提供 UI 開關,可設定也能透過環境變數配置的功能:
| 設定位置 | 開關 | 說明 |
| ------------------ | -------------- | ---------------------------- |
| 設定 → 進階 | 除錯模式 | 啟用除錯請求日誌UI |
| 設定 → 一般 | 側邊欄可見性 | 顯示/隱藏側邊欄區塊 |
| 設定位置 | 開關 | 說明 |
| ----------- | ------------ | ---------------------- |
| 設定 → 進階 | 除錯模式 | 啟用除錯請求日誌UI |
| 設定 → 一般 | 側邊欄可見性 | 顯示/隱藏側邊欄區塊 |
這些設定儲存在資料庫中,重新啟動後仍會保留,設定後會覆蓋環境變數的預設值。
@@ -73,11 +73,11 @@ PORT=20128 NEXT_PUBLIC_BASE_URL=http://localhost:20128 npm run dev
### 建置輸出結構
| 目錄 | 內容 | 版本追蹤 |
| ---------- | -------------------------------------------------- | -------- |
| `src/` | 應用程式原始碼TypeScript / TSX | 是 |
| `.build/` | 中間產物 — `next build` 輸出gitignored`distDir = .build/next` | 否 |
| `dist/` | 可發佈套件 — 由 `assembleStandalone` 組裝gitignored | 否 |
| 目錄 | 內容 | 版本追蹤 |
| --------- | ------------------------------------------------------------------- | -------- |
| `src/` | 應用程式原始碼TypeScript / TSX | 是 |
| `.build/` | 中間產物 — `next build` 輸出gitignored`distDir = .build/next` | 否 |
| `dist/` | 可發佈套件 — 由 `assembleStandalone` 組裝gitignored | 否 |
建置管線為單次傳遞:
@@ -113,14 +113,14 @@ git push -u origin feat/your-feature-name
### 分支命名
| 前綴 | 用途 |
| ------------ | ---------------------- |
| `feat/` | 新功能 |
| `fix/` | 錯誤修正 |
| `refactor/` | 程式碼重構 |
| `docs/` | 文件變更 |
| `test/` | 測試新增/修正 |
| `chore/` | 工具、CI、依賴項目 |
| 前綴 | 用途 |
| ----------- | ------------------ |
| `feat/` | 新功能 |
| `fix/` | 錯誤修正 |
| `refactor/` | 程式碼重構 |
| `docs/` | 文件變更 |
| `test/` | 測試新增/修正 |
| `chore/` | 工具、CI、依賴項目 |
### 提交訊息
@@ -167,17 +167,17 @@ npm run coverage:report
npm run lint
npm run check
# 實際上游 combo 冒煙測試(需要 VPS 存取 + 實際提供額度)
# 會打到真實提供 — 會花一點錢。絕對不會在 CI 中執行。沒有閘道時會乾淨地跳過。
# 實際上游 combo 冒煙測試(需要 VPS 存取 + 實際提供額度)
# 會打到真實提供 — 會花一點錢。絕對不會在 CI 中執行。沒有閘道時會乾淨地跳過。
# 需要ssh root@192.168.0.15 存取(從 VPS 讀取唯讀資料庫快照)。
RUN_COMBO_LIVE=1 npm run test:combo:live
# Phase-3 VPS 實戰冒煙測試 — 純 Node ESM 腳本,直接打到 .15 伺服器。
# 需要ssh root@192.168.0.15 存取combo 透過 SSH sqlite 建立/刪除)。
# 會打到真實提供(少量費用)。只會建立/刪除 __live_test__* combo。絕對不會在 CI 中執行。
# 會打到真實提供(少量費用)。只會建立/刪除 __live_test__* combo。絕對不會在 CI 中執行。
# REQUIRE_API_KEY=false on .15 所以不需要 API 金鑰,但如果設定了 COMBO_LIVE_BASE_URL / COMBO_LIVE_API_KEY 則會遵循。
npm run test:combo:live:vps # 7 個 HTTP 情境priority/round-robin/weighted/cost/fusion/auto + health
npm run test:combo:live:vps:failover # 增加實際跨提供容錯情境(共 8 個)
npm run test:combo:live:vps:failover # 增加實際跨提供容錯情境(共 8 個)
```
覆蓋率注意事項:
@@ -201,7 +201,7 @@ npm run test:combo:live:vps:failover # 增加實際跨提供商容錯情境
目前測試狀態:**122 個單元測試檔案** 涵蓋:
- 提供轉換器與格式轉換
- 提供轉換器與格式轉換
- 速率限制、斷路器與彈性
- 語意快取、冪等性、進度追蹤
- 資料庫操作與結構21 個 DB 模組)
@@ -238,7 +238,7 @@ src/ # TypeScript (.ts / .tsx)
│ ├── compliance/ # 合規政策引擎
│ ├── db/ # SQLite 資料庫層21 個模組 + 16 個遷移)
│ ├── memory/ # 持久對話記憶
│ ├── oauth/ # OAuth 提供、服務與工具
│ ├── oauth/ # OAuth 提供、服務與工具
│ ├── skills/ # 可擴展技能框架
│ ├── usage/ # 用量追蹤與成本計算
│ └── localDb.ts # 僅作為重新匯出層 — 永遠不要在此新增邏輯
@@ -246,13 +246,13 @@ src/ # TypeScript (.ts / .tsx)
├── mitm/ # MITM 代理憑證、DNS、目標路由
├── shared/
│ ├── components/ # React 元件 (.tsx)
│ ├── constants/ # 提供定義177、MCP 範圍、14 種路由策略
│ ├── constants/ # 提供定義177、MCP 範圍、14 種路由策略
│ ├── utils/ # 斷路器、清理工具、認證輔助
│ └── validation/ # Zod v4 結構
└── sse/ # SSE 代理管線
open-sse/ # @omniroute/open-sse 工作區
├── executors/ # 14 個提供專用請求執行器
├── executors/ # 14 個提供專用請求執行器
├── handlers/ # 11 個請求處理器(聊天、回應、嵌入、圖片等)
├── mcp-server/ # MCP 伺服器25 個工具、3 種傳輸、10 個範圍)
├── services/ # 36+ 服務combo、autoCombo、rateLimitManager 等)
@@ -282,7 +282,7 @@ docs/
├── i18n/ # 國際化 README 翻譯
├── marketing/ # 行銷素材
├── ops/ # 部署、代理、覆蓋率、發布
├── providers/ # 提供專用文件
├── providers/ # 提供專用文件
├── reference/ # API 參考、環境變數、CLI 工具、免費方案
├── releases/ # 版本說明
├── routing/ # Auto-combo 引擎、推理重播
@@ -293,9 +293,9 @@ docs/
---
## 新增提供
## 新增提供
### 步驟 1註冊提供常數
### 步驟 1註冊提供常數
新增至 `src/shared/constants/providers.ts` — 在模組載入時以 Zod 驗證。
@@ -311,7 +311,7 @@ docs/
`src/lib/oauth/constants/oauth.ts` 中新增 OAuth 憑證,並在 `src/lib/oauth/services/` 中新增服務。
如果上游提供在其公開 CLI / 瀏覽器套件中分發了公開的 OAuth client_id/secret 或 Firebase Web API 金鑰,**請勿**將其嵌入為字串字面值。請使用 `open-sse/utils/publicCreds.ts` 中的 `resolvePublicCred()`,並在 `EMBEDDED_DEFAULTS` 中新增一個遮罩位元組條目。完整的強制性工作流程記錄於 [`docs/security/PUBLIC_CREDS.md`](./docs/security/PUBLIC_CREDS.md)。
如果上游提供在其公開 CLI / 瀏覽器套件中分發了公開的 OAuth client_id/secret 或 Firebase Web API 金鑰,**請勿**將其嵌入為字串字面值。請使用 `open-sse/utils/publicCreds.ts` 中的 `resolvePublicCred()`,並在 `EMBEDDED_DEFAULTS` 中新增一個遮罩位元組條目。完整的強制性工作流程記錄於 [`docs/security/PUBLIC_CREDS.md`](./docs/security/PUBLIC_CREDS.md)。
在處理器/執行器內部,傳送到客戶端的錯誤訊息必須通過 `open-sse/utils/error.ts``buildErrorBody()` / `sanitizeErrorMessage()` — 絕對不要將原始 `err.stack``err.message` 放入回應主體。請參閱 [`docs/security/ERROR_SANITIZATION.md`](./docs/security/ERROR_SANITIZATION.md)。
@@ -323,7 +323,7 @@ docs/
`tests/unit/` 中撰寫單元測試,至少涵蓋:
- 提供註冊
- 提供註冊
- 請求/回應轉換
- 錯誤處理

Some files were not shown because too many files have changed in this diff Show More