mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-11 17:52:31 +03:00
Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
98962b0b30
commit
31fce91fbd
1
changelog.d/features/6674-gpt4free-batch-3-providers.md
Normal file
1
changelog.d/features/6674-gpt4free-batch-3-providers.md
Normal file
@@ -0,0 +1 @@
|
||||
- **feat(providers):** add Naga.ac and ChatAnywhere aggregator gateway providers (#6674 — thanks @chirag127)
|
||||
@@ -229,6 +229,8 @@ import { hcnsecProvider } from "./registry/hcnsec/index.ts";
|
||||
import { promptqlProvider } from "./registry/promptql/index.ts";
|
||||
import { hyperagentProvider } from "./registry/hyperagent/index.ts";
|
||||
import { muse_codeProvider } from "./registry/muse-code/index.ts";
|
||||
import { naga_acProvider } from "./registry/naga-ac/index.ts";
|
||||
import { chatanywhereProvider } from "./registry/chatanywhere/index.ts";
|
||||
|
||||
export const REGISTRY: Record<string, RegistryEntry> = {
|
||||
aimlapi: aimlapiProvider,
|
||||
@@ -460,4 +462,6 @@ export const REGISTRY: Record<string, RegistryEntry> = {
|
||||
hyperagent: hyperagentProvider,
|
||||
"muse-code": muse_codeProvider,
|
||||
unorouter: unorouterProvider,
|
||||
"naga-ac": naga_acProvider,
|
||||
chatanywhere: chatanywhereProvider,
|
||||
};
|
||||
|
||||
17
open-sse/config/providers/registry/chatanywhere/index.ts
Normal file
17
open-sse/config/providers/registry/chatanywhere/index.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import type { RegistryEntry } from "../../shared.ts";
|
||||
|
||||
// ChatAnywhere (api.chatanywhere.tech) — OpenAI-compatible gateway from the
|
||||
// chatanywhere/GPT_API_free project (~38.7k GitHub stars). Requires GitHub-account-
|
||||
// gated API key. Free tier is for personal non-commercial use only.
|
||||
export const chatanywhereProvider: RegistryEntry = {
|
||||
id: "chatanywhere",
|
||||
alias: "chtany",
|
||||
format: "openai",
|
||||
executor: "default",
|
||||
baseUrl: "https://api.chatanywhere.tech/v1/chat/completions",
|
||||
modelsUrl: "https://api.chatanywhere.tech/v1/models",
|
||||
authType: "apikey",
|
||||
authHeader: "bearer",
|
||||
passthroughModels: true,
|
||||
models: [],
|
||||
};
|
||||
17
open-sse/config/providers/registry/naga-ac/index.ts
Normal file
17
open-sse/config/providers/registry/naga-ac/index.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import type { RegistryEntry } from "../../shared.ts";
|
||||
|
||||
// Naga.ac — OpenAI-compatible aggregator gateway with free models.
|
||||
// See https://docs.naga.ac for API reference.
|
||||
// Free models accept an optional API key; authenticated users get higher rate limits.
|
||||
export const naga_acProvider: RegistryEntry = {
|
||||
id: "naga-ac",
|
||||
alias: "naga",
|
||||
format: "openai",
|
||||
executor: "default",
|
||||
baseUrl: "https://api.naga.ac/v1/chat/completions",
|
||||
modelsUrl: "https://api.naga.ac/v1/models",
|
||||
authType: "optional",
|
||||
authHeader: "bearer",
|
||||
passthroughModels: true,
|
||||
models: [],
|
||||
};
|
||||
@@ -93,6 +93,8 @@ export const AGGREGATOR_PROVIDER_IDS = new Set([
|
||||
"g4f-pollinations",
|
||||
"g4f-ollama",
|
||||
"g4f-nvidia",
|
||||
"naga-ac",
|
||||
"chatanywhere",
|
||||
]);
|
||||
|
||||
export const ENTERPRISE_CLOUD_PROVIDER_IDS = new Set([
|
||||
@@ -196,6 +198,7 @@ const EXPLICIT_OPTIONAL_APIKEY_PROVIDER_IDS = new Set([
|
||||
"huggingchat",
|
||||
"gitlawb",
|
||||
"gitlawb-gmi",
|
||||
"naga-ac",
|
||||
]);
|
||||
|
||||
export function providerAllowsOptionalApiKey(providerId: unknown): boolean {
|
||||
|
||||
@@ -835,5 +835,35 @@ export const APIKEY_PROVIDERS_GATEWAYS = {
|
||||
authHint: "Get your Regolo API key from regolo.ai, then paste it here as a Bearer token.",
|
||||
apiHint:
|
||||
"OpenAI-compatible endpoint at https://api.regolo.ai/v1 with dynamic model discovery (19 models).",
|
||||
"naga-ac": {
|
||||
id: "naga-ac",
|
||||
alias: "naga",
|
||||
name: "Naga.ac",
|
||||
icon: "bolt",
|
||||
color: "#7C3AED",
|
||||
textIcon: "NA",
|
||||
website: "https://naga.ac",
|
||||
docsUrl: "https://docs.naga.ac",
|
||||
hasFree: true,
|
||||
freeNote:
|
||||
"Free models include Nemotron 3 Ultra (free) and Llama 3.3 70B Instruct (Free). Paid models require credits. Google/GitHub/Discord signup.",
|
||||
passthroughModels: true,
|
||||
authHint:
|
||||
"Get API key at naga.ac — Google/GitHub/Discord signup available.",
|
||||
},
|
||||
chatanywhere: {
|
||||
id: "chatanywhere",
|
||||
alias: "chtany",
|
||||
name: "ChatAnywhere",
|
||||
icon: "chat",
|
||||
color: "#10B981",
|
||||
textIcon: "CA",
|
||||
website: "https://api.chatanywhere.tech",
|
||||
hasFree: true,
|
||||
freeNote:
|
||||
"Free tier: 5 req/day for GPT-5/4o/4.1, 30/day DeepSeek, 200/day gpt-4o-mini. Personal non-commercial use only — see chatanywhere/GPT_API_free. Requires GitHub-account-gated API key.",
|
||||
passthroughModels: true,
|
||||
authHint:
|
||||
"Get free API key at api.chatanywhere.tech — requires GitHub account signup.",
|
||||
},
|
||||
};
|
||||
|
||||
102
tests/unit/providers-g4f-batch3.test.ts
Normal file
102
tests/unit/providers-g4f-batch3.test.ts
Normal file
@@ -0,0 +1,102 @@
|
||||
/**
|
||||
* Issue #6674 — Add Naga.ac and ChatAnywhere as gpt4free-ecosystem aggregator providers.
|
||||
*
|
||||
* Verifies both providers are wired end-to-end the same way as the other aggregator
|
||||
* gateway providers (g4f-groq, freetheai, hackclub):
|
||||
* - present in the executor REGISTRY with an OpenAI-compatible shape
|
||||
* - resolvable through getExecutor() (falls through to DefaultExecutor)
|
||||
* - listed in AGGREGATOR_PROVIDER_IDS so they show up in the aggregator category
|
||||
* - has provider metadata (name/website/free-tier note) in the apikey gateway catalog
|
||||
* - Naga.ac allows optional API key (free models); ChatAnywhere requires a key
|
||||
*/
|
||||
import test from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
|
||||
interface RegistryEntryShape {
|
||||
format?: string;
|
||||
executor?: string;
|
||||
baseUrl?: string;
|
||||
modelsUrl?: string;
|
||||
authType?: string;
|
||||
authHeader?: string;
|
||||
passthroughModels?: boolean;
|
||||
models?: unknown[];
|
||||
}
|
||||
|
||||
interface ApikeyMetaShape {
|
||||
id?: string;
|
||||
name?: string;
|
||||
website?: string;
|
||||
hasFree?: boolean;
|
||||
freeNote?: string;
|
||||
passthroughModels?: boolean;
|
||||
}
|
||||
|
||||
const { REGISTRY } = await import("../../open-sse/config/providerRegistry.ts");
|
||||
const { getExecutor, DefaultExecutor } = await import("../../open-sse/executors/index.ts");
|
||||
const { AGGREGATOR_PROVIDER_IDS, providerAllowsOptionalApiKey } = await import(
|
||||
"../../src/shared/constants/providers.ts"
|
||||
);
|
||||
const { APIKEY_PROVIDERS } = await import("../../src/shared/constants/providers/apikey/index.ts");
|
||||
|
||||
const PROVIDERS: Record<string, { id: string; authType: string; baseUrl: string; website: string }> = {
|
||||
"naga-ac": {
|
||||
id: "naga-ac",
|
||||
authType: "optional",
|
||||
baseUrl: "https://api.naga.ac/v1/chat/completions",
|
||||
website: "https://naga.ac",
|
||||
},
|
||||
chatanywhere: {
|
||||
id: "chatanywhere",
|
||||
authType: "apikey",
|
||||
baseUrl: "https://api.chatanywhere.tech/v1/chat/completions",
|
||||
website: "https://api.chatanywhere.tech",
|
||||
},
|
||||
};
|
||||
|
||||
for (const [id, info] of Object.entries(PROVIDERS)) {
|
||||
test(`#6674 ${id} is registered in the executor registry with an OpenAI-compatible shape`, () => {
|
||||
const entry = (REGISTRY as Record<string, RegistryEntryShape>)[id];
|
||||
assert.ok(entry, `${id} should be present in the executor registry`);
|
||||
assert.equal(entry.format, "openai");
|
||||
assert.equal(entry.executor, "default");
|
||||
assert.equal(entry.baseUrl, info.baseUrl);
|
||||
assert.equal(entry.authType, info.authType);
|
||||
assert.equal(entry.authHeader, "bearer");
|
||||
assert.equal(entry.passthroughModels, true);
|
||||
});
|
||||
|
||||
test(`#6674 ${id} resolves through getExecutor() as a DefaultExecutor instance`, () => {
|
||||
const executor = getExecutor(id);
|
||||
assert.ok(
|
||||
executor instanceof DefaultExecutor,
|
||||
`${id} has no custom executor — must fall through to DefaultExecutor`
|
||||
);
|
||||
});
|
||||
|
||||
test(`#6674 ${id} is classified as an aggregator/gateway provider`, () => {
|
||||
assert.ok(
|
||||
AGGREGATOR_PROVIDER_IDS.has(id),
|
||||
`${id} must be listed in AGGREGATOR_PROVIDER_IDS`
|
||||
);
|
||||
});
|
||||
|
||||
test(`#6674 ${id} has provider metadata with free-tier info`, () => {
|
||||
const meta = (APIKEY_PROVIDERS as Record<string, ApikeyMetaShape>)[id];
|
||||
assert.ok(meta, `${id} should have an APIKEY_PROVIDERS metadata entry`);
|
||||
assert.equal(meta.id, id);
|
||||
assert.equal(meta.website, info.website);
|
||||
assert.equal(meta.hasFree, true);
|
||||
assert.equal(typeof meta.freeNote, "string");
|
||||
assert.ok((meta.freeNote as string).length > 0);
|
||||
assert.equal(meta.passthroughModels, true);
|
||||
});
|
||||
}
|
||||
|
||||
test("#6674 naga-ac allows optional (no-key) API key validation", () => {
|
||||
assert.equal(providerAllowsOptionalApiKey("naga-ac"), true);
|
||||
});
|
||||
|
||||
test("#6674 chatanywhere requires an API key (not optional)", () => {
|
||||
assert.equal(providerAllowsOptionalApiKey("chatanywhere"), false);
|
||||
});
|
||||
Reference in New Issue
Block a user