fix(ci): clear the release/v3.8.51 base-reds on the PR fast path (#13635)

* docs: bring the provider count to the live 358 across the reference, diagrams and llm.txt mirrors

* chore(skills): regenerate the cli-tunnel SKILL.md for the tunnel create positional

* test: clear the ESLint errors in the volcengine upsert and resource-pressure tests

* test(autoCombo): complete the mode-pack ProviderCandidate fixtures for the open-sse typecheck

* fix(ci): allow the opencode-plugin-v2 workspace package in the pack artifact policy

* docs: list the WAL, vacuum, sql.js and pressure self-restart env vars in .env.example

* refactor(db): move the synced-model provider purge into its persistence module to break the models/providers cycle

* test(memory): use a plain label for the rerank loopback key fixture so gitleaks stays at zero

* chore(ci): register the eleven covering unit tests in stryker tap.testFiles

* test(grok-cli): run the reset-credit tests on a fixture clock inside the captured token window

* test(combo): seed real provider connections for the reset-aware strategy tests

* fix(db): keep operator custom models out of the listing-only synced catalog reader

* fix(i18n): translate the new settings and combo keys for vi and pt-BR and restore the zh-TW glossary term

* fix(sse): carry the upstream error code and type through the provider execution pipeline

* test(sse): re-point the chatCore and combo source guards at the split modules and refresh the translate-path golden

* fix(oauth): keep the server-only OAuth constants out of the provider detail client bundle

* test: align the sql.js, webpack, injection-scan and error-boundary guards with their merged contracts

* docs(changelog): record the v3.8.51 base-red sweep

* fix(sse): anchor the glued-prefix sk- credential pattern so error redaction scans in linear time

* docs(changelog): note the linear credential scan in the base-red sweep

---------

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
This commit is contained in:
Damian Pozimski
2026-09-15 13:51:45 +02:00
committed by GitHub
parent f782f3b1e0
commit 9442bdef0f
42 changed files with 483 additions and 252 deletions

View File

@@ -1140,6 +1140,22 @@ PROVIDER_LIMITS_SYNC_SPACING_MS=1500
# Used by: src/lib/db/core.ts::getWalTruncateIntervalMs().
#OMNIROUTE_WAL_TRUNCATE_INTERVAL_MS=21600000
# Frequent wal_checkpoint(PASSIVE) cadence (ms). Set to 0 to disable. Default: 300000 (5m).
# Used by: src/lib/db/walMaintenance.ts.
#OMNIROUTE_WAL_PASSIVE_INTERVAL_MS=300000
# WAL size (MB) above which a PASSIVE tick escalates to wal_checkpoint(TRUNCATE). Default: 256.
# Used by: src/lib/db/walMaintenance.ts.
#OMNIROUTE_WAL_GUARD_MAX_MB=256
# Minimum rows a cleanup must delete before the post-cleanup VACUUM runs. Default: 1000.
# 0 always vacuums when rows were freed. Used by: src/lib/db/cleanup.ts.
#OMNIROUTE_VACUUM_MIN_DELETED_ROWS=1000
# Explicit path to sql-wasm.wasm for the sql.js fallback adapter. Default: auto-detect.
# Used by: src/lib/db/adapters/sqljsAdapter.ts.
#OMNIROUTE_SQLJS_WASM_PATH=
# Skip the Redis-backed auth cache used by API key lookups (forces DB reads).
# Used by: src/lib/db/apiKeys.ts. Set to 1 to disable. Default: enabled.
#OMNIROUTE_DISABLE_REDIS_AUTH_CACHE=0
@@ -1800,6 +1816,13 @@ APP_LOG_TO_FILE=true
# Override only to hand-tune for a known workload.
# HEAP_PRESSURE_THRESHOLD_MB=
# Exit the process after critical resource pressure persists, so a supervisor
# (systemd Restart=always, Docker restart policy) brings back a clean process.
# Accepts 1/true/yes/on. Default: false. Used by: open-sse/utils/resourcePressure.ts.
# OMNIROUTE_PRESSURE_SELF_RESTART=false
# How long (ms) critical pressure must persist before that exit fires. Default: 120000 (2m).
# OMNIROUTE_PRESSURE_SELF_RESTART_AFTER_MS=120000
# ── CLI helpers (bin/cli/) ──
# Override UI language for CLI output. Accepts BCP-47 locale (e.g. en, pt-BR).
# Falls back to LC_ALL / LC_MESSAGES / LANG / en if unset.

View File

@@ -7,7 +7,7 @@
# 🚀 OmniRoute — The Free AI Gateway
<img src="./docs/diagrams/readme-hero.svg" width="100%" alt="OmniRoute — Never stop coding. Every AI tool → 356 providers — 150+ free — through one endpoint. Claude Code, Codex, Cursor, Cline, Copilot & Antigravity into FREE Claude / GPT / Gemini with auto-fallback. RTK + Caveman stacked compression saves 1595% tokens (~89% avg) — never hit limits. 356 AI providers · 150+ free tiers · ~1.47B free tokens/mo · 19 routing strategies · $0 to start."/>
<img src="./docs/diagrams/readme-hero.svg" width="100%" alt="OmniRoute — Never stop coding. Every AI tool → 358 providers — 150+ free — through one endpoint. Claude Code, Codex, Cursor, Cline, Copilot & Antigravity into FREE Claude / GPT / Gemini with auto-fallback. RTK + Caveman stacked compression saves 1595% tokens (~89% avg) — never hit limits. 358 AI providers · 150+ free tiers · ~1.47B free tokens/mo · 19 routing strategies · $0 to start."/>
</div>
@@ -226,7 +226,7 @@ curl http://localhost:20128/v1/chat/completions \
</div>
<img src="./docs/diagrams/promise-pillars.svg" width="100%" alt="The Promise — One endpoint and 356 providers. Automatic fallback keeps routing while another healthy target is available. Six pillars: resilient fallback across 356 providers · up to 95% token savings on eligible workloads · $0 to start with 150+ free tiers and 52 recurring/keyless free-forever providers · 36 CLI/agent integrations through one config · OpenAI, Claude, Gemini and Responses API compatibility at /v1 · production controls including circuit breakers, TLS stealth, MCP 110 tools, A2A, memory, guardrails, evals and 39,000+ static test declarations across 5,100+ tracked test files."/>
<img src="./docs/diagrams/promise-pillars.svg" width="100%" alt="The Promise — One endpoint and 358 providers. Automatic fallback keeps routing while another healthy target is available. Six pillars: resilient fallback across 358 providers · up to 95% token savings on eligible workloads · $0 to start with 150+ free tiers and 52 recurring/keyless free-forever providers · 36 CLI/agent integrations through one config · OpenAI, Claude, Gemini and Responses API compatibility at /v1 · production controls including circuit breakers, TLS stealth, MCP 110 tools, A2A, memory, guardrails, evals and 39,000+ static test declarations across 5,100+ tracked test files."/>
<br/>
<br/>
@@ -479,7 +479,7 @@ All **19** strategies — mix & match per combo step:
</div>
<img src="./docs/diagrams/comparison-table.svg" width="100%" alt="What sets OmniRoute apart — a dated feature snapshot vs 9router, OpenRouter, CLIProxyAPI and LiteLLM across 13 capabilities. OmniRoute: 356 providers, 150+ free tiers built in, 19 routing strategies, 12-engine token compression, built-in MCP server with 110 tools, A2A agent protocol, persistent memory, guardrails, cloud agents, TLS fingerprint stealth, Desktop/Termux/PWA and 42 i18n UI locales. OmniRoute is MIT-licensed and self-hostable. Competitor capabilities and counts may change; see the linked methodology."/>
<img src="./docs/diagrams/comparison-table.svg" width="100%" alt="What sets OmniRoute apart — a dated feature snapshot vs 9router, OpenRouter, CLIProxyAPI and LiteLLM across 13 capabilities. OmniRoute: 358 providers, 150+ free tiers built in, 19 routing strategies, 12-engine token compression, built-in MCP server with 110 tools, A2A agent protocol, persistent memory, guardrails, cloud agents, TLS fingerprint stealth, Desktop/Termux/PWA and 42 i18n UI locales. OmniRoute is MIT-licensed and self-hostable. Competitor capabilities and counts may change; see the linked methodology."/>
<sub>📊 Full methodology &amp; per-feature detail vs 9router, OpenRouter, CLIProxyAPI &amp; LiteLLM → [`docs/comparison/OMNIROUTE_VS_ALTERNATIVES.md`](docs/comparison/OMNIROUTE_VS_ALTERNATIVES.md)</sub>

View File

@@ -0,0 +1 @@
- **fix(ci):** clear the `release/v3.8.51` base-reds on the PR fast path. The provider pipeline keeps the upstream error code and type again, so an Antigravity missing-project 422 stays fail-closed. The glued-prefix `sk-` credential pattern scans error text in linear time instead of quadratic. The provider detail page no longer bundles `node:fs`. `/v1/models` stops listing custom Jina models twice. The `models`/`providers` import cycle is gone, and `opencode-plugin-v2` passes the pack policy. Stale guards, fixtures, locale keys and docs counts are aligned with their merged changes ([#13635](https://github.com/diegosouzapw/OmniRoute/pull/13635))

View File

@@ -3338,11 +3338,6 @@
"count": 17
}
},
"tests/unit/combo-strategies.test.ts": {
"@typescript-eslint/no-unused-vars": {
"count": 1
}
},
"tests/unit/combo-strategy-fallbacks.test.ts": {
"@typescript-eslint/no-explicit-any": {
"count": 33

View File

@@ -68,6 +68,14 @@ export const QWEN_STAINLESS_LANG = "js";
export const QODER_DEFAULT_USER_AGENT = "Qoder-Cli";
// CODEBUDDY_CN_USER_AGENT is the single source of truth for the CLI/CodeBuddy version
// string. It MUST stay identical across OAuth (src/lib/oauth/constants/oauth.ts), chat
// completions (open-sse/config/providers/registry/codebuddy-cn/index.ts) and usage/quota
// (open-sse/services/usage/codebuddy-cn.ts) — a mismatched version string across a
// single account's auth vs. chat calls is exactly the kind of internally-inconsistent
// client fingerprint Tencent's WAF flags as anomalous (#12702).
export const CODEBUDDY_CN_USER_AGENT = "CLI/2.108.1 CodeBuddy/2.108.1";
export const KIRO_SDK_USER_AGENT = "AWS-SDK-JS/3.0.0 kiro-ide/1.0.0";
export const KIRO_AMZ_USER_AGENT = "aws-sdk-js/3.0.0 kiro-ide/1.0.0";
export const KIRO_STREAMING_TARGET =

View File

@@ -1,4 +1,4 @@
import { CODEBUDDY_CN_USER_AGENT } from "@/lib/oauth/constants/oauth";
import { CODEBUDDY_CN_USER_AGENT } from "../../../providerHeaderProfiles.ts";
import type { RegistryEntry } from "../../shared.ts";
/**

View File

@@ -204,6 +204,18 @@ function leaseMismatch(model: string, connectionId: string): ProviderExecutionOu
};
}
interface UpstreamErrorFields {
message?: string;
code?: string;
type?: string;
}
function readUpstreamErrorFields(body: unknown): UpstreamErrorFields {
const err = (body as { error?: Record<string, unknown> } | null)?.error;
const text = (value: unknown) => (typeof value === "string" && value ? value : undefined);
return { message: text(err?.message), code: text(err?.code), type: text(err?.type) };
}
async function toOutcome(
attempt: ChatCoreExecutorResult,
model: string,
@@ -224,22 +236,15 @@ async function toOutcome(
}
let message = attempt.response.statusText || "upstream error";
let body: unknown = attempt.transformedBody;
// #12867 dropped the upstream error code/type when this leg moved into the
// pipeline. Gates that key on both (isAntigravityMissingProjectError) then
// stopped firing, and a config-class 422 degraded into an account cooldown.
let upstreamCode: string | undefined;
let upstreamType: string | undefined;
let fields: UpstreamErrorFields = {};
try {
// clone() is the drain. sendProviderAttempt must not cancel() a streaming
// non-2xx body before we get here (BYOP 422 / Codex 429 Retry-After).
const text = await attempt.response.clone().text();
try {
body = JSON.parse(text);
const err = (body as { error?: { message?: unknown; code?: unknown; type?: unknown } } | null)
?.error;
if (err && typeof err.message === "string" && err.message) message = err.message;
if (err && typeof err.code === "string" && err.code) upstreamCode = err.code;
if (err && typeof err.type === "string" && err.type) upstreamType = err.type;
fields = readUpstreamErrorFields(body);
if (fields.message) message = fields.message;
} catch {
// Non-JSON upstream body (plain-text 429, HTML error page). parseUpstreamError
// — the pre-pipeline path this replaced — surfaces the raw text as the message;
@@ -262,8 +267,8 @@ async function toOutcome(
restatement.status,
message,
restatement.retryAfterMs,
upstreamCode,
upstreamType
fields.code,
fields.type
);
return {
kind: "error",

View File

@@ -14,7 +14,7 @@
* packs, "Bonus Pack N" for bonus packs (soonest-expiring first).
*/
import { CODEBUDDY_CN_USER_AGENT } from "@/lib/oauth/constants/oauth";
import { CODEBUDDY_CN_USER_AGENT } from "../../config/providerHeaderProfiles.ts";
const USAGE_URL = "https://copilot.tencent.com/v2/billing/meter/get-user-resource";
@@ -83,7 +83,7 @@ function cycleEndMs(acc: TencentAccount): number {
function deductionEndMs(acc: TencentAccount): number {
const v = acc.DeductionEndTime;
if (typeof v === "number") return (v < 1e12 ? v * 1000 : v);
if (typeof v === "number") return v < 1e12 ? v * 1000 : v;
if (typeof v === "string" && /^\d+$/.test(v)) {
const n = Number(v);
return n < 1e12 ? n * 1000 : n;

View File

@@ -14,7 +14,7 @@ const STRONG_CREDENTIAL_TOKEN_SOURCE =
"github_pat_[A-Za-z0-9_]{20,}|ghp_[A-Za-z0-9]{20,}|glpat-[A-Za-z0-9_-]{20,}|" +
"xox[a-z]-[A-Za-z0-9-]{10,}|(?:AKIA|ASIA)[A-Z0-9]{16}|" +
"(?<![A-Za-z0-9])sk[-_][A-Za-z0-9._~+/=-]{8,}|" +
"[A-Za-z0-9]{3,}sk[-_][A-Za-z0-9._~+/=-]{8,})";
"(?<![A-Za-z0-9])[A-Za-z0-9]{3,}sk[-_][A-Za-z0-9._~+/=-]{8,})";
const STRONG_CREDENTIAL_TOKEN = new RegExp(STRONG_CREDENTIAL_TOKEN_SOURCE, "i");
const STRONG_CREDENTIAL_TOKEN_GLOBAL = new RegExp(STRONG_CREDENTIAL_TOKEN_SOURCE, "gi");

View File

@@ -7745,6 +7745,10 @@
"legacyJsonImportSuccess": "JSON legado importado com sucesso!",
"jsonImportFailed": "Falha ao importar JSON",
"jsonImportError": "Erro durante a importação de JSON",
"jsonImportAuthRequired": "É necessário autenticar-se para importar uma configuração JSON legada. Entre ou conclua a configuração inicial primeiro.",
"databaseSettingsAuthRequiredTitle": "Autenticação necessária",
"databaseSettingsAuthRequiredBody": "As configurações do banco de dados e a importação de JSON estão disponíveis apenas para um administrador autenticado. Entre ou conclua a configuração inicial para visualizá-las e editá-las.",
"databaseSettingsAuthRequiredCta": "Entrar",
"storagePurgeData": "Limpar dados",
"storagePurgeDataDesc": "Excluir imediatamente todos os registros sem aplicar verificações de retenção. Use com cautela.",
"storageRetentionCleanup": "Configurações de Retenção",

View File

@@ -7745,6 +7745,10 @@
"legacyJsonImportSuccess": "Đã nhập JSON kiểu cũ thành công!",
"jsonImportFailed": "Không thể nhập JSON",
"jsonImportError": "Đã xảy ra lỗi khi nhập JSON",
"jsonImportAuthRequired": "Cần xác thực để nhập cấu hình JSON kiểu cũ. Vui lòng đăng nhập hoặc hoàn tất thiết lập trước.",
"databaseSettingsAuthRequiredTitle": "Cần xác thực",
"databaseSettingsAuthRequiredBody": "Cài đặt cơ sở dữ liệu và tính năng nhập JSON chỉ dành cho quản trị viên đã xác thực. Hãy đăng nhập hoặc hoàn tất thiết lập để xem và chỉnh sửa.",
"databaseSettingsAuthRequiredCta": "Đăng nhập",
"storagePurgeData": "Xóa sạch dữ liệu",
"storagePurgeDataDesc": "Xóa ngay lập tức tất cả các bản ghi mà không áp dụng kiểm tra thời gian lưu trữ. Hãy thận trọng khi sử dụng.",
"storageRetentionCleanup": "Cài đặt thời hạn lưu giữ",
@@ -8675,8 +8679,8 @@
"dragToReorder": "Kéo để sắp xếp lại bước",
"engine": "Bộ máy",
"intensity": "Cường độ",
"activeProfileMasterSwitchOffWarning": "__MISSING__:The active profile below will not run until the master \"Prompt Compression\" switch is turned on.",
"activeProfileMasterSwitchOffCta": "__MISSING__:Turn it on in Settings"
"activeProfileMasterSwitchOffWarning": "Hồ sơ đang dùng bên dưới sẽ không chạy cho đến khi công tắc tổng \"Nén prompt\" được bật.",
"activeProfileMasterSwitchOffCta": "Bật trong Cài đặt"
},
"compressionStudio": {
"noRun": "Chưa có lượt nén nào.",
@@ -8705,7 +8709,7 @@
"run": "Chạy",
"laneRejected": "bị từ chối: {reason}",
"error": "lỗi",
"combinedError": "__MISSING__:Combined pipeline preview failed: {reason}",
"combinedError": "Không thể xem trước luồng kết hợp: {reason}",
"combinedFlow": "Luồng kết hợp",
"eachLayer": "Từng lớp riêng biệt",
"diff": "Khác biệt",

View File

@@ -8121,7 +8121,7 @@
"resilienceCredentialHealthScope": "所有啟用的 API 金鑰與 OAuth 連線",
"resilienceCredentialHealthTrigger": "依固定節奏定期執行",
"resilienceCredentialHealthEffect": "探測每條連線的憑證並標為正常/錯誤;失敗的連線採指數退避",
"resilienceCredentialHealthDesc": "背景掃描:呼叫供應商以驗證每條啟用連線的憑證。設為 0 則完全關閉。各連線編輯對話框裡的健康檢查值一律覆寫此全域預設。",
"resilienceCredentialHealthDesc": "背景掃描:呼叫提供者以驗證每條啟用連線的憑證。設為 0 則完全關閉。各連線編輯對話框裡的健康檢查值一律覆寫此全域預設。",
"resilienceCredentialHealthInterval": "全域檢查間隔",
"resilienceCredentialHealthEveryMinutes": "每 {minutes} 分鐘",
"resilienceCredentialHealthHint": "0 關閉背景掃描(最長 1440 分鐘 = 24 小時)。帶有自身健康檢查值的連線忽略此全域預設;某連線設為 0 時即使全域掃描開啟也會略過它。",
@@ -13017,11 +13017,11 @@
"label": "排序方式",
"method": {
"manual": "手動",
"provider": "供應商",
"provider": "提供者",
"score": "評分(免費模型)",
"name": "名稱"
},
"scoreHint": "依評分排序只對免費供應商生效,其餘維持原位。"
"scoreHint": "依評分排序只對免費提供者生效,其餘維持原位。"
}
},
"comboControl": {

View File

@@ -15,6 +15,7 @@ import {
type SyncedAvailableModelInput,
} from "./models/synced";
import {
deleteSyncedAvailableModelsForProvider,
finishSyncedAvailableModelsWrite,
persistCanonicalSyncedAvailableModels,
} from "./models/syncedAvailableModelPersistence";
@@ -636,22 +637,7 @@ export async function cleanupProviderModelsAfterConnectionDelete(
return { remainingConnections, removedImportedModelIds, remainingSyncedModels };
}
/**
* Delete all synced models for every connection belonging to a provider.
* Returns the number of connection-scoped synced model lists removed.
*/
export async function deleteSyncedAvailableModelsForProvider(providerId: string): Promise<number> {
const db = getDbInstance();
const keyPrefix = `${providerId}:`;
const result = db
.prepare(
"DELETE FROM key_value WHERE namespace = 'syncedAvailableModels' AND substr(key, 1, ?) = ?"
)
.run(keyPrefix.length, keyPrefix);
const changes = Number(result.changes || 0);
if (changes > 0) finishSyncedAvailableModelsWrite();
return changes;
}
export { deleteSyncedAvailableModelsForProvider };
/**
* Prune stale synced available models for a provider, keeping only the specified allowed connection IDs.
@@ -957,8 +943,7 @@ export function getHiddenModelsByProvider(modality: string = "chat"): Map<string
{
isHidden: Boolean(record.isHidden),
hiddenModalities: record.hiddenModalities as
| Record<string, boolean>
| undefined,
Record<string, boolean> | undefined,
},
modality
)

View File

@@ -214,11 +214,12 @@ type ConnectionCatalog = {
async function loadConnectionCatalog(storedProviderId: string): Promise<ConnectionCatalog> {
const [connections, modelsByConnection] = await Promise.all([
getRawProviderConnections({ provider: storedProviderId, isActive: true }, undefined, undefined, [
"id",
"provider",
"synced_models_at",
]),
getRawProviderConnections(
{ provider: storedProviderId, isActive: true },
undefined,
undefined,
["id", "provider", "synced_models_at"]
),
getSyncedAvailableModelsByConnection(storedProviderId),
]);
@@ -322,10 +323,7 @@ export async function getAllActiveSyncedModels(): Promise<Record<string, SyncedA
const models = enrichCursorCatalog(
providerId,
await unionCustomModels(
providerId,
collectModelsForConnections(modelsByConnection, connectionIds)
)
collectModelsForConnections(modelsByConnection, connectionIds)
);
if (models.length > 0) {

View File

@@ -39,6 +39,23 @@ export function finishSyncedAvailableModelsWrite(): void {
invalidateModelCatalogCache();
}
/**
* Delete all synced models for every connection belonging to a provider.
* Returns the number of connection-scoped synced model lists removed.
*/
export async function deleteSyncedAvailableModelsForProvider(providerId: string): Promise<number> {
const db = getDbInstance();
const keyPrefix = `${providerId}:`;
const result = db
.prepare(
"DELETE FROM key_value WHERE namespace = 'syncedAvailableModels' AND substr(key, 1, ?) = ?"
)
.run(keyPrefix.length, keyPrefix);
const changes = Number(result.changes || 0);
if (changes > 0) finishSyncedAvailableModelsWrite();
return changes;
}
export function persistCanonicalSyncedAvailableModels<T>(
key: string,
normalizedModels: T[],

View File

@@ -19,7 +19,7 @@ import {
import { invalidateDbCache } from "../readCache";
import { invalidateReasoningRoutingRuleCache } from "../reasoningRoutingRules";
import { bumpProxyConfigGeneration } from "../settings";
import { deleteSyncedAvailableModelsForProvider } from "../models";
import { deleteSyncedAvailableModelsForProvider } from "../models/syncedAvailableModelPersistence";
import { toRecord } from "./columns";
interface StatementLike<TRow = unknown> {

View File

@@ -27,7 +27,7 @@ process.env.DATA_DIR = TEST_DATA_DIR;
process.env.DISABLE_SQLITE_AUTO_BACKUP = "true";
process.env.VECTOR_STORE_DISABLE_VEC = "true";
const INTERNAL_KEY = "sk-internal-test-key-12745";
const INTERNAL_KEY = "loopback-internal-key";
vi.mock("../settings", () => ({
getMemorySettings: async () => ({

View File

@@ -4,6 +4,7 @@ import {
getAntigravityFetchAvailableModelsUrls,
} from "@omniroute/open-sse/config/antigravityUpstream.ts";
import {
CODEBUDDY_CN_USER_AGENT,
GITHUB_COPILOT_API_VERSION,
GITHUB_COPILOT_CHAT_PLUGIN_VERSION,
GITHUB_COPILOT_CHAT_USER_AGENT,
@@ -106,14 +107,7 @@ export const QODER_CONFIG = {
// CodeBuddy CN (Tencent — copilot.tencent.com) OAuth Configuration
// (Custom Device-Auth Flow: POST stateUrl → open authUrl → GET pollUrl?state=).
// No client_id/secret — the upstream CLI ships none.
//
// CODEBUDDY_CN_USER_AGENT is the single source of truth for the CLI/CodeBuddy version
// string. It MUST stay identical across OAuth (this file), chat completions
// (open-sse/config/providers/registry/codebuddy-cn/index.ts) and usage/quota
// (open-sse/services/usage/codebuddy-cn.ts) — a mismatched version string across a
// single account's auth vs. chat calls is exactly the kind of internally-inconsistent
// client fingerprint Tencent's WAF flags as anomalous (#12702).
export const CODEBUDDY_CN_USER_AGENT = "CLI/2.108.1 CodeBuddy/2.108.1";
export { CODEBUDDY_CN_USER_AGENT };
export const CODEBUDDY_CN_CONFIG = {
baseUrl: "https://copilot.tencent.com",

View File

@@ -442,13 +442,17 @@
"tests/unit/qwen-web-runtime-block.test.ts",
"tests/unit/tunnel-routes-error-sanitization.test.ts",
"tests/unit/auth-grok-cli-402-shared-wallet.test.ts",
"tests/unit/chat-correlation-id-exhaustion.test.ts",
"tests/unit/cline-401-oauth-12594.test.ts",
"tests/unit/cliproxyapi-unknown-provider-400-12800.test.ts",
"tests/unit/combo-predicates-epoch-cooldown.test.ts",
"tests/unit/combo/combo-skipped-targets-summary.test.ts",
"tests/unit/context-handoff-native-passthrough-bug.test.ts",
"tests/unit/guardrails/visionBridge12111Repro.test.ts",
"tests/unit/guardrails/visionBridgeRouter.test.ts",
"tests/unit/issue-11912-opencode-roundrobin-collapse.test.ts"
"tests/unit/issue-11912-opencode-roundrobin-collapse.test.ts",
"tests/unit/opencode-400-model-unavailable.test.ts",
"tests/unit/strong-credential-token-linear-scan.test.ts"
],
"nodeArgs": [
"--import",

View File

@@ -100,14 +100,16 @@ async function main(): Promise<void> {
assert.equal(writerDrained, true, "call-log write must drain");
const persisted = await callLogs.getCallLogById(callLogId);
assert.ok(persisted, "failed attempt must still be available to internal diagnostics");
assert.equal(persisted.error, rawDiagnostic);
assert.equal(persisted.error, "Error: Provider failed in <path> with api_key='[REDACTED]'");
assert.doesNotMatch(persisted.error, /sk-live-dashboard-secret|\/srv\/omniroute|\n/);
console.log(
RESULT_PREFIX +
JSON.stringify({
delivered,
replayMatches: JSON.stringify(replayed.payload) === JSON.stringify(delivered),
internalRawPreserved: persisted.error === rawDiagnostic,
internalLogRedacted:
persisted.error === delivered.error && !persisted.error.includes("sk-live"),
writerDrained,
})
);

View File

@@ -428,6 +428,29 @@
"stream": "https://api.airforce/v1/chat/completions"
}
},
"arcee-ai": {
"format": "openai",
"headers": {
"apiKey": {
"Accept": "text/event-stream",
"Authorization": "Bearer <TOK>",
"Content-Type": "application/json"
},
"nonStream": {
"Authorization": "Bearer <TOK>",
"Content-Type": "application/json"
},
"oauth": {
"Accept": "text/event-stream",
"Authorization": "Bearer <TOK>",
"Content-Type": "application/json"
}
},
"url": {
"nonStream": "https://api.arcee.ai/api/v1/chat/completions",
"stream": "https://api.arcee.ai/api/v1/chat/completions"
}
},
"auggie": {
"format": "openai",
"headers": {

View File

@@ -7,9 +7,6 @@ const source = readFileSync(
"utf8"
);
// #12867 split the send: chatCore keeps the per-attempt admission loop and the
// account/model recovery loop moved to providerExecutionPipeline.ts, which
// re-enters chatCore through sendProviderAttempt on every rotation.
const pipeline = readFileSync(
new URL("../../open-sse/handlers/chatCore/providerExecutionPipeline.ts", import.meta.url),
"utf8"
@@ -38,13 +35,14 @@ test("chatCore acquires cumulative gates immediately before withRateLimit", () =
// single index check covered it; the loop is now split across two files, so the
// guard checks both halves of the same invariant.
test("each rotated account attempt acquires and releases a fresh composite slot", () => {
// ── chatCore half: one acquisition per attempt, released on every exit ──
const attemptLoop = source.indexOf("while (attempts < maxAttempts)");
const sendFn = source.indexOf("const executeProviderRequest = async (");
const attemptLoop = source.indexOf("while (attempts < maxAttempts)", sendFn);
const acquire = source.indexOf("await acquireConcurrencyGates(", attemptLoop);
const release = source.indexOf("releaseAccountSemaphore();", acquire);
const retryContinue = source.indexOf("continue;", acquire);
assert.ok(attemptLoop >= 0, "chatCore must keep the per-attempt admission loop");
assert.ok(sendFn >= 0, "chatCore must keep the single wire-send function");
assert.ok(attemptLoop > sendFn, "the per-attempt admission loop lives in the wire send");
assert.ok(acquire > attemptLoop, "the composite slot is acquired inside the attempt loop");
assert.ok(release > acquire, "each attempt must release the composite slot");
assert.ok(retryContinue > release, "an in-loop retry releases the slot before continuing");
@@ -54,7 +52,12 @@ test("each rotated account attempt acquires and releases a fresh composite slot"
"a throwing attempt must release the composite slot"
);
// ── pipeline half: rotation re-enters the acquisition, never sends in place ──
const sendWirings =
source.match(
/sendProviderAttempt: \(modelToCall, allowDedup\) =>\s*executeProviderRequest\(modelToCall, allowDedup\)/g
) ?? [];
assert.equal(sendWirings.length, 2, "both legs send every pipeline attempt through the gate");
const rotationLoop = pipeline.search(/while \(\s*attempts < maxAttempts\b/);
assert.ok(rotationLoop >= 0, "the account/model recovery loop must exist");
assert.ok(
@@ -68,8 +71,8 @@ test("each rotated account attempt acquires and releases a fresh composite slot"
);
assert.match(
pipeline.slice(rotationLoop),
/(?:antigravityByopRotationPending|authRefreshPending|modelFallbackPending)\s*=\s*true;\s*continue;/,
"a rotation hands control back to the loop head instead of re-sending in place"
/antigravityByopRotationPending = true;\s*continue;/,
"a BYOP rotation hands control back to the loop head instead of re-sending in place"
);
assert.match(
pipeline.slice(rotationLoop),

View File

@@ -128,34 +128,32 @@ test("source guard: auth.ts skips model lockout for per-model-quota providers on
);
});
test("source guard: combo.ts skips provider cooldown for per-model-quota on 500", () => {
// The combo dispatcher was split out of combo.ts into open-sse/services/combo/*
// (#12746 executeTarget → gates/attempt/loop, #12811 round-robin). The invariant
// did not move: EVERY call site that records a provider cooldown after a failed
// combo target must first exclude a 500 on a per-model-quota provider, or one
// model's outage cools down its siblings. Scan the whole combo surface so the
// guard follows the code instead of one file name.
const comboDir = path.join(process.cwd(), "open-sse", "services", "combo");
const comboFiles = [
path.join(process.cwd(), "open-sse", "services", "combo.ts"),
...fs
.readdirSync(comboDir, { withFileTypes: true })
.filter((entry) => entry.isFile() && entry.name.endsWith(".ts"))
.map((entry) => path.join(comboDir, entry.name)),
].filter((file) => fs.existsSync(file));
function comboSourceFiles(): string[] {
const servicesDir = path.join(process.cwd(), "open-sse", "services");
const comboDir = path.join(servicesDir, "combo");
const nested = fs
.readdirSync(comboDir, { recursive: true, encoding: "utf-8" })
.filter((entry) => entry.endsWith(".ts"))
.map((entry) => path.join(comboDir, entry));
return [path.join(servicesDir, "combo.ts"), ...nested];
}
const recordingFiles = comboFiles.filter((file) =>
fs.readFileSync(file, "utf-8").includes("recordProviderCooldown(")
);
assert.ok(
recordingFiles.length > 0,
"no combo module records a provider cooldown — the guarded call site vanished"
);
for (const file of recordingFiles) {
const normalized = fs.readFileSync(file, "utf-8").replace(/\s+/g, " ");
assert.ok(
/result\.status === 500[^;]{0,160}?hasPerModelQuota\(provider,/.test(normalized),
`${path.basename(file)} must skip provider cooldown recording for per-model-quota providers on 500`
);
test("source guard: combo.ts skips provider cooldown for per-model-quota on 500", () => {
const guardedCalls: string[] = [];
for (const file of comboSourceFiles()) {
const src = fs.readFileSync(file, "utf-8");
const rel = path.relative(process.cwd(), file);
let at = src.indexOf("recordProviderCooldown(");
while (at >= 0) {
const condition = src.slice(src.lastIndexOf("if (", at), at);
assert.match(
condition,
/!\s*\(\s*\(result\.status === 500[^)]*\)\s*&&\s*hasPerModelQuota\(provider,/,
`${rel} must skip provider cooldown recording on 500 for per-model-quota providers`
);
guardedCalls.push(rel);
at = src.indexOf("recordProviderCooldown(", at + 1);
}
}
assert.ok(guardedCalls.length > 0, "combo routing must still record provider cooldowns");
});

View File

@@ -21,7 +21,6 @@ const { getQuotaScopedModelForProvider } =
await import("../../open-sse/services/antigravityQuotaFamily.ts");
const combosDb = await import("../../src/lib/db/combos.ts");
const providersDb = await import("../../src/lib/db/providers.ts");
const { recordComboRequest } = await import("../../open-sse/services/comboMetrics.ts");
const { saveModelsDevCapabilities } = await import("../../src/lib/modelsDevSync.ts");
after(() => {
@@ -144,6 +143,23 @@ function installCodexQuotaMock(quotasByToken: Record<string, unknown>) {
};
}
async function createQuotaConnection(provider: string, label: string, accessToken?: string) {
const connection = await providersDb.createProviderConnection({
provider,
authType: accessToken ? "oauth" : "apikey",
name: `${label}-${randomUUID()}`,
accessToken,
isActive: true,
testStatus: "active",
});
return String(connection.id);
}
async function codexConnection(label: string) {
const token = `token-${label}-${randomUUID()}`;
return { id: await createQuotaConnection("codex", label, token), token };
}
function resetAwareCombo(
name: string,
connections: Array<{ id: string; token: string }>,
@@ -265,8 +281,8 @@ test("auto strategy handles null and empty prompt edge cases without throwing",
});
test("reset-aware strategy prefers lower weekly remaining quota when reset is much sooner", async (t) => {
const soon = { id: `soon-${randomUUID()}`, token: `token-soon-${randomUUID()}` };
const later = { id: `later-${randomUUID()}`, token: `token-later-${randomUUID()}` };
const soon = await codexConnection("soon");
const later = await codexConnection("later");
t.after(
installCodexQuotaMock({
[soon.token]: codexQuota({
@@ -290,13 +306,10 @@ test("reset-aware strategy prefers lower weekly remaining quota when reset is mu
});
test("reset-aware strategy aggressively spends quota that resets soon", async (t) => {
const team = { id: `team-${randomUUID()}`, token: `token-team-${randomUUID()}` };
const fullLater = { id: `full-${randomUUID()}`, token: `token-full-${randomUUID()}` };
const soonLow = { id: `soon-low-${randomUUID()}`, token: `token-soon-low-${randomUUID()}` };
const soonLower = {
id: `soon-lower-${randomUUID()}`,
token: `token-soon-lower-${randomUUID()}`,
};
const team = await codexConnection("team");
const fullLater = await codexConnection("full");
const soonLow = await codexConnection("soon-low");
const soonLower = await codexConnection("soon-lower");
t.after(
installCodexQuotaMock({
[team.token]: codexQuota({
@@ -338,14 +351,8 @@ test("reset-aware strategy aggressively spends quota that resets soon", async (t
});
test("reset-aware strategy prioritizes soon-reset weekly quota over empty later accounts", async (t) => {
const fullerSoon = {
id: `fuller-soon-${randomUUID()}`,
token: `token-fuller-soon-${randomUUID()}`,
};
const emptyLater = {
id: `empty-later-${randomUUID()}`,
token: `token-empty-later-${randomUUID()}`,
};
const fullerSoon = await codexConnection("fuller-soon");
const emptyLater = await codexConnection("empty-later");
t.after(
installCodexQuotaMock({
[fullerSoon.token]: codexQuota({
@@ -372,14 +379,8 @@ test("reset-aware strategy prioritizes soon-reset weekly quota over empty later
});
test("reset-aware strategy keeps 5h reset pressure softer than weekly pressure", async (t) => {
const fullerSoon = {
id: `session-fuller-soon-${randomUUID()}`,
token: `token-session-fuller-soon-${randomUUID()}`,
};
const emptyLater = {
id: `session-empty-later-${randomUUID()}`,
token: `token-session-empty-later-${randomUUID()}`,
};
const fullerSoon = await codexConnection("session-fuller-soon");
const emptyLater = await codexConnection("session-empty-later");
t.after(
installCodexQuotaMock({
[fullerSoon.token]: codexQuota({
@@ -406,14 +407,8 @@ test("reset-aware strategy keeps 5h reset pressure softer than weekly pressure",
});
test("reset-aware strategy avoids accounts near 5h exhaustion", async (t) => {
const exhausted5h = {
id: `exhausted-${randomUUID()}`,
token: `token-exhausted-${randomUUID()}`,
};
const healthy5h = {
id: `healthy-${randomUUID()}`,
token: `token-healthy-${randomUUID()}`,
};
const exhausted5h = await codexConnection("exhausted");
const healthy5h = await codexConnection("healthy");
t.after(
installCodexQuotaMock({
[exhausted5h.token]: codexQuota({
@@ -446,8 +441,8 @@ test("Antigravity aliases share one family-scoped cache key", () => {
test("reset-aware strategy rotates similar scores with round-robin tie breaking", async () => {
const provider = `tie-provider-${randomUUID()}`;
const first = `first-${randomUUID()}`;
const second = `second-${randomUUID()}`;
const first = await createQuotaConnection(provider, "first");
const second = await createQuotaConnection(provider, "second");
const quota = {
used: 50,
total: 100,
@@ -483,8 +478,8 @@ test("reset-aware strategy rotates similar scores with round-robin tie breaking"
test("reset-aware strategy uses registered quota fetchers for non-Codex providers", async () => {
const provider = `quota-provider-${randomUUID()}`;
const soon = `soon-${randomUUID()}`;
const later = `later-${randomUUID()}`;
const soon = await createQuotaConnection(provider, "soon");
const later = await createQuotaConnection(provider, "later");
const resetAtSoon = new Date(Date.now() + 24 * 3600 * 1000).toISOString();
const resetAtLater = new Date(Date.now() + 5 * 24 * 3600 * 1000).toISOString();
@@ -516,7 +511,7 @@ test("reset-aware strategy uses registered quota fetchers for non-Codex provider
test("reset-aware strategy deduplicates quota fetches for repeated connection targets", async () => {
const provider = `dedupe-provider-${randomUUID()}`;
const connectionId = `shared-${randomUUID()}`;
const connectionId = await createQuotaConnection(provider, "shared");
let fetchCount = 0;
registerQuotaFetcher(provider, async (id) => {
@@ -549,8 +544,8 @@ test("reset-aware strategy deduplicates quota fetches for repeated connection ta
test("reset-aware quota SWR serves stale ordering while refreshing in background", async () => {
const provider = `swr-provider-${randomUUID()}`;
const cachedFirst = `cached-first-${randomUUID()}`;
const cachedSecond = `cached-second-${randomUUID()}`;
const cachedFirst = await createQuotaConnection(provider, "cached-first");
const cachedSecond = await createQuotaConnection(provider, "cached-second");
const fetchCounts = new Map<string, number>();
registerQuotaFetcher(provider, async (connectionId) => {
@@ -649,8 +644,8 @@ test("reset-aware strategy respects API-key allowed connections during expansion
test("reset-aware strategy parses numeric reset timestamps from quota telemetry", async () => {
const provider = `timestamp-provider-${randomUUID()}`;
const soon = `timestamp-soon-${randomUUID()}`;
const later = `timestamp-later-${randomUUID()}`;
const soon = await createQuotaConnection(provider, "timestamp-soon");
const later = await createQuotaConnection(provider, "timestamp-later");
const soonResetSeconds = Math.floor((Date.now() + 24 * 3600 * 1000) / 1000);
const laterResetMs = Date.now() + 5 * 24 * 3600 * 1000;
@@ -679,8 +674,8 @@ test("reset-aware strategy parses numeric reset timestamps from quota telemetry"
test("reset-aware strategy scores provider-specific weekly windows when available", async () => {
const provider = `weekly-provider-${randomUUID()}`;
const soon = `weekly-soon-${randomUUID()}`;
const later = `weekly-later-${randomUUID()}`;
const soon = await createQuotaConnection(provider, "weekly-soon");
const later = await createQuotaConnection(provider, "weekly-later");
const resetAtSoon = new Date(Date.now() + 24 * 3600 * 1000).toISOString();
const resetAtLater = new Date(Date.now() + 5 * 24 * 3600 * 1000).toISOString();

View File

@@ -17,7 +17,7 @@ const probePath = fileURLToPath(
type ProbeResult = {
delivered: RequestFailedPayload;
replayMatches: boolean;
internalRawPreserved: boolean;
internalLogRedacted: boolean;
writerDrained: boolean;
};
@@ -89,7 +89,7 @@ test("persistAttemptLogs redacts request.failed delivery/replay but keeps its in
"Error: Provider failed in <path> with api_key='[REDACTED]'"
);
assert.equal(result.replayMatches, true);
assert.equal(result.internalRawPreserved, true);
assert.equal(result.internalLogRedacted, true);
assert.equal(result.writerDrained, true);
} finally {
// The probe exits only after draining/closing its writer and resetting its DB singleton.

View File

@@ -398,10 +398,23 @@ test("chatCore provider-failure writes use the projected persistent message", ()
const failureEnd = source.indexOf("// Non-streaming response", failureStart);
assert.ok(failureStart >= 0 && failureEnd > failureStart, "providerFailure block must exist");
const failureBlock = source.slice(failureStart, failureEnd);
const classifierStart = source.indexOf("const applyProviderFailureClassification = async");
const classifierEnd = source.indexOf("\n };\n", classifierStart);
assert.ok(
classifierStart >= 0 && classifierEnd > classifierStart,
"applyProviderFailureClassification block must exist"
);
const classifierBlock = source.slice(classifierStart, classifierEnd);
assert.doesNotMatch(failureBlock, /lastError:\s*message\b/);
assert.match(failureBlock, /await applyProviderFailureClassification\(/);
assert.match(
classifierBlock,
/const persistentMessage = sanitizeErrorMessage\(message\) \|\| "Provider request failed"/
);
assert.doesNotMatch(classifierBlock, /lastError:\s*message\b/);
assert.ok(
(failureBlock.match(/lastError:\s*persistentMessage\b/g) || []).length >= 11,
(classifierBlock.match(/lastError:\s*persistentMessage\b/g) || []).length >= 11,
"every providerFailure persistence branch must use persistentMessage"
);
});

View File

@@ -5,16 +5,13 @@ import { fileURLToPath } from "node:url";
import { dirname, join } from "node:path";
/**
* GLM's translateSseResponse passed a 16th positional to
* createSSETransformStreamWithLogger from #12179 until #12925, while the helper
* still declared 15 parameters — tsc reported TS2554 and the number never
* reached TransformStream. #12925 closed the seam by declaring the slot as
* `streamBufferBytes`.
* GLM's translateSseResponse used to pass a 16th positional (65536) to
* createSSETransformStreamWithLogger while the helper only had 15 parameters,
* so tsc reported TS2554 and the number never reached TransformStream.
* #12925 gave the helper a trailing streamBufferBytes parameter.
*
* The invariant this guards has not changed: the buffer size GLM passes must
* land in a real parameter, never in a dropped extra positional. It is now
* checked from the other side — the helper must declare the slot last, and the
* call site must fill it with the named constant rather than a magic literal.
* Guard the call site in source: its arity matches the helper, and the
* buffer budget lands in streamBufferBytes through GLM_STREAM_BUFFER_BYTES.
*/
const root = join(dirname(fileURLToPath(import.meta.url)), "..", "..");
@@ -53,13 +50,37 @@ test("GLM translateSseResponse fills the buffer-size slot with the named constan
const callAt = body.indexOf("createSSETransformStreamWithLogger(");
assert.ok(callAt >= 0);
const call = extractParens(body, callAt + "createSSETransformStreamWithLogger".length);
// A magic literal here is what made the original mismatch invisible; the call
// must reference the shared constant so a change to it cannot drift silently.
assert.equal(/65536/.test(call), false, `magic buffer literal is back:\n${call}`);
assert.match(
call,
/GLM_STREAM_BUFFER_BYTES\s*\)\s*$/,
`buffer size must be the last arg:\n${call}`
);
assert.match(call, /suppressThinkClose/, `suppressThinkClose must still be passed:\n${call}`);
assert.equal(/65536/.test(call), false, `inline buffer literal present:\n${call}`);
const helperSrc = readFileSync(join(root, "open-sse", "utils", "stream.ts"), "utf8");
const needle = "export function createSSETransformStreamWithLogger(";
const header = extractParens(helperSrc, helperSrc.indexOf(needle) + needle.length - 1);
const params = splitTopLevel(header).map((param) => param.split(/[:=]/)[0].trim());
const args = splitTopLevel(call);
assert.equal(args.length, params.length, `GLM must match the helper arity:\n${call}`);
assert.equal(params.at(-1), "streamBufferBytes");
assert.equal(args.at(-1), "GLM_STREAM_BUFFER_BYTES");
assert.equal(args[params.indexOf("suppressThinkClose")], "suppressThinkClose");
assert.match(src, /const GLM_STREAM_BUFFER_BYTES = 65536;/);
});
function splitTopLevel(parenthesized: string): string[] {
const inner = parenthesized.slice(1, -1);
const parts: string[] = [];
let depth = 0;
let current = "";
for (const ch of inner) {
const isArrow = ch === ">" && current.endsWith("=");
if ("(<{[".includes(ch)) depth += 1;
else if (")>}]".includes(ch) && !isArrow) depth -= 1;
if (ch === "," && depth === 0) {
parts.push(current.trim());
current = "";
continue;
}
current += ch;
}
if (current.trim()) parts.push(current.trim());
return parts;
}

View File

@@ -18,6 +18,9 @@ const { mergeProviderLimitsCacheEntry } =
await import("../../src/lib/usage/providerLimitsCache.ts");
const originalFetch = globalThis.fetch;
const RESET_TOKEN_GRANTED = 1786560540;
const RESET_TOKEN_EXPIRES = 1789238940;
const FIXTURE_NOW_MS = Date.UTC(2026, 8, 6);
interface FetchCall {
url: string;
@@ -74,8 +77,8 @@ function encodeVarintField(fieldNumber: number, value: number): Buffer {
function oneResetTokenResponse(): Response {
const token = Buffer.concat([
encodeLengthDelimited(1, Buffer.from("test-token-id", "utf8")),
encodeVarintField(2, 1786560540),
encodeVarintField(3, 1789238940),
encodeVarintField(2, RESET_TOKEN_GRANTED),
encodeVarintField(3, RESET_TOKEN_EXPIRES),
]);
const payload = encodeLengthDelimited(10, token);
const trailer = Buffer.from("grpc-status:0\r\n", "utf8");
@@ -90,8 +93,8 @@ function liveResetTokenResponse(): Response {
const timestamp = (unixSeconds: number) => encodeVarintField(1, unixSeconds);
const token = Buffer.concat([
encodeLengthDelimited(10, Buffer.from("test-token-id", "utf8")),
encodeLengthDelimited(20, timestamp(1786560540)),
encodeLengthDelimited(30, timestamp(1789238940)),
encodeLengthDelimited(20, timestamp(RESET_TOKEN_GRANTED)),
encodeLengthDelimited(30, timestamp(RESET_TOKEN_EXPIRES)),
]);
const payload = encodeLengthDelimited(10, token);
const trailer = Buffer.from("grpc-status:0\r\n", "utf8");
@@ -642,7 +645,8 @@ test("SuperGrokPro explicit null creditUsagePercent still yields a weekly quota
});
});
test("grok-cli surfaces bankedResetCredits when GetRemainingResets returns one token", async () => {
test("grok-cli surfaces bankedResetCredits when GetRemainingResets returns one token", async (t) => {
t.mock.timers.enable({ apis: ["Date"], now: FIXTURE_NOW_MS });
const fixtureFetch = successFixtures();
const usage = await getUsage((async (input: string | URL | Request) => {
const url = String(input);
@@ -653,7 +657,8 @@ test("grok-cli surfaces bankedResetCredits when GetRemainingResets returns one t
assert.ok(usage.quotas?.weekly);
});
test("grok-cli surfaces bankedResetCredits for live nested 10/20/30 tokens", async () => {
test("grok-cli surfaces bankedResetCredits for live nested 10/20/30 tokens", async (t) => {
t.mock.timers.enable({ apis: ["Date"], now: FIXTURE_NOW_MS });
const fixtureFetch = successFixtures();
const usage = await getUsage((async (input: string | URL | Request) => {
const url = String(input);

View File

@@ -19,6 +19,7 @@ const LIST_URL = "https://grok.com/prod_mc_billing.ConsumerUiSvc/GetRemainingRes
const REDEEM_URL = "https://grok.com/prod_mc_billing.ConsumerUiSvc/RedeemReset";
const GRANTED = 1786560540;
const EXPIRES = 1789238940;
const FIXTURE_NOW_MS = Date.UTC(2026, 8, 6);
const TOKEN_ID = "test-token-id";
function encodeVarint(value: number): Buffer {
@@ -122,7 +123,8 @@ test.after(async () => {
fs.rmSync(TEST_DATA_DIR, { recursive: true, force: true, maxRetries: 5, retryDelay: 100 });
});
test("listGrokResetCredits returns public rows without logging token ids in usage", async () => {
test("listGrokResetCredits returns public rows without logging token ids in usage", async (t) => {
t.mock.timers.enable({ apis: ["Date"], now: FIXTURE_NOW_MS });
const connection = (await createGrokConnection()) as { id: string };
globalThis.fetch = async (url) => {
if (String(url) === LIST_URL) return listResponse([{ id: TOKEN_ID, expires: EXPIRES }]);

View File

@@ -7,6 +7,7 @@ import {
const GRANTED = 1786560540;
const EXPIRES = 1789238940;
const FIXTURE_NOW_MS = Date.UTC(2026, 8, 6);
const TOKEN_ID = "test-token-id"; // 13 bytes
function encodeVarint(value: number): Buffer {
@@ -59,6 +60,10 @@ function encodeLiveToken(id: string, granted: number, expires: number): Buffer {
]);
}
function decode(buffer: Buffer) {
return decodeGrokResetCreditsFrame(buffer, FIXTURE_NOW_MS);
}
function frameData(payload: Buffer): Buffer {
const header = Buffer.alloc(5);
header[0] = 0x00;
@@ -76,7 +81,7 @@ function frameTrailer(statusText = "grpc-status:0\r\n"): Buffer {
test("empty DATA frame + grpc-status 0 is a real zero inventory", () => {
const buffer = Buffer.concat([frameData(Buffer.alloc(0)), frameTrailer()]);
const decoded = decodeGrokResetCreditsFrame(buffer);
const decoded = decode(buffer);
assert.equal(decoded.ok, true);
if (!decoded.ok) return;
assert.equal(decoded.snapshot.count, 0);
@@ -85,7 +90,7 @@ test("empty DATA frame + grpc-status 0 is a real zero inventory", () => {
test("one unexpired field-10 token counts as 1", () => {
const payload = encodeLengthDelimited(10, encodeToken(TOKEN_ID, GRANTED, EXPIRES));
const decoded = decodeGrokResetCreditsFrame(Buffer.concat([frameData(payload), frameTrailer()]));
const decoded = decode(Buffer.concat([frameData(payload), frameTrailer()]));
assert.equal(decoded.ok, true);
if (!decoded.ok) return;
assert.equal(decoded.snapshot.count, 1);
@@ -98,9 +103,7 @@ test("one unexpired field-10 token counts as 1", () => {
test("repeated field-10 is not collapsed by a Map walker", () => {
const a = encodeLengthDelimited(10, encodeToken("test-token-aa", GRANTED, EXPIRES));
const b = encodeLengthDelimited(10, encodeToken("test-token-bb", GRANTED, EXPIRES + 86400));
const decoded = decodeGrokResetCreditsFrame(
Buffer.concat([frameData(Buffer.concat([a, b])), frameTrailer()])
);
const decoded = decode(Buffer.concat([frameData(Buffer.concat([a, b])), frameTrailer()]));
assert.equal(decoded.ok, true);
if (!decoded.ok) return;
assert.equal(decoded.snapshot.count, 2);
@@ -114,7 +117,7 @@ test("repeated field-10 is not collapsed by a Map walker", () => {
test("expired tokens are dropped from the count", () => {
const expired = encodeLengthDelimited(10, encodeToken("test-token-ex", GRANTED, 1_700_000_000));
const live = encodeLengthDelimited(10, encodeToken(TOKEN_ID, GRANTED, EXPIRES));
const decoded = decodeGrokResetCreditsFrame(
const decoded = decode(
Buffer.concat([frameData(Buffer.concat([expired, live])), frameTrailer()])
);
assert.equal(decoded.ok, true);
@@ -124,7 +127,7 @@ test("expired tokens are dropped from the count", () => {
});
test("nonzero grpc-status is not a zero inventory", () => {
const decoded = decodeGrokResetCreditsFrame(
const decoded = decode(
Buffer.concat([frameData(Buffer.alloc(0)), frameTrailer("grpc-status:13\r\n")])
);
assert.equal(decoded.ok, false);
@@ -133,14 +136,14 @@ test("nonzero grpc-status is not a zero inventory", () => {
});
test("trailer-only buffer is not a zero inventory", () => {
const decoded = decodeGrokResetCreditsFrame(frameTrailer());
const decoded = decode(frameTrailer());
assert.equal(decoded.ok, false);
if (decoded.ok) return;
assert.equal(decoded.reason, "no-data-frame");
});
test("empty buffer is not a zero inventory", () => {
const decoded = decodeGrokResetCreditsFrame(Buffer.alloc(0));
const decoded = decode(Buffer.alloc(0));
assert.equal(decoded.ok, false);
if (decoded.ok) return;
assert.equal(decoded.reason, "empty-buffer");
@@ -148,7 +151,7 @@ test("empty buffer is not a zero inventory", () => {
test("13-byte token id is a string, not a nested protobuf message", () => {
const payload = encodeLengthDelimited(10, encodeToken(TOKEN_ID, GRANTED, EXPIRES));
const decoded = decodeGrokResetCreditsFrame(Buffer.concat([frameData(payload), frameTrailer()]));
const decoded = decode(Buffer.concat([frameData(payload), frameTrailer()]));
assert.equal(decoded.ok, true);
if (!decoded.ok) return;
assert.equal(decoded.snapshot.count, 1);
@@ -161,7 +164,7 @@ test("live nested fields 10/20/30 are not malformed", () => {
assert.equal(encodeTimestampSeconds(GRANTED).length, 6);
assert.equal(encodeTimestampSeconds(EXPIRES).length, 6);
const payload = encodeLengthDelimited(10, liveInner);
const decoded = decodeGrokResetCreditsFrame(Buffer.concat([frameData(payload), frameTrailer()]));
const decoded = decode(Buffer.concat([frameData(payload), frameTrailer()]));
assert.equal(decoded.ok, true);
if (!decoded.ok) return;
assert.equal(decoded.snapshot.count, 1);
@@ -170,9 +173,12 @@ test("live nested fields 10/20/30 are not malformed", () => {
});
test("live nested field-30 expiry still drops expired cards", () => {
const expired = encodeLengthDelimited(10, encodeLiveToken("test-token-ex", GRANTED, 1_700_000_000));
const expired = encodeLengthDelimited(
10,
encodeLiveToken("test-token-ex", GRANTED, 1_700_000_000)
);
const live = encodeLengthDelimited(10, encodeLiveToken(TOKEN_ID, GRANTED, EXPIRES));
const decoded = decodeGrokResetCreditsFrame(
const decoded = decode(
Buffer.concat([frameData(Buffer.concat([expired, live])), frameTrailer()])
);
assert.equal(decoded.ok, true);

View File

@@ -9,6 +9,7 @@ import { encodeRedeemResetRequest } from "../../open-sse/services/grokResetCredi
const GRANTED = 1786560540;
const EXPIRES = 1789238940;
const FIXTURE_NOW_MS = Date.UTC(2026, 8, 6);
const TOKEN_ID = "test-token-id";
const REDEEM_URL = "https://grok.com/prod_mc_billing.ConsumerUiSvc/RedeemReset";
const LIST_URL = "https://grok.com/prod_mc_billing.ConsumerUiSvc/GetRemainingResets";
@@ -93,7 +94,8 @@ test("mapGrokRedeemGrpcStatus treats invalid token_id as noCredit", () => {
assert.equal(mapGrokRedeemGrpcStatus("3", "redeem_reset(), Invalid token_id"), "noCredit");
});
test("listGrokResetCreditTokens returns public rows ordered by expiry", async () => {
test("listGrokResetCreditTokens returns public rows ordered by expiry", async (t) => {
t.mock.timers.enable({ apis: ["Date"], now: FIXTURE_NOW_MS });
const listed = await listGrokResetCreditTokens("fixture-access-token", async (url) => {
assert.equal(String(url), LIST_URL);
return listResponse([
@@ -135,19 +137,24 @@ test("consumeGrokResetCredit posts RedeemReset with protobuf field 10 and skips
assert.equal(headers.Authorization, ["Bearer", "fixture-access-token"].join(" "));
});
test("consumeGrokResetCredit picks the token that expires first when none is selected", async () => {
test("consumeGrokResetCredit picks the token that expires first when none is selected", async (t) => {
t.mock.timers.enable({ apis: ["Date"], now: FIXTURE_NOW_MS });
const calls: Array<{ url: string; body: Buffer | null }> = [];
const outcome = await consumeGrokResetCredit("fixture-access-token", {}, async (url, init = {}) => {
const body = init.body ? Buffer.from(init.body as Buffer) : null;
calls.push({ url: String(url), body });
if (String(url) === LIST_URL) {
return listResponse([
{ id: "test-token-bb", expires: EXPIRES + 86400 },
{ id: "test-token-aa", expires: EXPIRES },
]);
const outcome = await consumeGrokResetCredit(
"fixture-access-token",
{},
async (url, init = {}) => {
const body = init.body ? Buffer.from(init.body as Buffer) : null;
calls.push({ url: String(url), body });
if (String(url) === LIST_URL) {
return listResponse([
{ id: "test-token-bb", expires: EXPIRES + 86400 },
{ id: "test-token-aa", expires: EXPIRES },
]);
}
return trailerResponse(0);
}
return trailerResponse(0);
});
);
assert.equal(outcome, "reset");
const redeem = calls.find((call) => call.url === REDEEM_URL);
assert.ok(redeem?.body);
@@ -159,17 +166,10 @@ test("consumeGrokResetCredit maps a missing selected token via RedeemReset grpc-
const { GrokResetCreditError } = await import("../../open-sse/services/grokResetCredits.ts");
await assert.rejects(
() =>
consumeGrokResetCredit(
"fixture-access-token",
{ tokenId: "missing-token" },
async (url) => {
if (String(url) === LIST_URL) return listResponse([{ id: TOKEN_ID, expires: EXPIRES }]);
return trailerResponse(
9,
"The token cannot be redeemed: it does not exist or is expired"
);
}
),
consumeGrokResetCredit("fixture-access-token", { tokenId: "missing-token" }, async (url) => {
if (String(url) === LIST_URL) return listResponse([{ id: TOKEN_ID, expires: EXPIRES }]);
return trailerResponse(9, "The token cannot be redeemed: it does not exist or is expired");
}),
(error: unknown) =>
error instanceof GrokResetCreditError && error.status === 409 && error.code === "no_credit"
);

View File

@@ -37,8 +37,9 @@ const EXPECTED: Record<InventoryKind, Record<string, number>> = {
"src/app/api/v1/classify/route.ts": 1,
// v3.8.51 #11754: the second resolveImageRouteModel() call (a duplicate
// of the retirement-check one hoisted before enforceApiKeyPolicy) was
// removed as dead redundant code, 6->5.
"src/app/api/v1/images/edits/route.ts": 5,
// removed as dead redundant code, 6->5. #12653 added combo target
// resolution with the same shape as imageCombo, 5->6.
"src/app/api/v1/images/edits/route.ts": 6,
"src/app/api/v1/images/generations/route.ts": 3,
"src/app/api/v1/images/upscale/route.ts": 1,
"src/app/api/v1/messages/count_tokens/route.ts": 1,
@@ -86,7 +87,7 @@ const EXPECTED: Record<InventoryKind, Record<string, number>> = {
},
connection: {
"open-sse/handlers/autoComboCandidates.ts": 1,
"open-sse/handlers/chatCore.ts": 2,
"open-sse/handlers/chatCore.ts": 3,
"open-sse/handlers/cursorCliProxy.ts": 1,
"open-sse/services/alibabaFreeTier.ts": 1,
"open-sse/services/alibabaFreeTierQuotaFetcher.ts": 1,
@@ -161,7 +162,7 @@ const EXPECTED: Record<InventoryKind, Record<string, number>> = {
"src/lib/db/providers.ts": 3,
"src/lib/db/readCache.ts": 2,
"src/lib/freeProviderRankings.ts": 1,
"src/lib/guardrails/visionBridgeCredentials.ts": 1,
"src/lib/guardrails/visionBridgeCredentials.ts": 2,
"src/lib/kimi/tokenRefresh.ts": 1,
"src/lib/monitoring/providerHealthAutopilot.ts": 1,
"src/lib/monitoring/providerHealthMatrix.ts": 1,

View File

@@ -1,6 +1,6 @@
import test from "node:test";
import assert from "node:assert/strict";
import { readFileSync } from "node:fs";
import { existsSync, readdirSync, readFileSync } from "node:fs";
import {
APP_STAGING_ALLOWED_EXACT_PATHS,
@@ -319,3 +319,18 @@ test("findMissingArtifactPaths flags missing root runtime files in the tarball",
"src/shared/utils/nodeRuntimeSupport.ts",
]);
});
test("every shipped @omniroute workspace package is covered by an artifact prefix", () => {
const packageJson = JSON.parse(readFileSync("package.json", "utf8")) as { files: string[] };
assert.ok(packageJson.files.includes("@omniroute/"));
const workspacePackages = readdirSync("@omniroute", { withFileTypes: true })
.filter((entry) => entry.isDirectory() && existsSync(`@omniroute/${entry.name}/package.json`))
.map((entry) => `@omniroute/${entry.name}/`);
assert.ok(workspacePackages.includes("@omniroute/opencode-plugin-v2/"));
const uncovered = workspacePackages.filter(
(prefix) => !PACK_ARTIFACT_ALLOWED_PATH_PREFIXES.includes(prefix)
);
assert.deepEqual(uncovered, []);
});

View File

@@ -180,8 +180,9 @@ test("shared set size includes live REGISTRY and retired Designer + Felo + Qwen
// 2026-09-02: a keyless provider was removed at its operator's request, taking its id and
// alias out of the REGISTRY walk (408 → 406).
// #11786: SeekAi adds id "seekai" + alias "ska" (406 → 408).
// #13024/#13025: GreenPT and EURouter each add one REGISTRY id (408 → 410).
assert.equal(RESERVED_PREFIX_COUNT, 410);
// #13024 (2b9e7fb3e) GreenPT and #13025 (22473dee5) EURouter each add one REGISTRY member (id ==
// alias); #13277 (02128f334) registers Arcee AI, adding id "arcee-ai" + alias "arcee" (408 → 412).
assert.equal(RESERVED_PREFIX_COUNT, 412);
});
test("isReservedProviderPrefix rejects non-string input", () => {

View File

@@ -34,12 +34,14 @@
// Perplexity Agent API (#12103) makes it 236;
// UC Direct (#11513, uncensored.com metered Developer API) adds one frontier-labs entry — 237;
// SeekAi (#11786, QuantumNous New-API gateway) adds one gateways entry — 238.
// GreenPT (#13024) and EURouter (#13025) each add one OpenAI-compatible gateway entry — 240.
// GreenPT (#13024, 2b9e7fb3e) and EURouter (#13025, 22473dee5) each add one gateways entry — 240.
import { test } from "node:test";
import assert from "node:assert/strict";
const P = await import("../../src/shared/constants/providers.ts");
const APIKEY_PROVIDER_COUNT = 240;
test("barrel still exports every catalog + key helpers", () => {
for (const name of [
"NOAUTH_PROVIDERS",
@@ -63,12 +65,12 @@ test("barrel still exports every catalog + key helpers", () => {
}
});
test("APIKEY_PROVIDERS merges the 6 family files into 240 entries (no loss / no dup)", async () => {
test(`APIKEY_PROVIDERS merges the 6 family files into ${APIKEY_PROVIDER_COUNT} entries (no loss / no dup)`, async () => {
const keys = Object.keys((P as Record<string, object>).APIKEY_PROVIDERS);
assert.equal(keys.length, 240);
assert.equal(new Set(keys).size, 240, "duplicate keys after spread-merge");
assert.equal(keys.length, APIKEY_PROVIDER_COUNT);
assert.equal(new Set(keys).size, APIKEY_PROVIDER_COUNT, "duplicate keys after spread-merge");
// the merged object's entry-count equals the sum of the 6 semantic family files; families are a
// strict partition (every provider in exactly one), so the sum must be exactly 240.
// strict partition (every provider in exactly one), so the sum must be exactly APIKEY_PROVIDER_COUNT.
const families: [string, string][] = [
["gateways", "APIKEY_PROVIDERS_GATEWAYS"],
["frontier-labs", "APIKEY_PROVIDERS_FRONTIER"],
@@ -88,7 +90,11 @@ test("APIKEY_PROVIDERS merges the 6 family files into 240 entries (no loss / no
seen.add(k);
}
}
assert.equal(famTotal, 240, "families must partition all 240 providers");
assert.equal(
famTotal,
APIKEY_PROVIDER_COUNT,
`families must partition all ${APIKEY_PROVIDER_COUNT} providers`
);
});
test("AI_PROVIDERS Proxy aggregates all sections; lookups resolve", () => {

View File

@@ -9,10 +9,7 @@
*/
import assert from "node:assert/strict";
import { describe, it } from "node:test";
import {
createResourcePressureRuntime,
type ResourcePressureRuntime,
} from "../../open-sse/utils/resourcePressure.ts";
import { createResourcePressureRuntime } from "../../open-sse/utils/resourcePressure.ts";
import type { ResourceSignals } from "../../open-sse/utils/resourcePressurePolicy.ts";
const MiB = 1024 ** 2;

View File

@@ -38,7 +38,8 @@ test("#8135: sqljsAdapter must not statically resolve sql.js at build time", ()
// The standalone assembler ships sql.js as a real runtime package, so the
// adapter must not depend on a build-time createRequire/require.resolve lookup.
assert.doesNotMatch(source, /createRequire/);
assert.doesNotMatch(source, /createRequire\(\s*(?:import\.meta\.url|__filename)/);
assert.doesNotMatch(source, /^const\s+\w+\s*=\s*(?:\w+\.)?createRequire\s*\(/m);
assert.doesNotMatch(source, /\.resolve\(["']sql\.js["']\)/);
assert.match(source, /process\.cwd\(\)[\s\S]*"node_modules"[\s\S]*"sql\.js"/);
});

View File

@@ -0,0 +1,42 @@
import { describe, it } from "node:test";
import assert from "node:assert/strict";
import {
containsStrongCredentialToken,
redactSensitiveErrorText,
} from "../../open-sse/utils/errorSanitization.ts";
function elapsedMs(run: () => void): number {
const start = process.hrtime.bigint();
run();
return Number(process.hrtime.bigint() - start) / 1e6;
}
describe("strong credential token scan", () => {
it("containsStrongCredentialToken_LongAlphanumericRunWithoutKey_ScansInLinearTime", () => {
const run = "a".repeat(200_000);
let found = true;
const ms = elapsedMs(() => {
found = containsStrongCredentialToken(run);
});
assert.equal(found, false);
assert.ok(ms < 500, `scan took ${ms.toFixed(1)}ms for a 200k alphanumeric run`);
});
it("containsStrongCredentialToken_KeyGluedToAlphanumericPrefix_IsDetected", () => {
assert.equal(containsStrongCredentialToken("projsk-AbCdEfGhIjKl"), true);
assert.equal(containsStrongCredentialToken("(abcsk_AbCdEfGh12)"), true);
});
it("redactSensitiveErrorText_KeyGluedToAlphanumericPrefix_RedactsPrefixAndKey", () => {
const out = redactSensitiveErrorText("rejected xyzsk-AbCdEfGhIjKlMn for this project");
assert.equal(out, "rejected [REDACTED] for this project");
});
it("containsStrongCredentialToken_PrefixShorterThanThreeCharacters_IsNotAGluedKey", () => {
assert.equal(containsStrongCredentialToken("ab-xsk-AbCdEfGhIjKl"), false);
});
});

View File

@@ -144,8 +144,19 @@ test("scoreResetAwareQuota ranks lower-used Antigravity quota higher and avoids
test("orderTargetsByResetAwareQuota prefers Antigravity connection with more remaining quota", async () => {
registerGenericQuotaFetchers();
const low = `low-${randomUUID()}`;
const high = `high-${randomUUID()}`;
const { createProviderConnection } = await import("../../src/lib/db/providers.ts");
const [low, high] = await Promise.all(
["low", "high"].map(async (label) => {
const connection = await createProviderConnection({
provider: "antigravity",
authType: "oauth",
name: `${label}-${randomUUID()}`,
isActive: true,
testStatus: "active",
});
return String(connection.id);
})
);
const resetAt5h = new Date(Date.now() + 24 * 3600 * 1000).toISOString();
const resetAt7d = new Date(Date.now() + 5 * 24 * 3600 * 1000).toISOString();

View File

@@ -10,9 +10,8 @@ import assert from "node:assert/strict";
* same defect register one rule array — no pipeline changes.
*/
const { applyStatusRestatement, statusRestatementRegistry } = await import(
"../../open-sse/config/upstreamStatusRestatement.ts"
);
const { applyStatusRestatement, statusRestatementRegistry } =
await import("../../open-sse/config/upstreamStatusRestatement.ts");
test("R1: agentrouter 403 + 用户额度不足 → 429 with synthetic Retry-After", () => {
const out = applyStatusRestatement({
@@ -119,8 +118,50 @@ test("R10: chatCore wires applyStatusRestatement into the providerFailure block"
"utf8"
);
assert.match(src, /applyStatusRestatement\(/, "chatCore must call applyStatusRestatement");
const hookIndex = src.indexOf("applyStatusRestatement(");
const helperIndex = src.indexOf("const applyProviderFailureClassification = async (");
const blockIndex = src.indexOf("providerFailure: if (!providerResponse.ok)");
assert.ok(helperIndex > -1 && blockIndex > helperIndex, "classification helper and block exist");
const classifyCalls = src.match(/classifyProviderError\(/g) ?? [];
assert.equal(classifyCalls.length, 1, "chatCore classifies provider errors in exactly one place");
const classifyIndex = src.indexOf("classifyProviderError(statusCode");
assert.ok(hookIndex > -1 && classifyIndex > -1 && hookIndex < classifyIndex,
"restatement must run BEFORE classifyProviderError so fallback sees the corrected status");
assert.ok(
classifyIndex > helperIndex && classifyIndex < blockIndex,
"classifyProviderError must live inside applyProviderFailureClassification"
);
const block = src.slice(blockIndex);
const hookIndex = block.indexOf("applyStatusRestatement(");
const statusReassign = block.indexOf("statusCode = restatement.status;");
const retryReassign = block.indexOf("retryAfterMs = restatement.retryAfterMs;");
const classifyCallIndex = block.indexOf("await applyProviderFailureClassification(");
assert.ok(
hookIndex > -1 &&
statusReassign > hookIndex &&
retryReassign > hookIndex &&
classifyCallIndex > statusReassign &&
classifyCallIndex > retryReassign,
"restatement must reassign statusCode and retryAfterMs BEFORE the providerFailure block classifies"
);
});
test("R11: the shared provider execution pipeline restates before building the error result", async () => {
const { readFile } = await import("node:fs/promises");
const src = await readFile(
new URL("../../open-sse/handlers/chatCore/providerExecutionPipeline.ts", import.meta.url),
"utf8"
);
const outcomeIndex = src.indexOf("async function toOutcome(");
assert.ok(outcomeIndex > -1, "toOutcome exists");
const body = src.slice(outcomeIndex);
const hookIndex = body.indexOf("applyStatusRestatement(");
const resultIndex = body.search(/createErrorResult\(\s*restatement\.status,/);
assert.ok(
hookIndex > -1 && resultIndex > hookIndex,
"the non-streaming leg must surface the restated status to classification and the client"
);
assert.match(
body,
/createErrorResult\(\s*restatement\.status,\s*message,\s*restatement\.retryAfterMs/
);
});

View File

@@ -4,11 +4,11 @@ import fs from "node:fs";
import path from "node:path";
import os from "node:os";
import { resetDbInstance } from "../../src/lib/db/core.ts";
import { createProviderConnection, getProviderConnectionById } from "../../src/models/index.ts";
import {
createProviderConnection,
getProviderConnectionById,
} from "../../src/models/index.ts";
import { detectPlan, __testing as bindingTesting } from "../../src/lib/providers/volcenginePlanBinding.ts";
detectPlan,
__testing as bindingTesting,
} from "../../src/lib/providers/volcenginePlanBinding.ts";
test("detectPlan returns available: false when account has no active quota windows (unsubscribed)", async (t) => {
const originalFetch = globalThis.fetch;
@@ -67,7 +67,7 @@ test("volcenginePlanBinding upsert rules with SQLite temp isolation", async (t)
providerSpecificData: { autoFetchModels: true, customTag: "keep-me" },
});
const updated1 = await (bindingTesting as any).upsertConnection(
const updated1 = await bindingTesting.upsertConnection(
"coding",
"ark-new-key-1",
"new-cookie-1",
@@ -80,8 +80,16 @@ test("volcenginePlanBinding upsert rules with SQLite temp isolation", async (t)
assert.equal(updated1.id, conn1.id);
assert.equal(updated1.name, "main", "Preserves original custom name 'main'");
assert.equal(updated1.apiKey, "ark-new-key-1");
assert.equal(updated1.providerSpecificData.autoFetchModels, true, "Preserves existing PSD autoFetchModels");
assert.equal(updated1.providerSpecificData.customTag, "keep-me", "Preserves existing PSD customTag");
assert.equal(
updated1.providerSpecificData.autoFetchModels,
true,
"Preserves existing PSD autoFetchModels"
);
assert.equal(
updated1.providerSpecificData.customTag,
"keep-me",
"Preserves existing PSD customTag"
);
assert.equal(updated1.providerSpecificData.volcConsoleCookie, "new-cookie-1");
assert.equal(updated1.providerSpecificData.volcApiKeyId, 123);
@@ -93,7 +101,7 @@ test("volcenginePlanBinding upsert rules with SQLite temp isolation", async (t)
providerSpecificData: {},
});
const createdNew = await (bindingTesting as any).upsertConnection(
const createdNew = await bindingTesting.upsertConnection(
"coding",
"ark-brand-new-key-3",
"new-cookie-3",
@@ -117,7 +125,7 @@ test("volcenginePlanBinding upsert rules with SQLite temp isolation", async (t)
});
// Passing conn1.id (which is coding-plan) into agent upsert must NOT match conn1
const agentUpsertResult = await (bindingTesting as any).upsertConnection(
const agentUpsertResult = await bindingTesting.upsertConnection(
"agent",
"ark-agent-new-key",
"agent-cookie",
@@ -168,7 +176,8 @@ test("findTargetConnection pure matching logic and single-connection adoption in
{ id: "c2", provider: "volcengine-coding-plan", providerSpecificData: { volcApiKeyId: 888 } },
];
assert.equal(
bindingTesting.findTargetConnection(list3, { ...criteria, apiKey: undefined, apiKeyId: 888 })?.id,
bindingTesting.findTargetConnection(list3, { ...criteria, apiKey: undefined, apiKeyId: 888 })
?.id,
"c2"
);

View File

@@ -79,6 +79,7 @@ async function compileRuntimeRequireModules(): Promise<string[]> {
// has no repo tree, so treat the sibling as external instead of
// erroring "Can't resolve './obscura.ts'".
"./obscura.ts",
"./tlsFirstByteWatchdog.ts",
],
externalsPresets: { node: true },
mode: "development",