From a616b88c9516164b588b7f4e65b6296fe9941ea4 Mon Sep 17 00:00:00 2001 From: Diego Rodrigues de Sa e Souza Date: Wed, 15 Jul 2026 03:28:56 -0300 Subject: [PATCH] feat(provider): add Chenzk API OpenAI-compatible gateway MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Registers Chenzk (chenzk.top) as a new API-key gateway provider — an OpenAI-compatible aggregator exposing GPT/Claude/DeepSeek/GLM model groups behind one endpoint. Adapted to OmniRoute's directory-per-provider registry (open-sse/config/providers/registry/) and metadata catalog (src/shared/constants/providers/apikey/gateways.ts), following the same passthrough-models pattern already used for kenari/x5lab/sumopod (live /v1/models catalog resolves the model list instead of a hardcoded array). Co-authored-by: Ahmad Putra Cahyo Inspired-by: https://github.com/decolua/9router/pull/2437 --- open-sse/config/providers/index.ts | 2 + .../config/providers/registry/chenzk/index.ts | 15 ++++++ src/shared/constants/config.ts | 1 + .../constants/providers/apikey/gateways.ts | 13 +++++ tests/unit/chenzk-provider-2437.test.ts | 49 +++++++++++++++++++ 5 files changed, 80 insertions(+) create mode 100644 open-sse/config/providers/registry/chenzk/index.ts create mode 100644 tests/unit/chenzk-provider-2437.test.ts diff --git a/open-sse/config/providers/index.ts b/open-sse/config/providers/index.ts index ae083ecf34..8763f6326f 100644 --- a/open-sse/config/providers/index.ts +++ b/open-sse/config/providers/index.ts @@ -151,6 +151,7 @@ import { gigachatProvider } from "./registry/gigachat/index.ts"; import { devin_cliProvider } from "./registry/devin-cli/index.ts"; import { auggieProvider } from "./registry/auggie/index.ts"; import { chutesProvider } from "./registry/chutes/index.ts"; +import { chenzkProvider } from "./registry/chenzk/index.ts"; import { factoryProvider } from "./registry/factory/index.ts"; import { databricksProvider } from "./registry/databricks/index.ts"; import { rekaProvider } from "./registry/reka/index.ts"; @@ -336,6 +337,7 @@ export const REGISTRY: Record = { "devin-cli": devin_cliProvider, auggie: auggieProvider, chutes: chutesProvider, + chenzk: chenzkProvider, factory: factoryProvider, databricks: databricksProvider, reka: rekaProvider, diff --git a/open-sse/config/providers/registry/chenzk/index.ts b/open-sse/config/providers/registry/chenzk/index.ts new file mode 100644 index 0000000000..ee74a4d46f --- /dev/null +++ b/open-sse/config/providers/registry/chenzk/index.ts @@ -0,0 +1,15 @@ +import type { RegistryEntry } from "../../shared.ts"; + +export const chenzkProvider: RegistryEntry = { + id: "chenzk", + alias: "chenzk", + format: "openai", + executor: "default", + baseUrl: "https://chenzk.top/v1/chat/completions", + authType: "apikey", + authHeader: "bearer", + modelsUrl: "https://chenzk.top/v1/models", + defaultContextLength: 128000, + models: [], + passthroughModels: true, +}; diff --git a/src/shared/constants/config.ts b/src/shared/constants/config.ts index 30c3b426cb..100991598f 100644 --- a/src/shared/constants/config.ts +++ b/src/shared/constants/config.ts @@ -23,6 +23,7 @@ export const PROVIDER_ENDPOINTS = { sumopod: "https://ai.sumopod.com/v1/chat/completions", x5lab: "https://api.x5lab.dev/v1/chat/completions", kenari: "https://kenari.id/v1/chat/completions", + chenzk: "https://chenzk.top/v1/chat/completions", openai: "https://api.openai.com/v1/chat/completions", anthropic: "https://api.anthropic.com/v1/messages", gemini: "https://generativelanguage.googleapis.com/v1beta/models", diff --git a/src/shared/constants/providers/apikey/gateways.ts b/src/shared/constants/providers/apikey/gateways.ts index 59d1b10fde..69894ff504 100644 --- a/src/shared/constants/providers/apikey/gateways.ts +++ b/src/shared/constants/providers/apikey/gateways.ts @@ -579,6 +579,19 @@ export const APIKEY_PROVIDERS_GATEWAYS = { apiHint: "X5Lab exposes an OpenAI-compatible chat completions endpoint at https://api.x5lab.dev/v1/chat/completions, plus a live /v1/models catalog. OmniRoute uses the OpenAI protocol and lists models via passthrough.", }, + chenzk: { + id: "chenzk", + alias: "chenzk", + name: "Chenzk API", + icon: "hub", + color: "#10B981", + textIcon: "CZ", + passthroughModels: true, + website: "https://chenzk.top", + apiHint: + "Create an API key at https://chenzk.top/token, then paste it here as a Bearer token. " + + "OpenAI-compatible endpoint at https://chenzk.top/v1, with a live /v1/models catalog.", + }, kenari: { id: "kenari", alias: "kenari", diff --git a/tests/unit/chenzk-provider-2437.test.ts b/tests/unit/chenzk-provider-2437.test.ts new file mode 100644 index 0000000000..6c84052569 --- /dev/null +++ b/tests/unit/chenzk-provider-2437.test.ts @@ -0,0 +1,49 @@ +import test from "node:test"; +import assert from "node:assert/strict"; + +const { APIKEY_PROVIDERS } = await import("../../src/shared/constants/providers.ts"); +const { PROVIDER_ENDPOINTS } = await import("../../src/shared/constants/config.ts"); +const { REGISTRY: providerRegistry } = await import("../../open-sse/config/providerRegistry.ts"); + +const CHENZK_CHAT_URL = "https://chenzk.top/v1/chat/completions"; +const CHENZK_MODELS_URL = "https://chenzk.top/v1/models"; + +// Port of decolua/9router#2437 ("feat: add Chenzk API provider"), adapted to +// OmniRoute's directory-per-provider registry (`open-sse/config/providers/registry/`) +// and the `src/shared/constants/providers/apikey/*` metadata catalog, instead of +// upstream's flat `open-sse/providers/registry/*.js` + hardcoded model array. Chenzk +// exposes a "New API"-style OpenAI-compatible gateway with a live /v1/models catalog, +// so — matching the sibling kenari/x5lab/sumopod gateways already in this catalog — +// models are resolved via passthrough rather than a speculative hardcoded list. +test("Chenzk is registered as an OpenAI-compatible API-key gateway", () => { + const entry = APIKEY_PROVIDERS.chenzk; + assert.ok(entry, "APIKEY_PROVIDERS.chenzk must be defined"); + assert.equal(entry.id, "chenzk"); + assert.equal(entry.alias, "chenzk"); + assert.equal(entry.name, "Chenzk API"); + assert.equal(entry.website, "https://chenzk.top"); + assert.equal(entry.passthroughModels, true); +}); + +test("Chenzk exposes the OpenAI-compatible chat completions endpoint", () => { + assert.equal(PROVIDER_ENDPOINTS.chenzk, CHENZK_CHAT_URL); +}); + +test("Chenzk registry entry uses OpenAI format with bearer API-key auth and passthrough models", () => { + const entry = providerRegistry.chenzk; + assert.ok(entry, "providerRegistry.chenzk must be defined"); + assert.equal(entry.id, "chenzk"); + assert.equal(entry.alias, "chenzk"); + assert.equal(entry.format, "openai"); + assert.equal(entry.executor, "default"); + assert.equal(entry.authType, "apikey"); + assert.equal(entry.authHeader, "bearer"); + assert.equal(entry.baseUrl, CHENZK_CHAT_URL); + assert.equal(entry.modelsUrl, CHENZK_MODELS_URL); + assert.equal(entry.passthroughModels, true); + assert.deepEqual( + entry.models, + [], + "Chenzk ships no speculative seeded models — live catalog via passthrough only" + ); +});