Compare commits

...

17 Commits

Author SHA1 Message Date
diegosouzapw
bb94921f89 Merge remote-tracking branch 'origin/release/v3.8.50' into feat/free-tier-providers-phase3
# Conflicts:
#	open-sse/config/providers/index.ts
#	open-sse/config/providers/registry/unorouter/index.ts
2026-08-08 11:54:06 -03:00
diegosouzapw
d2d0c5919f feat(providers): integrate wave4 free-tier gateways 2026-08-02 08:33:37 -03:00
diegosouzapw
1637ae9798 feat(providers): add Free.ai registry 2026-08-02 08:15:41 -03:00
diegosouzapw
029bfd2488 feat(providers): add FreeInference registry 2026-08-02 08:15:41 -03:00
diegosouzapw
25854674c8 feat(providers): integrate wave3 free-tier gateways 2026-08-02 03:11:27 -03:00
diegosouzapw
9a8451b223 feat(providers): add Naga AI and Chat Oripe registries 2026-08-02 03:04:38 -03:00
diegosouzapw
188a7be2f5 feat(providers): add HelyxAI Auriko and Poixe registries 2026-08-02 03:03:53 -03:00
diegosouzapw
8853228c20 feat(providers): add Wave 3-A free-tier registries 2026-08-02 03:03:53 -03:00
diegosouzapw
e7b5e1870f feat(providers): integrate wave2 free-tier gateways 2026-08-02 01:52:26 -03:00
diegosouzapw
8b55e61bdb fix: align meganova provider slug 2026-08-02 01:38:45 -03:00
diegosouzapw
85e8fd8a19 feat: add wave 2 free-tier provider registries 2026-08-02 01:36:47 -03:00
diegosouzapw
89ae04867b feat(providers): add Mixlayer Speka and TokenReply registries 2026-08-02 01:36:47 -03:00
diegosouzapw
72e5bc9cb6 feat: add wave2 free-tier provider registries 2026-08-02 01:36:47 -03:00
diegosouzapw
58eb441307 feat(providers): integrate audited free-tier gateways 2026-08-01 23:27:36 -03:00
diegosouzapw
ddc4c827a7 feat(providers): add LLMGateway and LLM Kiwi registries 2026-08-01 23:13:26 -03:00
diegosouzapw
c7d9e9c4c7 feat(providers): add FastRouter AnyAPI and ElectronHub registries 2026-08-01 23:13:26 -03:00
diegosouzapw
f3c2e30879 feat(providers): add Zylo UnoRouter and Poolside registries 2026-08-01 23:13:25 -03:00
41 changed files with 1436 additions and 8 deletions

View File

@@ -1,5 +1,4 @@
import type { RegistryEntry } from "./shared.ts";
import { unorouterProvider } from "./registry/unorouter/index.ts";
import { aimlapiProvider } from "./registry/aimlapi/index.ts";
import { byteplusProvider } from "./registry/byteplus/index.ts";
@@ -22,7 +21,6 @@ import { glmProvider } from "./registry/glm/index.ts";
import { glmtProvider } from "./registry/glm/t/index.ts";
import { glm_cnProvider } from "./registry/glm/cn/index.ts";
import { traeProvider } from "./registry/trae/index.ts";
import { raycastProvider } from "./registry/raycast/index.ts";
import { muse_spark_webProvider } from "./registry/muse-spark-web/index.ts";
import { lmarenaProvider } from "./registry/lmarena/index.ts";
import { kilocodeProvider } from "./registry/kilocode/index.ts";
@@ -148,7 +146,6 @@ import { siliconflowProvider } from "./registry/siliconflow/index.ts";
import { gitlab_duoProvider } from "./registry/gitlab-duo/index.ts";
import { command_codeProvider } from "./registry/command-code/index.ts";
import { novitaProvider } from "./registry/novita/index.ts";
import { regoloProvider } from "./registry/regolo/index.ts";
import { windsurfProvider } from "./registry/windsurf/index.ts";
import { zed_hostedProvider } from "./registry/zed-hosted/index.ts";
import { nanogptProvider } from "./registry/nanogpt/index.ts";
@@ -171,7 +168,6 @@ import { kilo_gatewayProvider } from "./registry/kilo-gateway/index.ts";
import { bailian_coding_planProvider } from "./registry/bailian-coding-plan/index.ts";
import { gigachatProvider } from "./registry/gigachat/index.ts";
import { devin_cliProvider } from "./registry/devin-cli/index.ts";
import { devin_cli_agenticProvider } from "./registry/devin-cli-agentic/index.ts";
import { auggieProvider } from "./registry/auggie/index.ts";
import { chutesProvider } from "./registry/chutes/index.ts";
import { chenzkProvider } from "./registry/chenzk/index.ts";
@@ -225,6 +221,33 @@ import { digitaloceanProvider } from "./registry/digitalocean/index.ts";
import { hcnsecProvider } from "./registry/hcnsec/index.ts";
import { promptqlProvider } from "./registry/promptql/index.ts";
import { hyperagentProvider } from "./registry/hyperagent/index.ts";
import { zyloApiProvider } from "./registry/zylo-api/index.ts";
import { unorouterProvider } from "./registry/unorouter/index.ts";
import { poolsideProvider } from "./registry/poolside/index.ts";
import { fastrouterProvider } from "./registry/fastrouter/index.ts";
import { anyapiProvider } from "./registry/anyapi/index.ts";
import { electronhubProvider } from "./registry/electronhub/index.ts";
import { llmgatewayProvider } from "./registry/llmgateway/index.ts";
import { llmKiwiProvider } from "./registry/llm-kiwi/index.ts";
import { literouterProvider } from "./registry/literouter/index.ts";
import { mnnAiProvider } from "./registry/mnn-ai/index.ts";
import { meganovaAiProvider } from "./registry/meganova-ai/index.ts";
import { mixlayerProvider } from "./registry/mixlayer/index.ts";
import { spekaProvider } from "./registry/speka/index.ts";
import { tokenreplyProvider } from "./registry/tokenreply/index.ts";
import { yoloAutoProvider } from "./registry/yolo-auto/index.ts";
import { dxntProvider } from "./registry/dxnt/index.ts";
import { cloudcodeOneProvider } from "./registry/cloudcode-one/index.ts";
import { ofoxaiProvider } from "./registry/ofoxai/index.ts";
import { zerolimitaiProvider } from "./registry/zerolimitai/index.ts";
import { chatanywhereProvider } from "./registry/chatanywhere/index.ts";
import { helyxaiProvider } from "./registry/helyxai/index.ts";
import { aurikoProvider } from "./registry/auriko/index.ts";
import { poixeAiProvider } from "./registry/poixe-ai/index.ts";
import { nagaAiProvider } from "./registry/naga-ai/index.ts";
import { chatOripeProvider } from "./registry/chat-oripe/index.ts";
import { freeinferenceProvider } from "./registry/freeinference/index.ts";
import { freeAiProvider } from "./registry/free-ai/index.ts";
export const REGISTRY: Record<string, RegistryEntry> = {
aimlapi: aimlapiProvider,
@@ -246,7 +269,6 @@ export const REGISTRY: Record<string, RegistryEntry> = {
glmt: glmtProvider,
"glm-cn": glm_cnProvider,
trae: traeProvider,
raycast: raycastProvider,
"muse-spark-web": muse_spark_webProvider,
lmarena: lmarenaProvider,
kilocode: kilocodeProvider,
@@ -372,7 +394,6 @@ export const REGISTRY: Record<string, RegistryEntry> = {
"gitlab-duo": gitlab_duoProvider,
"command-code": command_codeProvider,
novita: novitaProvider,
regolo: regoloProvider,
windsurf: windsurfProvider,
"zed-hosted": zed_hostedProvider,
nanogpt: nanogptProvider,
@@ -394,7 +415,6 @@ export const REGISTRY: Record<string, RegistryEntry> = {
"bailian-coding-plan": bailian_coding_planProvider,
gigachat: gigachatProvider,
"devin-cli": devin_cliProvider,
"devin-cli-agentic": devin_cli_agenticProvider,
auggie: auggieProvider,
chutes: chutesProvider,
chenzk: chenzkProvider,
@@ -451,5 +471,31 @@ export const REGISTRY: Record<string, RegistryEntry> = {
hcnsec: hcnsecProvider,
promptql: promptqlProvider,
hyperagent: hyperagentProvider,
"zylo-api": zyloApiProvider,
unorouter: unorouterProvider,
poolside: poolsideProvider,
fastrouter: fastrouterProvider,
anyapi: anyapiProvider,
electronhub: electronhubProvider,
llmgateway: llmgatewayProvider,
"llm-kiwi": llmKiwiProvider,
literouter: literouterProvider,
"mnn-ai": mnnAiProvider,
"meganova-ai": meganovaAiProvider,
mixlayer: mixlayerProvider,
speka: spekaProvider,
tokenreply: tokenreplyProvider,
"yolo-auto": yoloAutoProvider,
dxnt: dxntProvider,
"cloudcode-one": cloudcodeOneProvider,
ofoxai: ofoxaiProvider,
zerolimitai: zerolimitaiProvider,
chatanywhere: chatanywhereProvider,
helyxai: helyxaiProvider,
auriko: aurikoProvider,
"poixe-ai": poixeAiProvider,
"naga-ai": nagaAiProvider,
"chat-oripe": chatOripeProvider,
freeinference: freeinferenceProvider,
"free-ai": freeAiProvider,
};

View File

@@ -0,0 +1,11 @@
import type { RegistryEntry } from "../../shared.ts";
import { buildOpenAiCompatibleRegistryEntry } from "../../shared.ts";
export const aurikoProvider: RegistryEntry = buildOpenAiCompatibleRegistryEntry({
id: "auriko",
alias: "auriko",
baseUrl: "https://api.auriko.ai/v1/chat/completions",
modelsUrl: "https://api.auriko.ai/v1/models",
models: [],
passthroughModels: true,
});

View File

@@ -0,0 +1,12 @@
import type { RegistryEntry } from "../../shared.ts";
import { buildOpenAiCompatibleRegistryEntry } from "../../shared.ts";
// The upstream brand and hostname are ambiguous, so avoid unverified quota claims.
export const chatOripeProvider: RegistryEntry = buildOpenAiCompatibleRegistryEntry({
id: "chat-oripe",
alias: "chat-oripe",
baseUrl: "https://api.oriper.com/v1/chat/completions",
modelsUrl: "https://api.oriper.com/v1/models",
models: [],
passthroughModels: true,
});

View File

@@ -0,0 +1,12 @@
import type { RegistryEntry } from "../../shared.ts";
import { buildOpenAiCompatibleRegistryEntry } from "../../shared.ts";
// International endpoint; audited free access is limited to non-commercial use.
export const chatanywhereProvider: RegistryEntry = buildOpenAiCompatibleRegistryEntry({
id: "chatanywhere",
alias: "chatanywhere",
baseUrl: "https://api.chatanywhere.org/v1/chat/completions",
modelsUrl: "https://api.chatanywhere.org/v1/models",
models: [],
passthroughModels: true,
});

View File

@@ -0,0 +1,20 @@
import type { RegistryEntry } from "../../shared.ts";
import { buildOpenAiCompatibleRegistryEntry } from "../../shared.ts";
/**
* CloudCode.ONE - OpenAI-compatible API with published free model aliases.
*
* The Anthropic-compatible endpoint is documented separately; this registry
* covers the OpenAI-compatible API surface audited for this migration.
*/
export const cloudcodeOneProvider: RegistryEntry = buildOpenAiCompatibleRegistryEntry({
id: "cloudcode-one",
alias: "cloudcode-one",
baseUrl: "https://api.cloudcode.one/v1/chat/completions",
modelsUrl: "https://api.cloudcode.one/v1/models",
models: [
{ id: "glm-4.7-flash", name: "GLM 4.7 Flash" },
{ id: "glm-4.6v-flash", name: "GLM 4.6V Flash" },
],
passthroughModels: true,
});

View File

@@ -0,0 +1,17 @@
import type { RegistryEntry } from "../../shared.ts";
import { buildOpenAiCompatibleRegistryEntry } from "../../shared.ts";
/**
* DXNT - OpenAI-compatible API with a free account quota.
*
* Models are discovered from the provider's authenticated catalog rather than
* copied into a static list, so account-specific availability remains intact.
*/
export const dxntProvider: RegistryEntry = buildOpenAiCompatibleRegistryEntry({
id: "dxnt",
alias: "dxnt",
baseUrl: "https://www.dxnt.com/v1/chat/completions",
modelsUrl: "https://www.dxnt.com/v1/models",
models: [],
passthroughModels: true,
});

View File

@@ -0,0 +1,11 @@
import type { RegistryEntry } from "../../shared.ts";
import { buildOpenAiCompatibleRegistryEntry } from "../../shared.ts";
export const freeAiProvider: RegistryEntry = buildOpenAiCompatibleRegistryEntry({
id: "free-ai",
alias: "free-ai",
baseUrl: "https://api.free.ai/v1/chat/",
modelsUrl: "https://api.free.ai/v1/models",
models: [],
passthroughModels: true,
});

View File

@@ -0,0 +1,11 @@
import type { RegistryEntry } from "../../shared.ts";
import { buildOpenAiCompatibleRegistryEntry } from "../../shared.ts";
export const freeinferenceProvider: RegistryEntry = buildOpenAiCompatibleRegistryEntry({
id: "freeinference",
alias: "freeinference",
baseUrl: "https://freeinference.org/v1/chat/completions",
modelsUrl: "https://freeinference.org/v1/models",
models: [],
passthroughModels: true,
});

View File

@@ -0,0 +1,11 @@
import type { RegistryEntry } from "../../shared.ts";
import { buildOpenAiCompatibleRegistryEntry } from "../../shared.ts";
export const helyxaiProvider: RegistryEntry = buildOpenAiCompatibleRegistryEntry({
id: "helyxai",
alias: "helyxai",
baseUrl: "https://helyxai.space/v1/chat/completions",
modelsUrl: "https://helyxai.space/v1/models",
models: [],
passthroughModels: true,
});

View File

@@ -0,0 +1,11 @@
import type { RegistryEntry } from "../../shared.ts";
import { buildOpenAiCompatibleRegistryEntry } from "../../shared.ts";
export const literouterProvider: RegistryEntry = buildOpenAiCompatibleRegistryEntry({
id: "literouter",
alias: "literouter",
baseUrl: "https://api.literouter.com/v1/chat/completions",
modelsUrl: "https://api.literouter.com/v1/models",
models: [],
passthroughModels: true,
});

View File

@@ -0,0 +1,11 @@
import type { RegistryEntry } from "../../shared.ts";
import { buildOpenAiCompatibleRegistryEntry } from "../../shared.ts";
export const meganovaAiProvider: RegistryEntry = buildOpenAiCompatibleRegistryEntry({
id: "meganova-ai",
alias: "meganova-ai",
baseUrl: "https://api.meganova.ai/v1/chat/completions",
modelsUrl: "https://api.meganova.ai/v1/models",
models: [],
passthroughModels: true,
});

View File

@@ -0,0 +1,11 @@
import type { RegistryEntry } from "../../shared.ts";
import { buildOpenAiCompatibleRegistryEntry } from "../../shared.ts";
export const mixlayerProvider: RegistryEntry = buildOpenAiCompatibleRegistryEntry({
id: "mixlayer",
alias: "mixlayer",
baseUrl: "https://models.mixlayer.ai/v1/chat/completions",
modelsUrl: "https://models.mixlayer.ai/v1/models",
models: [{ id: "qwen/qwen3.5-4b-free", name: "Qwen 3.5 4B (free)" }],
passthroughModels: true,
});

View File

@@ -0,0 +1,11 @@
import type { RegistryEntry } from "../../shared.ts";
import { buildOpenAiCompatibleRegistryEntry } from "../../shared.ts";
export const mnnAiProvider: RegistryEntry = buildOpenAiCompatibleRegistryEntry({
id: "mnn-ai",
alias: "mnn-ai",
baseUrl: "https://api.mnnai.ru/v1/chat/completions",
modelsUrl: "https://api.mnnai.ru/v1/models",
models: [],
passthroughModels: true,
});

View File

@@ -0,0 +1,12 @@
import type { RegistryEntry } from "../../shared.ts";
import { buildOpenAiCompatibleRegistryEntry } from "../../shared.ts";
// Free access terms may permit data collection or training use; discover models dynamically.
export const nagaAiProvider: RegistryEntry = buildOpenAiCompatibleRegistryEntry({
id: "naga-ai",
alias: "naga-ai",
baseUrl: "https://api.naga.ac/v1/chat/completions",
modelsUrl: "https://api.naga.ac/v1/models",
models: [],
passthroughModels: true,
});

View File

@@ -0,0 +1,11 @@
import type { RegistryEntry } from "../../shared.ts";
import { buildOpenAiCompatibleRegistryEntry } from "../../shared.ts";
export const ofoxaiProvider: RegistryEntry = buildOpenAiCompatibleRegistryEntry({
id: "ofoxai",
alias: "ofoxai",
baseUrl: "https://api.ofox.ai/v1/chat/completions",
modelsUrl: "https://api.ofox.ai/v1/models",
models: [],
passthroughModels: true,
});

View File

@@ -0,0 +1,11 @@
import type { RegistryEntry } from "../../shared.ts";
import { buildOpenAiCompatibleRegistryEntry } from "../../shared.ts";
export const poixeAiProvider: RegistryEntry = buildOpenAiCompatibleRegistryEntry({
id: "poixe-ai",
alias: "poixe-ai",
baseUrl: "https://api.poixe.com/v1/chat/completions",
modelsUrl: "https://api.poixe.com/v1/models",
models: [],
passthroughModels: true,
});

View File

@@ -0,0 +1,11 @@
import type { RegistryEntry } from "../../shared.ts";
import { buildOpenAiCompatibleRegistryEntry } from "../../shared.ts";
export const poolsideProvider: RegistryEntry = buildOpenAiCompatibleRegistryEntry({
id: "poolside",
alias: "poolside",
baseUrl: "https://inference.poolside.ai/v1/chat/completions",
modelsUrl: "https://inference.poolside.ai/v1/models",
models: [],
passthroughModels: true,
});

View File

@@ -0,0 +1,11 @@
import type { RegistryEntry } from "../../shared.ts";
import { buildOpenAiCompatibleRegistryEntry } from "../../shared.ts";
export const spekaProvider: RegistryEntry = buildOpenAiCompatibleRegistryEntry({
id: "speka",
alias: "speka",
baseUrl: "https://speka.me/v1/chat/completions",
modelsUrl: "https://speka.me/v1/models",
models: [],
passthroughModels: true,
});

View File

@@ -0,0 +1,11 @@
import type { RegistryEntry } from "../../shared.ts";
import { buildOpenAiCompatibleRegistryEntry } from "../../shared.ts";
export const tokenreplyProvider: RegistryEntry = buildOpenAiCompatibleRegistryEntry({
id: "tokenreply",
alias: "tokenreply",
baseUrl: "https://api.tokenreply.com/v1/chat/completions",
modelsUrl: "https://api.tokenreply.com/v1/models",
models: [],
passthroughModels: true,
});

View File

@@ -0,0 +1,17 @@
import type { RegistryEntry } from "../../shared.ts";
import { buildOpenAiCompatibleRegistryEntry } from "../../shared.ts";
/**
* Yolo-Auto - OpenAI-compatible API with a request-limited free tier.
*
* The catalog is kept intentionally small: the documented free-tier model is
* seeded while passthrough discovery allows the service to publish updates.
*/
export const yoloAutoProvider: RegistryEntry = buildOpenAiCompatibleRegistryEntry({
id: "yolo-auto",
alias: "yolo-auto",
baseUrl: "https://yolo-auto.com/v1/chat/completions",
modelsUrl: "https://yolo-auto.com/v1/models",
models: [{ id: "qwen3.6-35b-a3b", name: "Qwen 3.6 35B A3B" }],
passthroughModels: true,
});

View File

@@ -0,0 +1,11 @@
import type { RegistryEntry } from "../../shared.ts";
import { buildOpenAiCompatibleRegistryEntry } from "../../shared.ts";
export const zerolimitaiProvider: RegistryEntry = buildOpenAiCompatibleRegistryEntry({
id: "zerolimitai",
alias: "zerolimitai",
baseUrl: "https://www.zerolimitai.com/api/v1/chat/completions",
modelsUrl: "https://www.zerolimitai.com/api/v1/models",
models: [],
passthroughModels: true,
});

View File

@@ -0,0 +1,11 @@
import type { RegistryEntry } from "../../shared.ts";
import { buildOpenAiCompatibleRegistryEntry } from "../../shared.ts";
export const zyloApiProvider: RegistryEntry = buildOpenAiCompatibleRegistryEntry({
id: "zylo-api",
alias: "zylo",
baseUrl: "https://api.zyloai.net/v1/chat/completions",
modelsUrl: "https://api.zyloai.net/v1/models",
models: [],
passthroughModels: true,
});

View File

@@ -7,6 +7,33 @@ export const PROVIDER_ENDPOINTS = {
dgrid: "https://api.dgrid.ai/v1/chat/completions",
bai: "https://api.b.ai/v1/chat/completions",
qiniu: "https://api.qnaigc.com/v1/chat/completions",
"zylo-api": "https://api.zyloai.net/v1/chat/completions",
unorouter: "https://api.unorouter.com/v1/chat/completions",
poolside: "https://inference.poolside.ai/v1/chat/completions",
fastrouter: "https://api.fastrouter.ai/api/v1/chat/completions",
anyapi: "https://api.anyapi.ai/v1/chat/completions",
electronhub: "https://api.electronhub.ai/v1/chat/completions",
llmgateway: "https://api.llmgateway.io/v1/chat/completions",
"llm-kiwi": "https://api.llm.kiwi/v1/chat/completions",
literouter: "https://api.literouter.com/v1/chat/completions",
"mnn-ai": "https://api.mnnai.ru/v1/chat/completions",
"meganova-ai": "https://api.meganova.ai/v1/chat/completions",
mixlayer: "https://models.mixlayer.ai/v1/chat/completions",
speka: "https://speka.me/v1/chat/completions",
tokenreply: "https://api.tokenreply.com/v1/chat/completions",
"yolo-auto": "https://yolo-auto.com/v1/chat/completions",
dxnt: "https://www.dxnt.com/v1/chat/completions",
"cloudcode-one": "https://api.cloudcode.one/v1/chat/completions",
ofoxai: "https://api.ofox.ai/v1/chat/completions",
zerolimitai: "https://www.zerolimitai.com/api/v1/chat/completions",
chatanywhere: "https://api.chatanywhere.org/v1/chat/completions",
helyxai: "https://helyxai.space/v1/chat/completions",
auriko: "https://api.auriko.ai/v1/chat/completions",
"poixe-ai": "https://api.poixe.com/v1/chat/completions",
"naga-ai": "https://api.naga.ac/v1/chat/completions",
"chat-oripe": "https://api.oriper.com/v1/chat/completions",
freeinference: "https://freeinference.org/v1/chat/completions",
"free-ai": "https://api.free.ai/v1/chat/",
glm: "https://api.z.ai/api/anthropic/v1/messages",
glmt: "https://api.z.ai/api/anthropic/v1/messages",
"bailian-coding-plan": "https://coding-intl.dashscope.aliyuncs.com/apps/anthropic/v1/messages",

View File

@@ -21,7 +21,10 @@ import { PROVIDER_MODELS as MODELS } from "@omniroute/open-sse/config/providerMo
const PASSTHROUGH_PROVIDERS = new Set(
Object.entries(AI_PROVIDERS)
.filter(([, p]) => (p as any).passthroughModels)
.map(([key]) => key)
.flatMap(([key, provider]) => {
const alias = (provider as { alias?: unknown }).alias;
return typeof alias === "string" && alias.length > 0 ? [key, alias] : [key];
})
);
// Wrap isValidModel with passthrough providers

View File

@@ -92,6 +92,32 @@ export const AGGREGATOR_PROVIDER_IDS = new Set([
"g4f-pollinations",
"g4f-ollama",
"g4f-nvidia",
"zylo-api",
"unorouter",
"fastrouter",
"anyapi",
"electronhub",
"llmgateway",
"llm-kiwi",
"literouter",
"mnn-ai",
"meganova-ai",
"mixlayer",
"speka",
"tokenreply",
"yolo-auto",
"dxnt",
"cloudcode-one",
"ofoxai",
"zerolimitai",
"chatanywhere",
"helyxai",
"auriko",
"poixe-ai",
"naga-ai",
"chat-oripe",
"freeinference",
"free-ai",
]);
export const ENTERPRISE_CLOUD_PROVIDER_IDS = new Set([

View File

@@ -95,6 +95,395 @@ export const APIKEY_PROVIDERS_GATEWAYS = {
"Create an API key at https://app.requesty.ai, then paste it here as a Bearer token. " +
"OpenAI-compatible endpoint at https://router.requesty.ai/v1, with a live /v1/models catalog.",
},
"zylo-api": {
id: "zylo-api",
alias: "zylo",
name: "Zylo API",
icon: "hub",
color: "#2563EB",
textIcon: "ZY",
passthroughModels: true,
website: "https://zyloai.net",
hasFree: true,
freeNote:
"Basic plan: 10 RPM, 7,200 requests/day and 200,000 tokens/day; limited to Basic text models.",
apiHint:
"Create a free Zylo API key at https://zyloai.net, then use https://api.zyloai.net/v1 as the OpenAI-compatible base URL.",
},
unorouter: {
id: "unorouter",
alias: "unorouter",
name: "UnoRouter",
icon: "router",
color: "#7C3AED",
textIcon: "UR",
passthroughModels: true,
website: "https://unorouter.com",
hasFree: true,
freeNote:
"Models with the :free suffix do not debit balance; limit is 1 request/minute per free model per user.",
apiHint:
"Create an UnoRouter token, then use https://api.unorouter.com/v1 as the OpenAI-compatible base URL.",
},
fastrouter: {
id: "fastrouter",
alias: "fastrouter",
name: "FastRouter",
icon: "speed",
color: "#F97316",
textIcon: "FR",
passthroughModels: true,
website: "https://fastrouter.ai",
hasFree: true,
freeNote:
"Models with the :free suffix allow 10 requests/day per organization and model; availability may change.",
apiHint:
"Create a FastRouter API key, then use https://api.fastrouter.ai/api/v1 as the OpenAI-compatible base URL.",
},
anyapi: {
id: "anyapi",
alias: "anyapi",
name: "AnyAPI AI",
icon: "hub",
color: "#0EA5E9",
textIcon: "AA",
passthroughModels: true,
website: "https://anyapi.ai",
hasFree: true,
freeNote:
"Free plan: 100,000 ANY Tokens/day and 100 RPM for eligible Free/Basic models; no credit card required.",
apiHint:
"Create and verify an AnyAPI account, then use https://api.anyapi.ai/v1 as the OpenAI-compatible base URL.",
},
electronhub: {
id: "electronhub",
alias: "electronhub",
name: "Electron Hub",
icon: "hub",
color: "#22C55E",
textIcon: "EH",
passthroughModels: true,
website: "https://www.electronhub.ai",
hasFree: true,
freeNote:
"Free plan: 5 RPM, $0.25 weekly credits and 10 Neutrinos/day for :free models; family budgets also apply.",
apiHint:
"Create a free API key at https://app.electronhub.ai, then use https://api.electronhub.ai/v1 as the OpenAI-compatible base URL.",
},
llmgateway: {
id: "llmgateway",
alias: "llmgateway",
name: "LLM Gateway",
icon: "router",
color: "#6366F1",
textIcon: "LG",
passthroughModels: true,
website: "https://llmgateway.io",
hasFree: true,
freeNote:
"Hosted Free plan: free-priced models are limited to 5 requests per 10 minutes when the account has no credits.",
apiHint:
"Create an LLM Gateway API key, then use https://api.llmgateway.io/v1 as the OpenAI-compatible base URL.",
},
"llm-kiwi": {
id: "llm-kiwi",
alias: "llmkiwi",
name: "LLM.Kiwi",
icon: "hub",
color: "#84CC16",
textIcon: "LK",
passthroughModels: true,
website: "https://llm.kiwi",
hasFree: true,
freeNote:
"Free plan exposes auto and hrLLM; the published 40 requests/hour limit applies to hrLLM.",
apiHint:
"Create a free LLM.Kiwi key, then use https://api.llm.kiwi/v1 as the OpenAI-compatible base URL.",
},
literouter: {
id: "literouter",
alias: "literouter",
name: "LiteRouter",
icon: "router",
color: "#2563EB",
textIcon: "LR",
passthroughModels: true,
website: "https://literouter.com",
hasFree: true,
freeNote:
"Free model variants use the :free suffix; daily credit limits vary by model and free input is capped at 5,000 tokens.",
apiHint:
"Create a LiteRouter API key, then use https://api.literouter.com/v1 as the OpenAI-compatible base URL.",
},
"mnn-ai": {
id: "mnn-ai",
alias: "mnn-ai",
name: "MNN AI",
icon: "hub",
color: "#0F766E",
textIcon: "MNN",
passthroughModels: true,
website: "https://mnnai.ru",
hasFree: true,
freeNote: "Free plan: $1 monthly credits, 10 RPM and access only to models marked Free.",
apiHint:
"Create an MNN AI API key, then use the primary https://api.mnnai.ru/v1 OpenAI-compatible endpoint. Review jurisdiction, privacy and regional data-transfer requirements before use.",
},
"meganova-ai": {
id: "meganova-ai",
alias: "meganova-ai",
name: "MegaNova AI",
icon: "router",
color: "#7C3AED",
textIcon: "MN",
passthroughModels: true,
website: "https://meganova.ai",
hasFree: true,
freeNote:
"Free signup without a card. Published Tier 1 per-model quotas total 550 requests/day; they are not a shared global pool, and paid overage can apply if enabled.",
apiHint:
"Create a MegaNova API key, then use https://api.meganova.ai/v1 as the OpenAI-compatible base URL.",
},
mixlayer: {
id: "mixlayer",
alias: "mixlayer",
name: "Mixlayer",
icon: "router",
color: "#0EA5E9",
textIcon: "MX",
passthroughModels: true,
website: "https://www.mixlayer.com",
hasFree: true,
freeNote:
"The qwen/qwen3.5-4b-free model is free for prototyping and rate-limited; no fixed public RPM or daily quota is confirmed.",
apiHint:
"Create a Mixlayer API key, then use https://models.mixlayer.ai/v1 as the OpenAI-compatible base URL.",
},
speka: {
id: "speka",
alias: "speka",
name: "Speka AI",
icon: "router",
color: "#DB2777",
textIcon: "SP",
passthroughModels: true,
website: "https://speka.me",
hasFree: true,
freeNote:
"Free plan: $1 monthly usage, 10 RPM, one API key and access to open models and the playground; no card required.",
apiHint:
"Create a Speka API key, then use https://speka.me/v1 as the OpenAI-compatible base URL. Confirm current model availability and overage settings before use.",
},
tokenreply: {
id: "tokenreply",
alias: "tokenreply",
name: "TokenReply",
icon: "router",
color: "#3B82F6",
textIcon: "TR",
passthroughModels: true,
website: "https://www.tokenreply.com",
hasFree: true,
freeNote:
"Free-tagged models have model- and campaign-specific daily limits; no fixed global free quota is published.",
apiHint:
"Create a TokenReply token, then use https://api.tokenreply.com/v1 as the OpenAI-compatible base URL and confirm the selected model's current limit.",
},
"yolo-auto": {
id: "yolo-auto",
alias: "yolo-auto",
name: "Yolo-Auto",
icon: "auto_awesome",
color: "#F59E0B",
textIcon: "YA",
passthroughModels: true,
website: "https://yolo-auto.com",
hasFree: true,
freeNote:
"Free API access is request-limited and intended for testing; no numeric daily quota is published and free access is not promised indefinitely.",
apiHint:
"Create a yolo_ API key, then use https://yolo-auto.com/v1 as the OpenAI-compatible base URL.",
},
dxnt: {
id: "dxnt",
alias: "dxnt",
name: "DXNT / DX Token",
icon: "hub",
color: "#111827",
textIcon: "DX",
passthroughModels: true,
website: "https://www.dxnt.com",
hasFree: true,
freeNote:
"Free accounts are documented at 100 calls/day; the quota may increase through invitations and can vary by account.",
apiHint:
"Create a DXNT API key, then use https://www.dxnt.com/v1 as the OpenAI-compatible base URL.",
},
"cloudcode-one": {
id: "cloudcode-one",
alias: "cloudcode-one",
name: "CloudCode.ONE",
icon: "router",
color: "#6366F1",
textIcon: "CC",
passthroughModels: true,
website: "https://cloudcode.one",
hasFree: true,
freeNote:
"Published free models include glm-4.7-flash and glm-4.6v-flash; no numeric quota is published, and key creation may require credit or a coupon.",
apiHint:
"Create a CloudCode.ONE key, then use https://api.cloudcode.one/v1 as the OpenAI-compatible base URL. Key issuance may require credit or a coupon.",
},
ofoxai: {
id: "ofoxai",
alias: "ofoxai",
name: "OfoxAI",
icon: "router",
color: "#0F766E",
textIcon: "OF",
passthroughModels: true,
website: "https://ofox.ai",
hasFree: true,
freeNote:
"The current catalog advertises 10+ free models without a public numeric quota; review upstream provenance, retention and training terms before production use.",
apiHint:
"Create an OfoxAI Bearer key, then use https://api.ofox.ai/v1 as the OpenAI-compatible base URL. This integration covers the OpenAI surface only.",
},
zerolimitai: {
id: "zerolimitai",
alias: "zerolimitai",
name: "ZeroLimitAI",
icon: "router",
color: "#475569",
textIcon: "ZL",
passthroughModels: true,
website: "https://www.zerolimitai.com",
hasFree: true,
freeNote:
"Temporary free trial is advertised, but official pages conflict between 3 and 7 days; a 100-calls/day claim is not treated as permanent.",
apiHint:
"Create a ZeroLimitAI Bearer token, then use https://www.zerolimitai.com/api/v1 as the OpenAI-compatible base URL.",
},
chatanywhere: {
id: "chatanywhere",
alias: "chatanywhere",
name: "ChatAnywhere",
icon: "router",
color: "#2563EB",
textIcon: "CA",
passthroughModels: true,
website: "https://chatanywhere.tech",
hasFree: true,
freeNote:
"Personal, educational or research use only: public documentation cites 10,000 points/day and 200 requests/day per IP/key; do not use for commercial traffic.",
apiHint:
"Create a ChatAnywhere key linked to GitHub, then use https://api.chatanywhere.org/v1 outside China. Review the non-commercial terms before enabling it.",
},
helyxai: {
id: "helyxai",
alias: "helyxai",
name: "Helyx AI",
icon: "hub",
color: "#7C3AED",
textIcon: "HX",
passthroughModels: true,
website: "https://helyxai.space",
hasFree: true,
freeNote:
"Operational Free plan documents 100,000 tokens/day; the site's separate 2M+ marketing claim conflicts and is not treated as a quota guarantee.",
apiHint:
"Create a Helyx AI Bearer key, then use https://helyxai.space/v1 as the OpenAI-compatible base URL. Review terms and data retention first.",
},
auriko: {
id: "auriko",
alias: "auriko",
name: "Auriko",
icon: "hub",
color: "#0891B2",
textIcon: "AU",
passthroughModels: true,
website: "https://www.auriko.ai",
hasFree: true,
freeNote:
"Free plan publishes 1,000 Platform RPM and 10,000 BYOK RPM. Platform inference still passes through provider cost; this is not a free-token pool or unlimited free inference.",
apiHint:
"Create an Auriko key with the ak_ prefix, then use https://api.auriko.ai/v1 as the OpenAI-compatible base URL. BYOK and platform credits have different cost semantics.",
},
"poixe-ai": {
id: "poixe-ai",
alias: "poixe-ai",
name: "Poixe AI",
icon: "router",
color: "#EA580C",
textIcon: "PX",
passthroughModels: true,
website: "https://poixe.com",
hasFree: true,
freeNote:
"Current public free limits are small and model-group specific: 2 RPM/5 RPD for large-cup models and 20 RPM/50 RPD for small-cup models.",
apiHint:
"Create a Poixe Bearer key, then use https://api.poixe.com/v1 as the OpenAI-compatible base URL. Treat free model provenance and regional availability as experimental.",
},
"naga-ai": {
id: "naga-ai",
alias: "naga-ai",
name: "Naga AI",
icon: "router",
color: "#059669",
textIcon: "NA",
passthroughModels: true,
website: "https://naga.ac",
hasFree: true,
freeNote:
"Models marked :free are publicly listed, but no numeric quota is confirmed. Naga's policy warns that free-tier prompts and outputs may be collected or used for training.",
apiHint:
"Create a Naga AI Bearer key, then use https://api.naga.ac/v1 as the OpenAI-compatible base URL. Never send sensitive data to the free tier without accepting its training policy.",
},
"chat-oripe": {
id: "chat-oripe",
alias: "chat-oripe",
name: "Chat Oripe",
icon: "router",
color: "#64748B",
textIcon: "CO",
passthroughModels: true,
website: "https://api.oriper.com",
hasFree: true,
freeNote:
"Official metadata advertises 2M tokens/month, but the public site and documentation were blocked during audit; treat the quota and brand mapping as unconfirmed.",
apiHint:
"Use https://api.oriper.com/v1 only after confirming the provider's current documentation, terms and key issuance. No quota is guaranteed by this catalog.",
},
freeinference: {
id: "freeinference",
alias: "freeinference",
name: "FreeInference",
icon: "science",
color: "#8B5CF6",
textIcon: "FI",
passthroughModels: true,
website: "https://freeinference.org",
hasFree: true,
freeNote:
"Free research access without a card; non-Harvard applicants require manual approval and no numeric quota is publicly guaranteed.",
apiHint:
"Apply for a FreeInference key, then use https://freeinference.org/v1 as the OpenAI-compatible base URL. Terms allow prompt/response logging and possible publication of anonymized research data; never send sensitive or production data.",
},
"free-ai": {
id: "free-ai",
alias: "free-ai",
name: "Free.ai",
icon: "hub",
color: "#16A34A",
textIcon: "FA",
passthroughModels: true,
website: "https://free.ai",
hasFree: true,
freeNote:
"30,000 tokens/day cover self-hosted models after email verification. Usage beyond the pool can bill at raw cost, and premium external models are paid.",
apiHint:
"Create an sk-free- key, then use the nonstandard but OpenAI-shaped https://api.free.ai/v1/chat/ endpoint. Select a self-hosted zero-price model to stay within the free pool.",
},
dgrid: {
id: "dgrid",
alias: "dgrid",

View File

@@ -32,6 +32,21 @@ export const APIKEY_PROVIDERS_INFERENCE = {
freeNote:
"Free credits on signup for OpenAI-compatible inference across LLMs, embeddings, and reasoning models",
},
poolside: {
id: "poolside",
alias: "poolside",
name: "Poolside",
icon: "memory",
color: "#111827",
textIcon: "PS",
passthroughModels: true,
website: "https://poolside.ai",
hasFree: true,
freeNote:
"Laguna S 2.1 and XS 2.1 are free during Preview; no public numeric quota is published.",
apiHint:
"Create a free developer API key, then use https://inference.poolside.ai/v1 as the OpenAI-compatible base URL.",
},
fireworks: {
id: "fireworks",
alias: "fireworks",

View File

@@ -0,0 +1,55 @@
import assert from "node:assert/strict";
import test from "node:test";
const { REGISTRY } = await import("../../open-sse/config/providerRegistry.ts");
const { DefaultExecutor, getExecutor } = await import("../../open-sse/executors/index.ts");
const { PROVIDER_ENDPOINTS } = await import("../../src/shared/constants/config.ts");
const { isValidModel } = await import("../../src/shared/constants/models.ts");
const { AGGREGATOR_PROVIDER_IDS } = await import("../../src/shared/constants/providers.ts");
const { APIKEY_PROVIDERS } = await import("../../src/shared/constants/providers/apikey/index.ts");
const providers = [
["zylo-api", "zylo", "https://api.zyloai.net/v1/chat/completions"],
["unorouter", "unorouter", "https://api.unorouter.com/v1/chat/completions"],
["poolside", "poolside", "https://inference.poolside.ai/v1/chat/completions"],
["fastrouter", "fastrouter", "https://api.fastrouter.ai/api/v1/chat/completions"],
["anyapi", "anyapi", "https://api.anyapi.ai/v1/chat/completions"],
["electronhub", "electronhub", "https://api.electronhub.ai/v1/chat/completions"],
["llmgateway", "llmgateway", "https://api.llmgateway.io/v1/chat/completions"],
["llm-kiwi", "llmkiwi", "https://api.llm.kiwi/v1/chat/completions"],
] as const;
for (const [id, alias, endpoint] of providers) {
test(`${id} is wired through registry, metadata, endpoint and default executor`, () => {
const registry = REGISTRY[id];
const metadata = APIKEY_PROVIDERS[id];
assert.ok(registry);
assert.ok(metadata);
assert.equal(registry.id, id);
assert.equal(registry.alias, alias);
assert.equal(registry.baseUrl, endpoint);
assert.equal(PROVIDER_ENDPOINTS[id], endpoint);
assert.equal(metadata.id, id);
assert.equal(metadata.alias, alias);
assert.equal(metadata.hasFree, true);
assert.equal(metadata.passthroughModels, true);
assert.ok(typeof metadata.freeNote === "string" && metadata.freeNote.length > 0);
assert.ok(getExecutor(id) instanceof DefaultExecutor);
assert.equal(isValidModel(id, "future/live-catalog-model"), true);
assert.equal(isValidModel(alias, "future/live-catalog-model"), true);
});
}
test("gateway providers are classified as aggregators while direct Poolside is not", () => {
const gatewayIds = providers.map(([id]) => id).filter((id) => id !== "poolside");
for (const id of gatewayIds) assert.equal(AGGREGATOR_PROVIDER_IDS.has(id), true);
assert.equal(AGGREGATOR_PROVIDER_IDS.has("poolside"), false);
});
test("LLM.Kiwi statically exposes only the confirmed Free plan models", () => {
assert.deepEqual(REGISTRY["llm-kiwi"].models, [
{ id: "auto", name: "Auto" },
{ id: "hrLLM", name: "hrLLM" },
]);
});

View File

@@ -0,0 +1,55 @@
import assert from "node:assert/strict";
import test from "node:test";
import { poolsideProvider } from "../../open-sse/config/providers/registry/poolside/index.ts";
import { unorouterProvider } from "../../open-sse/config/providers/registry/unorouter/index.ts";
import { zyloApiProvider } from "../../open-sse/config/providers/registry/zylo-api/index.ts";
import type { RegistryEntry } from "../../open-sse/config/providers/shared.ts";
const providers: Array<{
entry: RegistryEntry;
id: string;
alias: string;
chatUrl: string;
modelsUrl: string;
}> = [
{
entry: zyloApiProvider,
id: "zylo-api",
alias: "zylo",
chatUrl: "https://api.zyloai.net/v1/chat/completions",
modelsUrl: "https://api.zyloai.net/v1/models",
},
{
entry: unorouterProvider,
id: "unorouter",
alias: "unorouter",
chatUrl: "https://api.unorouter.com/v1/chat/completions",
modelsUrl: "https://api.unorouter.com/v1/models",
},
{
entry: poolsideProvider,
id: "poolside",
alias: "poolside",
chatUrl: "https://inference.poolside.ai/v1/chat/completions",
modelsUrl: "https://inference.poolside.ai/v1/models",
},
];
for (const { entry, id, alias, chatUrl, modelsUrl } of providers) {
test(`${id} uses the standard OpenAI-compatible API-key registry shape`, () => {
assert.equal(entry.id, id);
assert.equal(entry.alias, alias);
assert.equal(entry.format, "openai");
assert.equal(entry.executor, "default");
assert.equal(entry.authType, "apikey");
assert.equal(entry.authHeader, "bearer");
assert.equal(entry.baseUrl, chatUrl);
assert.equal(entry.modelsUrl, modelsUrl);
assert.equal(entry.passthroughModels, true);
});
test(`${id} relies on its live catalog without invented static model ids`, () => {
assert.deepEqual(entry.models, []);
});
}

View File

@@ -0,0 +1,51 @@
import assert from "node:assert/strict";
import test from "node:test";
import { literouterProvider } from "../../open-sse/config/providers/registry/literouter/index.ts";
import { meganovaAiProvider } from "../../open-sse/config/providers/registry/meganova-ai/index.ts";
import { mnnAiProvider } from "../../open-sse/config/providers/registry/mnn-ai/index.ts";
import type { RegistryEntry } from "../../open-sse/config/providers/shared.ts";
const providers: Array<{
entry: RegistryEntry;
id: string;
chatUrl: string;
modelsUrl: string;
}> = [
{
entry: literouterProvider,
id: "literouter",
chatUrl: "https://api.literouter.com/v1/chat/completions",
modelsUrl: "https://api.literouter.com/v1/models",
},
{
entry: mnnAiProvider,
id: "mnn-ai",
chatUrl: "https://api.mnnai.ru/v1/chat/completions",
modelsUrl: "https://api.mnnai.ru/v1/models",
},
{
entry: meganovaAiProvider,
id: "meganova-ai",
chatUrl: "https://api.meganova.ai/v1/chat/completions",
modelsUrl: "https://api.meganova.ai/v1/models",
},
];
for (const { entry, id, chatUrl, modelsUrl } of providers) {
test(`${id} uses an OpenAI-compatible Bearer registry entry`, () => {
assert.equal(entry.id, id);
assert.equal(entry.alias, id);
assert.equal(entry.format, "openai");
assert.equal(entry.executor, "default");
assert.equal(entry.authType, "apikey");
assert.equal(entry.authHeader, "bearer");
assert.equal(entry.baseUrl, chatUrl);
assert.equal(entry.modelsUrl, modelsUrl);
assert.equal(entry.passthroughModels, true);
});
test(`${id} leaves model discovery to the live upstream catalog`, () => {
assert.deepEqual(entry.models, []);
});
}

View File

@@ -0,0 +1,60 @@
import assert from "node:assert/strict";
import test from "node:test";
import { mixlayerProvider } from "../../open-sse/config/providers/registry/mixlayer/index.ts";
import { spekaProvider } from "../../open-sse/config/providers/registry/speka/index.ts";
import { tokenreplyProvider } from "../../open-sse/config/providers/registry/tokenreply/index.ts";
import type { RegistryEntry } from "../../open-sse/config/providers/shared.ts";
const providers: Array<{
entry: RegistryEntry;
id: string;
chatUrl: string;
modelsUrl: string;
}> = [
{
entry: mixlayerProvider,
id: "mixlayer",
chatUrl: "https://models.mixlayer.ai/v1/chat/completions",
modelsUrl: "https://models.mixlayer.ai/v1/models",
},
{
entry: spekaProvider,
id: "speka",
chatUrl: "https://speka.me/v1/chat/completions",
modelsUrl: "https://speka.me/v1/models",
},
{
entry: tokenreplyProvider,
id: "tokenreply",
chatUrl: "https://api.tokenreply.com/v1/chat/completions",
modelsUrl: "https://api.tokenreply.com/v1/models",
},
];
test("Wave 2-B providers expose OpenAI-compatible Bearer registries", () => {
for (const { entry, id, chatUrl, modelsUrl } of providers) {
assert.equal(entry.id, id);
assert.equal(entry.alias, id);
assert.equal(entry.format, "openai");
assert.equal(entry.executor, "default");
assert.equal(entry.authType, "apikey");
assert.equal(entry.authHeader, "bearer");
assert.equal(entry.baseUrl, chatUrl);
assert.equal(entry.modelsUrl, modelsUrl);
assert.equal(entry.passthroughModels, true);
assert.ok(Array.isArray(entry.models));
}
});
test("Mixlayer seeds only its documented free model", () => {
assert.deepEqual(
mixlayerProvider.models.map((model) => model.id),
["qwen/qwen3.5-4b-free"]
);
});
test("Speka and TokenReply rely on live model catalogs without invented models", () => {
assert.deepEqual(spekaProvider.models, []);
assert.deepEqual(tokenreplyProvider.models, []);
});

View File

@@ -0,0 +1,58 @@
import assert from "node:assert/strict";
import test from "node:test";
import { cloudcodeOneProvider } from "../../open-sse/config/providers/registry/cloudcode-one/index.ts";
import { dxntProvider } from "../../open-sse/config/providers/registry/dxnt/index.ts";
import { yoloAutoProvider } from "../../open-sse/config/providers/registry/yolo-auto/index.ts";
import type { RegistryEntry } from "../../open-sse/config/providers/shared.ts";
const providers: Array<{
entry: RegistryEntry;
id: string;
chatUrl: string;
modelsUrl: string;
modelIds: string[];
}> = [
{
entry: yoloAutoProvider,
id: "yolo-auto",
chatUrl: "https://yolo-auto.com/v1/chat/completions",
modelsUrl: "https://yolo-auto.com/v1/models",
modelIds: ["qwen3.6-35b-a3b"],
},
{
entry: dxntProvider,
id: "dxnt",
chatUrl: "https://www.dxnt.com/v1/chat/completions",
modelsUrl: "https://www.dxnt.com/v1/models",
modelIds: [],
},
{
entry: cloudcodeOneProvider,
id: "cloudcode-one",
chatUrl: "https://api.cloudcode.one/v1/chat/completions",
modelsUrl: "https://api.cloudcode.one/v1/models",
modelIds: ["glm-4.7-flash", "glm-4.6v-flash"],
},
];
for (const { entry, id, chatUrl, modelsUrl, modelIds } of providers) {
test(`${id} uses the standard OpenAI-compatible API-key registry shape`, () => {
assert.equal(entry.id, id);
assert.equal(entry.alias, id);
assert.equal(entry.format, "openai");
assert.equal(entry.executor, "default");
assert.equal(entry.authType, "apikey");
assert.equal(entry.authHeader, "bearer");
assert.equal(entry.baseUrl, chatUrl);
assert.equal(entry.modelsUrl, modelsUrl);
assert.equal(entry.passthroughModels, true);
});
test(`${id} seeds only the audited model identifiers`, () => {
assert.deepEqual(
(entry.models ?? []).map((model) => model.id),
modelIds
);
});
}

View File

@@ -0,0 +1,60 @@
import assert from "node:assert/strict";
import test from "node:test";
const { REGISTRY } = await import("../../open-sse/config/providerRegistry.ts");
const { DefaultExecutor, getExecutor } = await import("../../open-sse/executors/index.ts");
const { PROVIDER_ENDPOINTS } = await import("../../src/shared/constants/config.ts");
const { isValidModel } = await import("../../src/shared/constants/models.ts");
const { AGGREGATOR_PROVIDER_IDS } = await import("../../src/shared/constants/providers.ts");
const { APIKEY_PROVIDERS } = await import("../../src/shared/constants/providers/apikey/index.ts");
const providers = [
["literouter", "https://api.literouter.com/v1/chat/completions", []],
["mnn-ai", "https://api.mnnai.ru/v1/chat/completions", []],
["meganova-ai", "https://api.meganova.ai/v1/chat/completions", []],
["mixlayer", "https://models.mixlayer.ai/v1/chat/completions", ["qwen/qwen3.5-4b-free"]],
["speka", "https://speka.me/v1/chat/completions", []],
["tokenreply", "https://api.tokenreply.com/v1/chat/completions", []],
["yolo-auto", "https://yolo-auto.com/v1/chat/completions", ["qwen3.6-35b-a3b"]],
["dxnt", "https://www.dxnt.com/v1/chat/completions", []],
[
"cloudcode-one",
"https://api.cloudcode.one/v1/chat/completions",
["glm-4.7-flash", "glm-4.6v-flash"],
],
] as const;
for (const [id, endpoint, modelIds] of providers) {
test(`${id} is wired through registry, metadata, endpoint and default executor`, () => {
const registry = REGISTRY[id];
const metadata = APIKEY_PROVIDERS[id];
assert.ok(registry);
assert.ok(metadata);
assert.equal(registry.id, id);
assert.equal(registry.alias, id);
assert.equal(registry.baseUrl, endpoint);
assert.equal(PROVIDER_ENDPOINTS[id], endpoint);
assert.equal(metadata.id, id);
assert.equal(metadata.alias, id);
assert.equal(metadata.hasFree, true);
assert.equal(metadata.passthroughModels, true);
assert.ok(typeof metadata.freeNote === "string" && metadata.freeNote.length > 0);
assert.equal(AGGREGATOR_PROVIDER_IDS.has(id), true);
assert.ok(getExecutor(id) instanceof DefaultExecutor);
assert.equal(isValidModel(id, "future/live-catalog-model"), true);
assert.deepEqual(
registry.models.map((model) => model.id),
modelIds
);
});
}
test("risk-sensitive metadata preserves the audited quota qualifications", () => {
assert.match(APIKEY_PROVIDERS["mnn-ai"].apiHint ?? "", /jurisdiction.*privacy/i);
assert.match(APIKEY_PROVIDERS["meganova-ai"].freeNote ?? "", /per-model quotas/i);
assert.match(APIKEY_PROVIDERS["meganova-ai"].freeNote ?? "", /paid overage/i);
assert.match(APIKEY_PROVIDERS.tokenreply.freeNote ?? "", /no fixed global free quota/i);
assert.match(APIKEY_PROVIDERS["yolo-auto"].freeNote ?? "", /no numeric daily quota/i);
assert.match(APIKEY_PROVIDERS["cloudcode-one"].freeNote ?? "", /credit or a coupon/i);
});

View File

@@ -0,0 +1,48 @@
import assert from "node:assert/strict";
import test from "node:test";
import { chatanywhereProvider } from "../../open-sse/config/providers/registry/chatanywhere/index.ts";
import { ofoxaiProvider } from "../../open-sse/config/providers/registry/ofoxai/index.ts";
import { zerolimitaiProvider } from "../../open-sse/config/providers/registry/zerolimitai/index.ts";
import type { RegistryEntry } from "../../open-sse/config/providers/shared.ts";
const providers: Array<{
entry: RegistryEntry;
id: string;
chatUrl: string;
modelsUrl: string;
}> = [
{
entry: ofoxaiProvider,
id: "ofoxai",
chatUrl: "https://api.ofox.ai/v1/chat/completions",
modelsUrl: "https://api.ofox.ai/v1/models",
},
{
entry: zerolimitaiProvider,
id: "zerolimitai",
chatUrl: "https://www.zerolimitai.com/api/v1/chat/completions",
modelsUrl: "https://www.zerolimitai.com/api/v1/models",
},
{
entry: chatanywhereProvider,
id: "chatanywhere",
chatUrl: "https://api.chatanywhere.org/v1/chat/completions",
modelsUrl: "https://api.chatanywhere.org/v1/models",
},
];
test("Wave 3-A providers expose OpenAI-compatible Bearer registries", () => {
for (const { entry, id, chatUrl, modelsUrl } of providers) {
assert.equal(entry.id, id);
assert.equal(entry.alias, id);
assert.equal(entry.format, "openai");
assert.equal(entry.executor, "default");
assert.equal(entry.authType, "apikey");
assert.equal(entry.authHeader, "bearer");
assert.equal(entry.baseUrl, chatUrl);
assert.equal(entry.modelsUrl, modelsUrl);
assert.equal(entry.passthroughModels, true);
assert.deepEqual(entry.models, []);
}
});

View File

@@ -0,0 +1,53 @@
import assert from "node:assert/strict";
import test from "node:test";
import { aurikoProvider } from "../../open-sse/config/providers/registry/auriko/index.ts";
import { helyxaiProvider } from "../../open-sse/config/providers/registry/helyxai/index.ts";
import { poixeAiProvider } from "../../open-sse/config/providers/registry/poixe-ai/index.ts";
import type { RegistryEntry } from "../../open-sse/config/providers/shared.ts";
const providers: Array<{
entry: RegistryEntry;
id: string;
chatUrl: string;
modelsUrl: string;
}> = [
{
entry: helyxaiProvider,
id: "helyxai",
chatUrl: "https://helyxai.space/v1/chat/completions",
modelsUrl: "https://helyxai.space/v1/models",
},
{
entry: aurikoProvider,
id: "auriko",
chatUrl: "https://api.auriko.ai/v1/chat/completions",
modelsUrl: "https://api.auriko.ai/v1/models",
},
{
entry: poixeAiProvider,
id: "poixe-ai",
chatUrl: "https://api.poixe.com/v1/chat/completions",
modelsUrl: "https://api.poixe.com/v1/models",
},
];
test("Wave 3-B providers expose OpenAI-compatible Bearer registries", () => {
for (const { entry, id, chatUrl, modelsUrl } of providers) {
assert.equal(entry.id, id);
assert.equal(entry.alias, id);
assert.equal(entry.format, "openai");
assert.equal(entry.executor, "default");
assert.equal(entry.authType, "apikey");
assert.equal(entry.authHeader, "bearer");
assert.equal(entry.baseUrl, chatUrl);
assert.equal(entry.modelsUrl, modelsUrl);
assert.equal(entry.passthroughModels, true);
}
});
test("Wave 3-B providers rely on live catalogs without invented models", () => {
for (const { entry } of providers) {
assert.deepEqual(entry.models, []);
}
});

View File

@@ -0,0 +1,41 @@
import assert from "node:assert/strict";
import test from "node:test";
import { chatOripeProvider } from "../../open-sse/config/providers/registry/chat-oripe/index.ts";
import { nagaAiProvider } from "../../open-sse/config/providers/registry/naga-ai/index.ts";
import type { RegistryEntry } from "../../open-sse/config/providers/shared.ts";
const providers: Array<{
entry: RegistryEntry;
id: string;
chatUrl: string;
modelsUrl: string;
}> = [
{
entry: nagaAiProvider,
id: "naga-ai",
chatUrl: "https://api.naga.ac/v1/chat/completions",
modelsUrl: "https://api.naga.ac/v1/models",
},
{
entry: chatOripeProvider,
id: "chat-oripe",
chatUrl: "https://api.oriper.com/v1/chat/completions",
modelsUrl: "https://api.oriper.com/v1/models",
},
];
test("Wave 3-C providers expose OpenAI-compatible Bearer registries", () => {
for (const { entry, id, chatUrl, modelsUrl } of providers) {
assert.equal(entry.id, id);
assert.equal(entry.alias, id);
assert.equal(entry.format, "openai");
assert.equal(entry.executor, "default");
assert.equal(entry.authType, "apikey");
assert.equal(entry.authHeader, "bearer");
assert.equal(entry.baseUrl, chatUrl);
assert.equal(entry.modelsUrl, modelsUrl);
assert.equal(entry.passthroughModels, true);
assert.deepEqual(entry.models, []);
}
});

View File

@@ -0,0 +1,53 @@
import assert from "node:assert/strict";
import test from "node:test";
const { REGISTRY } = await import("../../open-sse/config/providerRegistry.ts");
const { DefaultExecutor, getExecutor } = await import("../../open-sse/executors/index.ts");
const { PROVIDER_ENDPOINTS } = await import("../../src/shared/constants/config.ts");
const { isValidModel } = await import("../../src/shared/constants/models.ts");
const { AGGREGATOR_PROVIDER_IDS } = await import("../../src/shared/constants/providers.ts");
const { APIKEY_PROVIDERS } = await import("../../src/shared/constants/providers/apikey/index.ts");
const providers = [
["ofoxai", "https://api.ofox.ai/v1/chat/completions"],
["zerolimitai", "https://www.zerolimitai.com/api/v1/chat/completions"],
["chatanywhere", "https://api.chatanywhere.org/v1/chat/completions"],
["helyxai", "https://helyxai.space/v1/chat/completions"],
["auriko", "https://api.auriko.ai/v1/chat/completions"],
["poixe-ai", "https://api.poixe.com/v1/chat/completions"],
["naga-ai", "https://api.naga.ac/v1/chat/completions"],
["chat-oripe", "https://api.oriper.com/v1/chat/completions"],
] as const;
for (const [id, endpoint] of providers) {
test(`${id} is wired through registry, metadata, endpoint and default executor`, () => {
const registry = REGISTRY[id];
const metadata = APIKEY_PROVIDERS[id];
assert.ok(registry);
assert.ok(metadata);
assert.equal(registry.id, id);
assert.equal(registry.alias, id);
assert.equal(registry.baseUrl, endpoint);
assert.equal(PROVIDER_ENDPOINTS[id], endpoint);
assert.equal(metadata.id, id);
assert.equal(metadata.alias, id);
assert.equal(metadata.hasFree, true);
assert.equal(metadata.passthroughModels, true);
assert.ok(typeof metadata.freeNote === "string" && metadata.freeNote.length > 0);
assert.equal(AGGREGATOR_PROVIDER_IDS.has(id), true);
assert.ok(getExecutor(id) instanceof DefaultExecutor);
assert.equal(isValidModel(id, "future/live-catalog-model"), true);
assert.deepEqual(registry.models, []);
});
}
test("Wave 3 metadata preserves the audited legal, quota and privacy warnings", () => {
assert.match(APIKEY_PROVIDERS.chatanywhere.freeNote ?? "", /commercial traffic/i);
assert.match(APIKEY_PROVIDERS.zerolimitai.freeNote ?? "", /3 and 7 days/i);
assert.match(APIKEY_PROVIDERS.helyxai.freeNote ?? "", /100,000 tokens\/day/i);
assert.match(APIKEY_PROVIDERS.auriko.freeNote ?? "", /not a free-token pool/i);
assert.match(APIKEY_PROVIDERS["poixe-ai"].freeNote ?? "", /2 RPM\/5 RPD/i);
assert.match(APIKEY_PROVIDERS["naga-ai"].freeNote ?? "", /training/i);
assert.match(APIKEY_PROVIDERS["chat-oripe"].freeNote ?? "", /unconfirmed/i);
});

View File

@@ -0,0 +1,27 @@
import assert from "node:assert/strict";
import test from "node:test";
import { freeinferenceProvider } from "../../open-sse/config/providers/registry/freeinference/index.ts";
import {
DefaultExecutor,
getExecutor,
hasSpecializedExecutor,
} from "../../open-sse/executors/index.ts";
test("FreeInference exposes an OpenAI-compatible Bearer registry", () => {
assert.equal(freeinferenceProvider.id, "freeinference");
assert.equal(freeinferenceProvider.alias, "freeinference");
assert.equal(freeinferenceProvider.format, "openai");
assert.equal(freeinferenceProvider.executor, "default");
assert.equal(freeinferenceProvider.authType, "apikey");
assert.equal(freeinferenceProvider.authHeader, "bearer");
assert.equal(freeinferenceProvider.baseUrl, "https://freeinference.org/v1/chat/completions");
assert.equal(freeinferenceProvider.modelsUrl, "https://freeinference.org/v1/models");
assert.deepEqual(freeinferenceProvider.models, []);
assert.equal(freeinferenceProvider.passthroughModels, true);
});
test("FreeInference uses DefaultExecutor without specialized behavior", () => {
assert.equal(hasSpecializedExecutor("freeinference"), false);
assert.ok(getExecutor("freeinference") instanceof DefaultExecutor);
});

View File

@@ -0,0 +1,27 @@
import assert from "node:assert/strict";
import test from "node:test";
import { freeAiProvider } from "../../open-sse/config/providers/registry/free-ai/index.ts";
import {
DefaultExecutor,
getExecutor,
hasSpecializedExecutor,
} from "../../open-sse/executors/index.ts";
test("Free.ai exposes its exact OpenAI-compatible endpoint and live catalog", () => {
assert.equal(freeAiProvider.id, "free-ai");
assert.equal(freeAiProvider.alias, "free-ai");
assert.equal(freeAiProvider.format, "openai");
assert.equal(freeAiProvider.executor, "default");
assert.equal(freeAiProvider.authType, "apikey");
assert.equal(freeAiProvider.authHeader, "bearer");
assert.equal(freeAiProvider.baseUrl, "https://api.free.ai/v1/chat/");
assert.equal(freeAiProvider.modelsUrl, "https://api.free.ai/v1/models");
assert.deepEqual(freeAiProvider.models, []);
assert.equal(freeAiProvider.passthroughModels, true);
});
test("Free.ai uses DefaultExecutor without a specialized executor", () => {
assert.ok(getExecutor("free-ai") instanceof DefaultExecutor);
assert.equal(hasSpecializedExecutor("free-ai"), false);
});

View File

@@ -0,0 +1,64 @@
import assert from "node:assert/strict";
import test from "node:test";
import { deriveConfigFromRegistryModelsUrl } from "../../src/app/api/providers/[id]/models/discoveryConfig.ts";
const { REGISTRY } = await import("../../open-sse/config/providerRegistry.ts");
const { DefaultExecutor, getExecutor, hasSpecializedExecutor } =
await import("../../open-sse/executors/index.ts");
const { PROVIDER_ENDPOINTS } = await import("../../src/shared/constants/config.ts");
const { isValidModel } = await import("../../src/shared/constants/models.ts");
const { AGGREGATOR_PROVIDER_IDS } = await import("../../src/shared/constants/providers.ts");
const { APIKEY_PROVIDERS } = await import("../../src/shared/constants/providers/apikey/index.ts");
const providers = [
["freeinference", "https://freeinference.org/v1/chat/completions"],
["free-ai", "https://api.free.ai/v1/chat/"],
] as const;
for (const [id, endpoint] of providers) {
test(`${id} is fully wired without a specialized executor`, () => {
const registry = REGISTRY[id];
const metadata = APIKEY_PROVIDERS[id];
assert.ok(registry);
assert.ok(metadata);
assert.equal(registry.id, id);
assert.equal(registry.alias, id);
assert.equal(registry.baseUrl, endpoint);
assert.equal(PROVIDER_ENDPOINTS[id], endpoint);
assert.equal(metadata.id, id);
assert.equal(metadata.alias, id);
assert.equal(metadata.hasFree, true);
assert.equal(metadata.passthroughModels, true);
assert.equal(AGGREGATOR_PROVIDER_IDS.has(id), true);
assert.equal(hasSpecializedExecutor(id), false);
const executor = getExecutor(id);
assert.ok(executor instanceof DefaultExecutor);
assert.equal(executor.buildUrl("live-model", false), endpoint);
assert.equal(isValidModel(id, "future/live-catalog-model"), true);
assert.deepEqual(registry.models, []);
});
}
test("Wave 4 model discovery accepts both public catalog response envelopes", () => {
const freeInferenceDiscovery = deriveConfigFromRegistryModelsUrl("freeinference");
const freeAiDiscovery = deriveConfigFromRegistryModelsUrl("free-ai");
assert.ok(freeInferenceDiscovery);
assert.ok(freeAiDiscovery);
assert.deepEqual(freeInferenceDiscovery.parseResponse({ data: [{ id: "glm-5.1" }] }), [
{ id: "glm-5.1" },
]);
assert.deepEqual(freeAiDiscovery.parseResponse({ models: [{ id: "qwen7b" }] }), [
{ id: "qwen7b" },
]);
});
test("Wave 4 metadata preserves approval, logging and overage warnings", () => {
assert.match(APIKEY_PROVIDERS.freeinference.freeNote ?? "", /manual approval/i);
assert.match(APIKEY_PROVIDERS.freeinference.apiHint ?? "", /logging/i);
assert.match(APIKEY_PROVIDERS["free-ai"].freeNote ?? "", /30,000 tokens\/day/i);
assert.match(APIKEY_PROVIDERS["free-ai"].freeNote ?? "", /premium external models are paid/i);
assert.match(APIKEY_PROVIDERS["free-ai"].apiHint ?? "", /\/v1\/chat\//i);
});

View File

@@ -0,0 +1,15 @@
import assert from "node:assert/strict";
import test from "node:test";
const { isValidModel } = await import("../../src/shared/constants/models.ts");
test("passthrough providers accept live model ids through both provider id and alias", () => {
for (const [id, alias] of [
["zylo-api", "zylo"],
["llm-kiwi", "llmkiwi"],
["freetheai", "fta"],
] as const) {
assert.equal(isValidModel(id, "future/live-catalog-model"), true);
assert.equal(isValidModel(alias, "future/live-catalog-model"), true);
}
});